X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fpng.c;h=5895269fd8cfcf0385bb4a94e62252bbe3a138f2;hp=d40d3e47e1cbcbdadb469b3f3bfef700e595419a;hb=27215f1c64457c50a5e1a5b2790bf2b9e73d3c4e;hpb=ff2fc105608a90214af3b03a6adb0078a27d04af diff --git a/lib/png.c b/lib/png.c index d40d3e4..5895269 100644 --- a/lib/png.c +++ b/lib/png.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef EXPORT #undef EXPORT @@ -122,7 +123,7 @@ static int png_read_header(FILE*fi, struct png_header*header) return 0; } if(a!=8 && (b==2 || b==6)) { - printf("Bpp %d in mode %d not supported!\n", a); + printf("Bpp %d in mode %d not supported!\n", b, a); return 0; } if(c!=0) { @@ -486,6 +487,7 @@ EXPORT int getPNG(const char*sname, int*destwidth, int*destheight, unsigned char } if(!png_read_header(fi, &header)) { + fclose(fi); return 0; } @@ -779,10 +781,10 @@ typedef struct { u32 color; } colornum_t; -int compare_colors(const void*_c1, const void*_c2) { +static int compare_colors(const void*_c1, const void*_c2) { colornum_t*c1 = (colornum_t*)_c1; colornum_t*c2 = (colornum_t*)_c2; - return c1->num - c2->num; + return c2->num - c1->num; } static colornum_t* getColors(COL*image, int size, int*num) @@ -817,6 +819,7 @@ static colornum_t* getColors(COL*image, int size, int*num) int col = (image[t].r)|(image[t].g)<<8|(image[t].b)<<16; int min,max,i,l; for(min=0, max=count, i=count/2, l=count; i != l; l=i,i=(min+max)/2) { + // binary search if(colors[i].color >= col) max=i; else min=i+1; } @@ -828,11 +831,10 @@ static colornum_t* getColors(COL*image, int size, int*num) return colors; } -static COL* getOptimalPalette(COL*image, int size, int palettesize) +static void getOptimalPalette(COL*image, int size, int palettesize, COL*palette) { int num; - COL* ret = malloc(sizeof(COL)*palettesize); - memset(ret, 0, sizeof(COL)*palettesize); + memset(palette, 0, sizeof(COL)*256); colornum_t*colors = getColors(image, size, &num); assert(palettesize<=256); @@ -844,12 +846,18 @@ static COL* getOptimalPalette(COL*image, int size, int palettesize) the image anyway, we are done */ int t; for(t=0;t>8; - ret[t].b = colors[t].color>>16; - ret[t].a = 255; + palette[t].r = colors[t].color; + palette[t].g = colors[t].color>>8; + palette[t].b = colors[t].color>>16; + palette[t].a = 255; } - return ret; + return; + } + + if(num>2048) { + /* if there are too many different colors, pick the ones that + occur most often */ + num = 2048; } colornum_t*centers = malloc(sizeof(colornum_t)*palettesize); @@ -904,7 +912,7 @@ static COL* getOptimalPalette(COL*image, int size, int palettesize) } } if(!count) { - int random = lrand48()%num; + int random = rand()%num; centers[s].color = colors[random].color; centers[s].num = 0; change = 1; @@ -920,22 +928,20 @@ static COL* getOptimalPalette(COL*image, int size, int palettesize) free(belongsto); free(colors); for(t=0;t>8; - ret[t].b = centers[t].color>>16; - ret[t].a = 255; + palette[t].r = centers[t].color; + palette[t].g = centers[t].color>>8; + palette[t].b = centers[t].color>>16; + palette[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) +static void png_quantize_image(unsigned char*_image, int size, int numcolors, unsigned char**newimage, COL*palette) { COL*image = (COL*)_image; - COL*pal= getOptimalPalette(image, size, numcolors); - *palette = pal; + getOptimalPalette(image, size, numcolors, palette); *newimage = (unsigned char*)malloc(size); int t; for(t=0;t> 17) ^ col32; + hash ^= ((hash>>8) + 1) ^ hash; + return hash; +} + +static int png_get_number_of_palette_entries(COL*img, int width, int height, COL*palette, char*has_alpha) +{ + int len = width*height; + int t; + int palsize = 0; + int size[256]; + int palette_overflow = 0; + u32 lastcol32 = 0; + + memset(size, 0, sizeof(size)); + + u32*pal = (u32*)malloc(65536*sizeof(u32)); + int*count = (int*)malloc(65536*sizeof(int)); + + assert(sizeof(COL)==sizeof(u32)); + assert(width && height); + + lastcol32 = (*(u32*)&img[0])^0xffffffff; // don't match + + for(t=0;t0?5:2; //don't apply y-direction filter in first line + int f; + int best_nr = 0; + int best_energy = INT_MAX; + int w = width*(bpp/8); + unsigned char* pairs = malloc(8192); + assert(bpp==8 || bpp==32); + for(f=0;f>3; + int b = 1<<(v&7); + if(!pairs[p]&b) { + pairs[p]|=b; + different_pairs ++; + } + } + int energy = different_pairs; + if(energy=2) continue; // don't do y direction filters in the first row line[0]=filtermode; //filter type if(bpp==8) - filter_line8(filtermode, line+1, &data[y*srcwidth], width); + png_apply_specific_filter_8(filtermode, line+1, &data[y*srcwidth], width); else - filter_line32(filtermode, line+1, &data[y*srcwidth], width); + png_apply_specific_filter_32(filtermode, line+1, &data[y*srcwidth], width); int size = test_line(&zs, line, linelen); if(size < bestsize) { @@ -1363,7 +1590,18 @@ EXPORT void savePNG(const char*filename, unsigned char*data, int width, int heig } idatsize += compress_line(&zs, bestline, linelen, fi); } - free(line);free(bestline); + free(bestline); +#else + for(y=0;y