// fill transparent areas of an image with nearby values // increases compressibility and enhances image quality // in the presence of naive interpolation algorithms. //---------------------------------------------------------- //Copyright (C) 2006 Marc Lehmann //This program is free software; you can redistribute it and/or //modify it under the terms of the GNU Lesser General Public //License as published by the Free Software Foundation; either //version 2.1 of the License, or (at your option) any later version. // //This program is distributed in the hope that it will be useful, //but WITHOUT ANY WARRANTY; without even the implied warranty of //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU //Lesser General Public License for more details. // //You should have received a copy of the GNU Lesser General Public //License along with this program; if not, write to the Free Software //Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include #include #include #include #include using namespace std; #if __BYTE_ORDER == __BIG_ENDIAN # define Rmask 0xff000000UL # define Gmask 0x00ff0000UL # define Bmask 0x0000ff00UL # define Amask 0x000000ffUL # define Rshift 24 # define Gshift 16 # define Bshift 8 # define Ashift 0 #else # define Rmask 0x000000ffUL # define Gmask 0x0000ff00UL # define Bmask 0x00ff0000UL # define Amask 0xff000000UL # define Rshift 0 # define Gshift 8 # define Bshift 16 # define Ashift 24 #endif #define Cmask 0xffUL typedef uint32_t pixel; inline void gather (pixel *img, char *flag, int x, int y, int w, int h, int &c, int &r, int &g, int &b) { if (x < 0 || x >= w) return; if (y < 0 || y >= h) return; int p = img [y * w + x]; int weight = (p >> Ashift) & Cmask; if (!weight) weight = !!flag [y * w + x]; if (!weight) return; c += weight; r += ((p >> Rshift) & Cmask) * weight; g += ((p >> Gshift) & Cmask) * weight; b += ((p >> Bshift) & Cmask) * weight; } void filla (pixel *img, int w, int h) { char *flag = (char *)calloc (w * h, 1); char *flag2 = (char *)calloc (w * h, 1); pixel *dst = new pixel [w * h]; for (int iter = 3; --iter; ) { for (int x = 0; x < w; x++) for (int y = 0; y < h; y++) { int o = y * w + x; if ((img [o] & Amask) || flag [o]) dst [o] = img [o]; else { int weight = 0, r = 0, g = 0, b = 0; gather (img, flag, x - 1, y - 1, w, h, weight, r, g, b); gather (img, flag, x , y - 1, w, h, weight, r, g, b); gather (img, flag, x + 1, y - 1, w, h, weight, r, g, b); gather (img, flag, x - 1, y , w, h, weight, r, g, b); gather (img, flag, x + 1, y , w, h, weight, r, g, b); gather (img, flag, x - 1, y + 1, w, h, weight, r, g, b); gather (img, flag, x , y + 1, w, h, weight, r, g, b); gather (img, flag, x + 1, y + 1, w, h, weight, r, g, b); if (weight) { flag2 [o] = 1; dst [o] = ((r + weight / 2) / weight) << Rshift | ((g + weight / 2) / weight) << Gshift | ((b + weight / 2) / weight) << Bshift; } else dst [o] = img [o]; // not yet here } } memcpy (img, dst, w * h * sizeof (pixel)); memcpy (flag, flag2, w * h); } for (int o = w * h; o--; ) if (!(img [o] & Amask || flag [o])) img [o] = 0; free (dst); free (flag); free (flag2); } int main (int argc, char* argv[]) { if (argc <= 2) { printf("\nUsage: filla w h output.rgba\n"); printf("input file must be 32 bit rgba w*h.\n"); return 1; } int w = atoi (argv [1]); int h = atoi (argv [2]); int size = w * h * sizeof (pixel); pixel *img = (pixel *)new unsigned char [size]; if (fread (img, size, 1, stdin) != 1) { perror ("unable to read input file\n"); exit (1); } filla (img, w, h); if (fwrite (img, size, 1, stdout) != 1) { perror ("unable to read output file\n"); exit (1); } return 0; }