X-Git-Url: http://git.asbjorn.biz/?p=swftools.git;a=blobdiff_plain;f=lib%2Fpng.c;h=4aa4ddb41435cb0e9b9a6d1e7048a20426e0581f;hp=b74dfb074324f8ada59d3aee22759959468b249c;hb=5a4a20931aade60f0e99df0819fbd1c007a705da;hpb=8e7368c8b06e0a916fa82c44ea22172075a7ef4c diff --git a/lib/png.c b/lib/png.c index b74dfb0..4aa4ddb 100644 --- a/lib/png.c +++ b/lib/png.c @@ -23,6 +23,7 @@ #include #include #include +#include #ifdef EXPORT #undef EXPORT @@ -84,8 +85,8 @@ static unsigned int png_get_dword(FILE*fi) struct png_header { - int width; - int height; + unsigned width; + unsigned height; int bpp; int mode; }; @@ -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) { @@ -166,7 +167,7 @@ static inline byte PaethPredictor (byte a,byte b,byte c) else return c; } -static void applyfilter1(int mode, unsigned char*src, unsigned char*old, unsigned char*dest, int width) +static void applyfilter1(int mode, unsigned char*src, unsigned char*old, unsigned char*dest, unsigned width) { int x; unsigned char last=0; @@ -217,7 +218,7 @@ static void applyfilter1(int mode, unsigned char*src, unsigned char*old, unsigne } -static void applyfilter2(int mode, unsigned char*src, unsigned char*old, unsigned char*dest, int width) +static void applyfilter2(int mode, unsigned char*src, unsigned char*old, unsigned char*dest, unsigned width) { int x; unsigned char lasta=0; @@ -280,7 +281,7 @@ static void applyfilter2(int mode, unsigned char*src, unsigned char*old, unsigne /* also performs 24 bit conversion! */ -static void applyfilter3(int mode, unsigned char*src, unsigned char*old, unsigned char*dest, int width) +static void applyfilter3(int mode, unsigned char*src, unsigned char*old, unsigned char*dest, unsigned width) { int x; unsigned char lastr=0; @@ -357,7 +358,7 @@ static void applyfilter3(int mode, unsigned char*src, unsigned char*old, unsigne } } -static void inline applyfilter4(int mode, unsigned char*src, unsigned char*old, unsigned char*dest, int width) +void png_inverse_filter_32(int mode, unsigned char*src, unsigned char*old, unsigned char*dest, unsigned width) { int x; unsigned char lastr=0; @@ -440,8 +441,7 @@ static void inline applyfilter4(int mode, unsigned char*src, unsigned char*old, } } - -EXPORT int getPNGdimensions(const char*sname, int*destwidth, int*destheight) +EXPORT int getPNGdimensions(const char*sname, unsigned*destwidth, unsigned*destheight) { FILE*fi; struct png_header header; @@ -455,17 +455,17 @@ EXPORT int getPNGdimensions(const char*sname, int*destwidth, int*destheight) *destwidth = header.width; *destheight = header.height; + fclose(fi); return 1; } -EXPORT int getPNG(const char*sname, int*destwidth, int*destheight, unsigned char**destdata) +EXPORT int getPNG(const char*sname, unsigned*destwidth, unsigned*destheight, unsigned char**destdata) { char tagid[4]; int len; unsigned char*data; unsigned char*imagedata; unsigned char*zimagedata=0; - unsigned long int imagedatalen; unsigned long int zimagedatalen=0; unsigned char*palette = 0; int palettelen = 0; @@ -499,7 +499,10 @@ EXPORT int getPNG(const char*sname, int*destwidth, int*destheight, unsigned char return 0; } - imagedatalen = bypp * header.width * header.height + 65536; + unsigned long long imagedatalen_64 = ((unsigned long long)header.width + 1) * header.height * bypp; + if(imagedatalen_64 > 0xffffffff) + return 0; + unsigned long imagedatalen = (unsigned long)imagedatalen_64; imagedata = (unsigned char*)malloc(imagedatalen); fseek(fi,8,SEEK_SET); @@ -561,6 +564,7 @@ EXPORT int getPNG(const char*sname, int*destwidth, int*destheight, unsigned char } } + fclose(fi); if(!zimagedata || uncompress(imagedata, &imagedatalen, zimagedata, zimagedatalen) != Z_OK) { printf("Couldn't uncompress %s!\n", sname); if(zimagedata) @@ -568,7 +572,6 @@ EXPORT int getPNG(const char*sname, int*destwidth, int*destheight, unsigned char return 0; } free(zimagedata); - fclose(fi); *destwidth = header.width; *destheight = header.height; @@ -648,7 +651,7 @@ EXPORT int getPNG(const char*sname, int*destwidth, int*destheight, unsigned char old = &data2[(y-1)*header.width*4]; } if(header.mode == 6) { - applyfilter4(mode, src, old, dest, header.width); + png_inverse_filter_32(mode, src, old, dest, header.width); } else { // header.mode = 2 applyfilter3(mode, src, old, dest, header.width); /* replace alpha color */ @@ -830,11 +833,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); @@ -846,12 +848,12 @@ 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) { @@ -928,22 +930,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, unsigned width, unsigned 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 bytes_per_pixel = bpp>>3; + int w = width*bytes_per_pixel; + int back_x = bytes_per_pixel; + int back_y = y?width*bytes_per_pixel:0; + + unsigned char*pairs[5]; + pairs[0] = calloc(1, 8192); + pairs[1] = calloc(1, 8192); + pairs[2] = calloc(1, 8192); + pairs[3] = calloc(1, 8192); + pairs[4] = calloc(1, 8192); + + unsigned char old[5]; + int l = bytes_per_pixel - 1; + old[0] = src[l]; + old[1] = src[l]; + old[2] = src[l] - src[l-back_y]; + old[3] = src[l] - src[l-back_y]; + old[4] = src[l] - PaethPredictor(0, src[l-back_y], 0); + + int different_pairs[5] = {0,0,0,0,0}; + + int x; + for(x=bytes_per_pixel;x>3; + int b = 1<<(v&7); + if(!pairs[i][p]&b) { + pairs[i][p]|=b; + different_pairs[i]++; + } + } + memcpy(old, dest, sizeof(old)); + } + int f; + int best_nr = 0; + int best_energy = INT_MAX; + for(f=0;f0?5:2; //don't apply y-direction filter in first line + int f; + 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) { @@ -1377,7 +1663,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