From ff2fc105608a90214af3b03a6adb0078a27d04af Mon Sep 17 00:00:00 2001 From: kramm Date: Wed, 12 Nov 2008 10:38:28 +0000 Subject: [PATCH] added support for palette images --- lib/png.c | 279 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- lib/png.h | 4 + 2 files changed, 271 insertions(+), 12 deletions(-) diff --git a/lib/png.c b/lib/png.c index e290b6f..d40d3e4 100644 --- a/lib/png.c +++ b/lib/png.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -762,6 +763,200 @@ EXPORT int getPNG(const char*sname, int*destwidth, int*destheight, unsigned char return 1; } +static char hasAlpha(unsigned char*_image, int size) +{ + COL*image = (COL*)_image; + int t; + for(t=0;tnum - c2->num; +} + +static colornum_t* getColors(COL*image, int size, int*num) +{ + unsigned char*colexists = malloc((256*256*256)/8); + memset(colexists, 0, (256*256*256)/8); + int t; + int count=0; + + /* find all different colors in the image */ + for(t=0;t= col) max=i; + else min=i+1; + } + assert(colors[i].color==col); + colors[i].num++; + } + free(colexists); + *num = count; + return colors; +} + +static COL* getOptimalPalette(COL*image, int size, int palettesize) +{ + int num; + COL* ret = malloc(sizeof(COL)*palettesize); + memset(ret, 0, sizeof(COL)*palettesize); + colornum_t*colors = getColors(image, size, &num); + + assert(palettesize<=256); + + qsort(colors, num, sizeof(colornum_t), compare_colors); + + if(num<=palettesize) { + /* if there are not more than palettesize different colors in + the image anyway, we are done */ + int t; + for(t=0;t>8; + ret[t].b = colors[t].color>>16; + ret[t].a = 255; + } + return ret; + } + + colornum_t*centers = malloc(sizeof(colornum_t)*palettesize); + int t; + for(t=0;t= (palettesize+num)*2) { + fprintf(stderr, "Warning: didn't find optimal palette\n"); + break; + } + change = 0; + int s,t; + for(s=0;s>0&0xff) - (colors[t].color>>0&0xff)); + distance += abs((centers[s].color>>8&0xff) - (colors[t].color>>8&0xff)); + distance += abs((centers[s].color>>16&0xff) - (colors[t].color>>16&0xff)); + distance *= colors[t].num; + if(distance>0)&0xff)*colors[t].num; + g += ((colors[t].color>>8)&0xff)*colors[t].num; + b += ((colors[t].color>>16)&0xff)*colors[t].num; + count+=colors[t].num; + } + } + if(!count) { + int random = lrand48()%num; + centers[s].color = colors[random].color; + centers[s].num = 0; + change = 1; + } else { + r /= count; + g /= count; + b /= count; + centers[s].color = r|g<<8|b<<16; + centers[s].num = count; + } + } + } + free(belongsto); + free(colors); + for(t=0;t>8; + ret[t].b = centers[t].color>>16; + ret[t].a = 255; + } + free(centers); + return ret; +} + +static int sqr(const int x) {return x*x;} + +static void quantizeImage(unsigned char*_image, int size, int numcolors, unsigned char**newimage, COL**palette) +{ + COL*image = (COL*)_image; + COL*pal= getOptimalPalette(image, size, numcolors); + *palette = pal; + *newimage = (unsigned char*)malloc(size); + int t; + for(t=0;t=2) continue; // don't do y direction filters in the first row line[0]=filtermode; //filter type - filter_line(filtermode, line+1, &data[y*srcwidth], width); + if(bpp==8) + filter_line8(filtermode, line+1, &data[y*srcwidth], width); + else + filter_line32(filtermode, line+1, &data[y*srcwidth], width); int size = test_line(&zs, line, linelen); if(size < bestsize) { @@ -1130,3 +1377,11 @@ EXPORT void writePNG(const char*filename, unsigned char*data, int width, int hei fclose(fi); } +void writePNG(const char*filename, unsigned char*data, int width, int height) +{ + savePNG(filename, data, width, height, 0); +} +void writePalettePNG(const char*filename, unsigned char*data, int width, int height) +{ + savePNG(filename, data, width, height, 256); +} diff --git a/lib/png.h b/lib/png.h index 97eebac..775a84f 100644 --- a/lib/png.h +++ b/lib/png.h @@ -25,7 +25,11 @@ extern "C" { int getPNG(const char*sname, int*destwidth, int*destheight, unsigned char**destdata); int getPNGdimensions(const char*sname, int*destwidth, int*destheight); + +void savePNG(const char*filename, unsigned char*data, int width, int height, int numcolors); + void writePNG(const char*filename, unsigned char*data, int width, int height); +void writePalettePNG(const char*filename, unsigned char*data, int width, int height); #ifdef __cplusplus } -- 1.7.10.4