#include #include #include #include #include "bmp2txt.h" static void init_map_helper(float xx, float yy, int x, int y, map_t* m); /* Sets up the entire map */ map_t* init_permutation(int width, int height) { float sx, sy; /* Source pixel */ int dx, dy; /* Destination pixel */ float rot = M_PI / 50.0;/* Rotation */ float xsc = 1.06; /* X scaling factor */ float ysc = 1.06; /* Y scaling factor */ map_t* map = malloc(sizeof(map_t)); map->w = width; map->h = height; map->e = malloc(sizeof(map_elem_t) * width * height); /* Map from destination back to source */ for (dy = 0; dy < height; dy++) for (dx = 0; dx < width; dx++) { sx = width / 2.0 + (-cos(-rot) * (width / 2.0 - dx) + sin(-rot) * (height / 2.0 - dy)) / xsc; sy = height / 2.0 + (-sin(-rot) * (width / 2.0 - dx) - cos(-rot) * (height / 2.0 - dy)) / ysc; init_map_helper(sx, sy, dx, dy, map); } return map; } /* Clean up */ void cleanup_permutation(map_t* map) { free(map->e); free(map); } /* Apply the effect */ void permute_bmp(map_t* map, BITMAP* victim, BITMAP* buffer) { int width = map->w; int height = map->h; /* Pointers to rows of pixels */ unsigned char** bpp = buffer->line; unsigned char** bpp_end = bpp + height; /* Rows of pixels */ unsigned char* bp; unsigned char* bp_end; /* Block of source pixels */ unsigned char** line; unsigned char* l1; unsigned char* l2; /* Sum of color values */ int c; map_elem_t* mp = map->e; /* Add interesting junk */ circlefill(victim, width / 2 + (rand() & 63) - 31, height / 2 + (rand() & 63) - 31, 3, 255); putpixel(victim, width / 2, height / 2, 0); /* Map old image to new */ for (; bpp < bpp_end; bpp++) { bp = *bpp; bp_end = bp + width; for (; bp < bp_end; bp++, mp++) { /* Locate block of source pixels */ line = victim->line + mp->y; l1 = line[0] + mp->x; l2 = mp->y < height ? (line[1] + mp->x) : NULL; /* Total the weighted color values */ c = 0; if (mp->a1 != 0) c += l1[0] * mp->a1; if (mp->a2 != 0) c += l1[1] * mp->a2; if (mp->a3 != 0) c += l2[0] * mp->a3; if (mp->a4 != 0) c += l2[1] * mp->a4; *bp = c / 256; } } /* Feedback! */ blit(buffer, victim, 0, 0, 0, 0, width, height); } /* Sets up four contiguous map entries */ static void init_map_helper(float sx, float sy, int dx, int dy, map_t* map) { /* Locate correct map element */ map_elem_t* m = &map->e[dy * map->w + dx]; /* Round down */ int fx = m->x = floor(sx); int fy = m->y = floor(sy); /* Find fractional part */ float cx = sx - fx; float cy = sy - fy; /* Find 1 - fraction */ float icx = 1.0 - cx; float icy = 1.0 - cy; /* Calculate borders */ int w1 = map->w - 1; int w2 = map->w - 2; int h1 = map->h - 1; int h2 = map->h - 2; /* Interpolate fraction among four adjacent pixels */ m->a1 = fx < 0 || fx > w1 || fy < 0 || fy > h1 ? 0 : icx * icy * 256; m->a2 = fx < -1 || fx > w2 || fy < 0 || fy > h1 ? 0 : cx * icy * 256; m->a3 = fx < 0 || fx > w1 || fy < -1 || fy > h2 ? 0 : icx * cy * 256; m->a4 = fx < -1 || fx > w2 || fy < -1 || fy > h2 ? 0 : cx * cy * 256; }