X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fpng.c;h=f51715117343d024e6b36a4cabc8507abbc1e2ca;hb=5956b76b28e80a49abd7409520282edc5e11dfc0;hp=8dd105b4dd21793a28c5483a2523528b8f312564;hpb=d890a03706282500c2129ae8ab7b399069038192;p=swftools.git diff --git a/lib/png.c b/lib/png.c index 8dd105b..f517151 100644 --- a/lib/png.c +++ b/lib/png.c @@ -30,21 +30,19 @@ typedef struct _COL { U8 a,r,g,b; } COL; -#define REVERSESWAP16(s) ((((s)>>8)&0x00ff)|(((s)<<8)&0xff00)) -#define REVERSESWAP32(s) (REVERSESWAP16(((s)>>16)&0x0000ffff)|((REVERSESWAP16(s)<<16)&0xffff0000)) - int png_read_chunk(char (*head)[4], int*destlen, U8**destdata, FILE*fi) { unsigned int len; + unsigned char blen[4]; if(destlen) *destlen=0; if(destdata) *destdata=0; - if(!fread(&len, 4, 1, fi)) { + if(!fread(&blen, 4, 1, fi)) { return 0; } if(!fread(head, 4, 1, fi)) { return 0; } - len = REVERSESWAP32(len); + len = blen[0]<<24|blen[1]<<16|blen[2]<<8|blen[3]; if(destlen) *destlen = len; if(destdata) { if(!len) { @@ -68,8 +66,9 @@ int png_read_chunk(char (*head)[4], int*destlen, U8**destdata, FILE*fi) unsigned int png_get_dword(FILE*fi) { unsigned int a; - fread(&a,4,1,fi); - return REVERSESWAP32(a); + unsigned char b[4]; + fread(&b,4,1,fi); + return b[0]<<24|b[1]<<16|b[2]<<8|b[3]; } struct png_header @@ -98,8 +97,8 @@ int png_read_header(FILE*fi, struct png_header*header) if(!strncasecmp(id, "IHDR", 4)) { char a,b,c,f,i; if(len < 8) exit(1); - header->width = REVERSESWAP32(*(U32*)&data[0]); - header->height = REVERSESWAP32(*(U32*)&data[4]); + header->width = data[0]<<24|data[1]<<16|data[2]<<8|data[3]; + header->height = data[4]<<24|data[5]<<16|data[6]<<8|data[7]; a = data[8]; // should be 8 b = data[9]; // should be 3(indexed) or 2(rgb) @@ -107,12 +106,8 @@ int png_read_header(FILE*fi, struct png_header*header) f = data[11]; // filter mode (0) i = data[12]; // interlace mode (0) - if(b!=0 && b!=2 && b!=3 && b!=6) { + if(b!=0 && b!=4 && b!=2 && b!=3 && b!=6) { fprintf(stderr, "Image mode %d not supported!\n", b); - if(b == 4) { - fprintf(stderr, "(This is a grayscale image with alpha channel-\n"); - fprintf(stderr, " try converting it into an RGB image with alpha channel)\n"); - } return 0; } if(a!=8 && (b==2 || b==6)) { @@ -467,6 +462,9 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata) int alphapalettelen = 0; struct png_header header; int bypp; + U8*data2 = 0; + U8 alphacolor[3]; + int hasalphacolor=0; FILE *fi; U8 *scanline; @@ -482,10 +480,9 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata) } if(header.mode == 3 || header.mode == 0) bypp = 1; - else - if(header.mode == 2) bypp = 3; - else - if(header.mode == 6) bypp = 4; + else if(header.mode == 4) bypp = 2; + else if(header.mode == 2) bypp = 3; + else if(header.mode == 6) bypp = 4; else { printf("ERROR: mode:%d\n", header.mode); return 0; @@ -514,6 +511,16 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata) alphapalettelen = len; data = 0; //don't free data //printf("found %d alpha colors\n", alphapalettelen); + } else if(header.mode == 0 || header.mode == 2) { + int t; + if(header.mode == 2) { + alphacolor[0] = data[1]; + alphacolor[1] = data[3]; + alphacolor[2] = data[5]; + } else { + alphacolor[0] = alphacolor[1] = alphacolor[2] = data[1]; + } + hasalphacolor = 1; } } if(!strncmp(tagid, "IDAT", 4)) { @@ -553,10 +560,49 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata) *destwidth = header.width; *destheight = header.height; + + data2 = (U8*)malloc(header.width*header.height*4); - if(header.mode == 6 || header.mode == 2) + if(header.mode == 4) { - U8*data2 = (U8*)malloc(header.width*header.height*4); + int i,s=0; + int x,y; + int pos=0; + U8* old= (U8*)malloc(header.width*2); + memset(old, 0, header.width*2); + *destdata = data2; + for(y=0;y=0;x--) { + U8 gray = dest[x*2+0]; + U8 alpha = dest[x*2+1]; + dest[x*4+0] = alpha; + dest[x*4+1] = gray; + dest[x*4+2] = gray; + dest[x*4+3] = gray; + } + } + free(old); + } else if(header.mode == 6 || header.mode == 2) { int i,s=0; int x,y; int pos=0; @@ -575,7 +621,7 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata) pos+=header.width*(header.mode==6?4:3); } else { /* not implemented yet */ - printf("ERROR: bpp:%d\n", header.bpp); + fprintf(stderr, "ERROR: bpp:%d\n", header.bpp); free(data2); return 0; } @@ -593,7 +639,6 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata) } } else if(header.mode == 0 || header.mode == 3) { COL*rgba = 0; - U8*data2 = (U8*)malloc(header.width*header.height*4); U8*tmpline = (U8*)malloc(header.width+1); U8*destline = (U8*)malloc(header.width+1); int i,x,y; @@ -610,6 +655,10 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata) rgba[i].r = i*mult; rgba[i].g = i*mult; rgba[i].b = i*mult; + if(hasalphacolor) { + if(rgba[i].r == alphacolor[0]) + rgba[i].a = 0; + } } } else { if(!palette) { @@ -630,6 +679,12 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata) } else { rgba[i].a = 255; } + if(hasalphacolor) { + if(rgba[i].r == alphacolor[0] && + rgba[i].g == alphacolor[1] && + rgba[i].b == alphacolor[2]) + rgba[i].a = 0; + } } } @@ -706,7 +761,11 @@ static inline void png_write_byte(FILE*fi, U8 byte) static void png_start_chunk(FILE*fi, char*type, int len) { U8 mytype[4]={0,0,0,0}; - U32 mylen = REVERSESWAP32(len); + U8 mylen[4]; + mylen[0] = len>>24; + mylen[1] = len>>16; + mylen[2] = len>>8; + mylen[3] = len; memcpy(mytype,type,strlen(type)); fwrite(&mylen, 4, 1, fi); mycrc32=0xffffffff; @@ -730,8 +789,13 @@ static void png_write_dword(FILE*fi, U32 dword) } static void png_end_chunk(FILE*fi) { - U32 tmp = REVERSESWAP32((mycrc32^0xffffffff)); - fwrite(&tmp,4,1,fi); + U32 tmp = mycrc32^0xffffffff; + U8 tmp2[4]; + tmp2[0] = tmp>>24; + tmp2[1] = tmp>>16; + tmp2[2] = tmp>>8; + tmp2[3] = tmp; + fwrite(&tmp2,4,1,fi); } void writePNG(char*filename, unsigned char*data, int width, int height) @@ -819,7 +883,7 @@ void writePNG(char*filename, unsigned char*data, int width, int height) } datalen2 = datalen3; - data2 = malloc(datalen2); + data2 = (U8*)malloc(datalen2); if((ret = compress (data2, &datalen2, data3, datalen3)) != Z_OK) { fprintf(stderr, "zlib error in pic %d\n", ret); @@ -831,7 +895,6 @@ void writePNG(char*filename, unsigned char*data, int width, int height) png_start_chunk(fi, "IEND", 0); png_end_chunk(fi); - free(data); free(data2); free(data3); }