/* ichika5.c - Don Yang (uguu.org) 11/20/04 */ #include #include typedef float flt; unsigned char *image, *mask, *m, *u, c; int width, height, size, align, headersize, i, j, k; flt r, g, b, h, s, v, r0, g0, b0, d1, d2, f, p, q, t; char header[64], *errstr[] = {"read error", "write error", "invalid image", "out of memory"}; FILE *file; void rgb2hsv() { p = q = r; if( p > g ) p = g; if( q < g ) q = g; if( p > b ) p = b; if( q < b ) q = b; h = s = v = 0; if( p != q ) { p = q - p; h = (r == q) ? ((g - b) / p) : (g == q) ? ((b - r) / p + 2) : ((r - g) / p + 4); s = p / (v = q); } } int CheckNeighbors0(int offset) { if( offset < width || offset > size - width || !(offset % width) || !((offset + 1) % width) ) return 1; r = (flt)*(image + offset * 3) / 255; g = (flt)*(image + offset * 3 + 1) / 255; b = (flt)*(image + offset * 3 + 2) / 255; rgb2hsv(); return ((.3 < h && h < .45) || 4.3 < h || h < .1) ? 0 : CheckNeighbors0(offset + k); } int ErrorMsg() { if( file ) fclose(file); return puts(errstr[k]); } void Erase(int offset) { if( mask[offset] - 255 ) { mask[offset] = 255; if( (offset % width) < width - 1 ) Erase(offset + 1); if( (offset / width) < height - 1 ) Erase(offset + width); if( offset % width ) Erase(offset - 1); if( offset / width ) Erase(offset - width); } } void ReorderBytes() { u = image - 1; for(i = 0; i < size; i++) { c = *++u; *u = *(u + 2); *(u += 2) = c; } } int main(int argc, char **argv) { if( argc < 3 ) return printf("%s \n", *argv); k = width = 0; if( !(file = fopen(*++argv, "rb")) ) return ErrorMsg(); image = 0; if( fread(header, 64, 1, file) - 1 ) return ErrorMsg(); k += 2; if( *header == 66 && header[1] == 77 ) { if( *(int*)(header + 28) - 24 ) return ErrorMsg(); width = *(int*)(header + 18); height = *(int*)(header + 22); align = (4 - ((width * 3) & 3)) & 3; headersize = 54; } else if( *header == 80 && header[1] == 54 ) { for(i = j = headersize = 0; i < 63; i++) if( header[i] == 10 ) if( ++j == 3 ) { header[headersize = ++i] = 0; i = 64; } if( !headersize || (sscanf(header, "P6\n%d %d\n", &width, &height) - 2) ) return ErrorMsg(); align = 0; } if( width < 16 || height < 16 ) return ErrorMsg(); k++; if( !(image = (unsigned char*)malloc((size = width * height) * 3)) ) return ErrorMsg(); u = image; for(fseek(file, headersize, i = 0); i < height; i++) { fread(u, width * 3, 1, file); u += width * 3; for(j = 0; j++ < align; fgetc(file)); } fclose(file); file = 0; if( *header - 80 ) ReorderBytes(); if( !(m = mask = (unsigned char*)malloc(size)) ) return ErrorMsg(); u = image; for(j = 0; j < size; j++) { r = (flt)*(u++) / 255; g = (flt)*(u++) / 255; b = (flt)*(u++) / 255; rgb2hsv(); *m = 255; if( 3.6 < h && h < 4.24 ) { d1 = (s-.65)*(s-.65) + (v-.42)*(v-.42) * 1.29; d2 = (s-.36)*(s-.36) + (v-.6)*(v-.6) * 1.29; if( d1 < .6 || d2 < .6 ) *m = (unsigned char)(255 * ((d1 < .6) ? (d1 / .6) : (d2 / .6))); } m++; } for(i = j = k = 0; j < width;) { Erase(j); Erase(j + width); Erase(j + size - width * 2); Erase(j++ + size - width); } for(; k < height;) { Erase(k * width); Erase(k * width + 1); Erase((k + 1) * width - 2); Erase(++k * width - 1); } for(m = mask; i < size; i++) { if( *m - 255 ) if( (CheckNeighbors0(i + (k = 1)) ? 1 : CheckNeighbors0(i + (k = -1)) ? 1 : CheckNeighbors0(i + (k = width)) ? 1 : CheckNeighbors0(i + (k = -width)) ? 1 : 0) ) Erase(i); m++; } u = image; m = mask; for(i = 0; i < size; i++) { if( *m - 255 ) { d1 = (flt)*m / 255; d2 = 1 - d1; r = r0 = (flt)*u / 255; g = g0 = (flt)*(u+1) / 255; b = b0 = (flt)*(u+2) / 255; rgb2hsv(); if( (h += 2) >= 6 ) h -= 6; if( (s += .7) > 1 ) s = 1; if( (v += .1) > 1 ) v = 1; k = (int)h; f = h - (flt)k; p = v * (1 - s); q = v * (1 - s * f); t = v * (1 - s * (1 - f)); r = (k < 4) ? (k < 2) ? k ? q : v : p : (k > 4) ? v : t; g = (k < 3) ? k ? v : t : k > 3 ? p : q; b = (k < 3) ? (k > 1) ? t : p : (k > 4) ? q : v; r = r0 * d1 + r * d2; g = r0 * d1 + g * d2; b = r0 * d1 + b * d2; *u = (unsigned char)(r * 255); u[1] = (unsigned char)(g * 255); u[2] = (unsigned char)(b * 255); } u += 3; m++; } free(mask); if( *header - 80 ) ReorderBytes(); k = 1; if( !(file = fopen(*++argv, "wb+")) ) return ErrorMsg(); fwrite(header, headersize, 1, file); u = image; for(j = 0; j < height; j++) { fwrite(u, width * 3, 1, file); for(k = 0; k < align; k++) fputc(0, file); u += width * 3; } fclose(file); free(image); return 0; }