#include #include #include #include #include #include #include #include #include "mypng.h" #define MIN(x, y) ((x) < (y) ? (x) : (y)) #define MAX(x, y) ((x) > (y) ? (x) : (y)) #define NELEM(a) (sizeof((a))/sizeof(*(a))) #if 0 static inline void plasma_pixel(int x, int y, unsigned char *rgb, unsigned long t) { double rx = 0.001 * x - 7, ry = 0.001 * y + 2.5, rt = 0.01 * t; double dx = rx + 0.5 * sin(rt / 5.0); double dy = ry + 0.5 * cos(rt / 3.0); double dv = sin(0.1 * rx + rt) + sin(10.0*(rx*sin(rt/2.0) + ry*cos(rt/3.0)) + rt) + sin(sqrt(10.0*(dx*dx + dy*dy) + 1.0) + rt); rgb[0] = 128 + 128.0 * fabs(sin(dv * M_PI)); rgb[1] = 128 + 128.0 * fabs(sin((dv + 2.0/3.0) * M_PI)); rgb[2] = 128 + 128.0 * fabs(sin((dv + 4.0/3.0) * M_PI)); } static void plasma_map(unsigned int width, unsigned int height, unsigned char *rgb_map, unsigned long t) { int x, y; for (x = 0; x < width; x++) for (y = 0; y < height; y++, rgb_map += 3) { plasma_pixel(x - width/2, y - height/2, rgb_map, t); } } #endif void zero_component(struct pngdata *pp, int idx) { unsigned int x, y; assert(idx < 3); for (x = 0; x < pp->height; x++) for (y = 0; y < pp->width; y++) { png_byte *bp = pp->rows[x] + PNG_COMPONENTS * y; bp[idx] = 0; } } void blur(struct pngdata *src, struct pngdata *dst, unsigned long length) { unsigned int x, y, i, j; struct { long sx, sy; long ex, ey; } box; unsigned long sum[3], nelem = length * length, nbox; unsigned long half_l = (length + 1) / 2; assert(src != NULL); assert(dst != NULL); assert(src->width = dst->width); assert(src->height = dst->height); assert(length > 0); for (x = 0; x < src->height; x++) for (y = 0; y < src->width; y++) { png_byte *bp = NULL; box.sx = x - half_l; box.ex = box.sx + length; box.sy = y - half_l; box.ey = box.sy + length; if (box.sx < 0) box.sx = 0; if (box.ex > src->height) box.ex = src->height; if (box.sy < 0) box.sy = 0; if (box.ey > src->width) box.ey = src->width; nbox = (box.ex - box.sx) * (box.ey - box.sy); sum[0] = sum[1] = sum[2] = 255 * (nelem - nbox); for (i = box.sx; i < box.ex; i++) for (j = box.sy; j < box.ey; j++) { bp = src->rows[i] + PNG_COMPONENTS * j; sum[0] += bp[0]; sum[1] += bp[1]; sum[2] += bp[2]; } bp = dst->rows[x] + PNG_COMPONENTS * y; bp[0] = sum[0] / nelem; bp[1] = sum[1] / nelem; bp[2] = sum[2] / nelem; } } void grey(struct pngdata *src, struct pngdata *dst) { unsigned int x, y; unsigned long gamma = 0; assert(src != NULL); assert(dst != NULL); assert(src->width = dst->width); assert(src->height = dst->height); for (x = 0; x < src->height; x++) for (y = 0; y < src->width; y++) { png_byte *bp = src->rows[x] + PNG_COMPONENTS * y; gamma = (bp[0] + bp[1] + bp[2]) / 3; bp = dst->rows[x] + PNG_COMPONENTS * y; bp[0] = bp[1] = bp[2] = (unsigned int)gamma; } } void usage(const char *argv0) { printf("Usage: %s filename blur-length\n", argv0); } static void add_name_suffix(const char *src, const char *suffix, char *dst, size_t dst_len) { int i; const char *comma = NULL; if (strlen(src) + strlen(suffix) + 1 >= dst_len) { fprintf(stderr, "%s,%d: too small buffer (%zd bytes) for src = '%s' and suffix = '%s'\n", __FILE__, __LINE__, dst_len, src, suffix); exit(1); } for (i = 0, comma = src; src[i]; i++) { if (src[i] == '.') comma = &src[i]; } strncpy(dst, src, comma - src); dst[comma - src] = '\0'; strcat(dst, suffix); strcat(dst, comma); } int main(int argc, char *argv[]) { unsigned long blur_r = 0; struct pngdata data, new; const char *error = NULL; char *name = NULL, *input = NULL; size_t namelen = 0; const unsigned int max_int_bits = 128; int i; struct { char *suffix; int idx; } pure_colors[] = { {"--no-red", 0}, {"--no-green", 1}, {"--no-blue", 2}, }; if (argc < 3) { usage(argv[0]); return 1; } input = argv[1]; blur_r = strtoul(argv[2], NULL, 10); if (blur_r == ULONG_MAX) { fprintf(stderr, "Blur length must be positive (and not bigger than long).\n"); return (1); } namelen = strlen(input) + 1 + ((max_int_bits + 9) / 10 + 1); name = (char *)malloc(namelen * sizeof(char)); if (name == NULL) { fprintf(stderr, "Failed to allocate memory for output filename.\n"); return (1); } error = png_read_8bit_rgb(input, &data); if (error) { fprintf(stderr, "Error while reading %s: %s\n", input, error); return (1); } new.width = data.width; new.height = data.height; png_allocate(&new); for (i = 0; i < NELEM(pure_colors); i++) { add_name_suffix(input, pure_colors[i].suffix, name, namelen); png_copy(&data, &new); zero_component(&new, pure_colors[i].idx); png_write(name, &new); } add_name_suffix(input, "--blurred", name, namelen); blur(&data, &new, blur_r); png_write(name, &new); add_name_suffix(input, "--grey", name, namelen); grey(&data, &new); png_write(name, &new); png_destroy(&data); png_destroy(&new); if (name) free((void *)name); return 0; }