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) {
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
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)
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)) {
int alphapalettelen = 0;
struct png_header header;
int bypp;
+ U8*data2 = 0;
+ U8 alphacolor[3];
+ int hasalphacolor=0;
FILE *fi;
U8 *scanline;
}
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;
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)) {
}
printf("\n");*/
}
- if(data)
- free(data);
+ if(data) {
+ free(data); data=0;
+ }
}
if(!zimagedata || uncompress(imagedata, &imagedatalen, zimagedata, zimagedatalen) != Z_OK) {
*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<header.height;y++) {
+ int mode = imagedata[pos++]; //filter mode
+ U8*src;
+ U8*dest;
+ int x;
+ dest = &data2[(y*header.width)*4];
+
+ if(header.bpp == 8) {
+ /* one byte per pixel */
+ src = &imagedata[pos];
+ pos+=header.width*2;
+ } else {
+ /* not implemented yet */
+ fprintf(stderr, "ERROR: mode=4 bpp:%d\n", header.bpp);
+ free(data2);
+ return 0;
+ }
+
+ applyfilter2(mode, src, old, dest, header.width);
+ memcpy(old, dest, header.width*2);
+
+ for(x=header.width-1;x>=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);
+ free(imagedata);
+ } else if(header.mode == 6 || header.mode == 2) {
int i,s=0;
int x,y;
int pos=0;
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;
}
else // header.mode = 2
applyfilter3(mode, src, old, dest, header.width);
}
+ free(imagedata);
} 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;
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) {
} 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;
+ }
}
}
free(tmpline);
free(destline);
free(rgba);
+ free(imagedata);
} else {
printf("expected PNG mode to be 2, 3 or 6 (is:%d)\n", header.mode);
return 0;
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;
}
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)
}
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);
png_start_chunk(fi, "IEND", 0);
png_end_chunk(fi);
- free(data);
free(data2);
free(data3);
}