made a few functions static
[swftools.git] / lib / png.c
index 9669f89..96fd463 100644 (file)
--- 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)
+static 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) {
@@ -65,11 +63,12 @@ int png_read_chunk(char (*head)[4], int*destlen, U8**destdata, FILE*fi)
     return 1;
 }
 
-unsigned int png_get_dword(FILE*fi)
+static 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
@@ -80,7 +79,7 @@ struct png_header
     int mode;
 };
 
-int png_read_header(FILE*fi, struct png_header*header)
+static int png_read_header(FILE*fi, struct png_header*header)
 {
     char id[4];
     int len;
@@ -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)
 
@@ -140,7 +139,7 @@ int png_read_header(FILE*fi, struct png_header*header)
 
 typedef unsigned char byte;
 #define ABS(a) ((a)>0?(a):(-(a)))
-byte inline PaethPredictor (byte a,byte b,byte c)
+static inline byte PaethPredictor (byte a,byte b,byte c)
 {
         // a = left, b = above, c = upper left
         int p = a + b - c;        // initial estimate
@@ -156,7 +155,7 @@ byte inline PaethPredictor (byte a,byte b,byte c)
         else return c;
 }
 
-void applyfilter1(int mode, U8*src, U8*old, U8*dest, int width)
+static void applyfilter1(int mode, U8*src, U8*old, U8*dest, int width)
 {
     int x;
     unsigned char last=0;
@@ -206,7 +205,7 @@ void applyfilter1(int mode, U8*src, U8*old, U8*dest, int width)
 
 }
 
-void applyfilter2(int mode, U8*src, U8*old, U8*dest, int width)
+static void applyfilter2(int mode, U8*src, U8*old, U8*dest, int width)
 {
     int x;
     unsigned char lasta=0;
@@ -269,7 +268,7 @@ void applyfilter2(int mode, U8*src, U8*old, U8*dest, int width)
 
 
 /* also performs 24 bit conversion! */
-void applyfilter3(int mode, U8*src, U8*old, U8*dest, int width)
+static void applyfilter3(int mode, U8*src, U8*old, U8*dest, int width)
 {
     int x;
     unsigned char lastr=0;
@@ -346,7 +345,7 @@ void applyfilter3(int mode, U8*src, U8*old, U8*dest, int width)
     }    
 }
 
-void inline applyfilter4(int mode, U8*src, U8*old, U8*dest, int width)
+static void inline applyfilter4(int mode, U8*src, U8*old, U8*dest, int width)
 {
     int x;
     unsigned char lastr=0;
@@ -464,6 +463,8 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata)
     struct png_header header;
     int bypp;
     U8*data2 = 0;
+    U8 alphacolor[3];
+    int hasalphacolor=0;
 
     FILE *fi;
     U8 *scanline;
@@ -510,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)) {
@@ -534,8 +545,9 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata)
            }
            printf("\n");*/
        }
-       if(data)
-           free(data);
+       if(data) {
+           free(data); data=0;
+        }
     }
     
     if(!zimagedata || uncompress(imagedata, &imagedatalen, zimagedata, zimagedatalen) != Z_OK) {
@@ -591,6 +603,7 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata)
            }
        }
        free(old);
+        free(imagedata);
     } else if(header.mode == 6 || header.mode == 2) {
        int i,s=0;
        int x,y;
@@ -621,11 +634,24 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata)
            } else {
                old = &data2[(y-1)*header.width*4];
            }
-           if(header.mode == 6)
+           if(header.mode == 6) {
                applyfilter4(mode, src, old, dest, header.width);
-           else // header.mode = 2
+           } else { // header.mode = 2
                applyfilter3(mode, src, old, dest, header.width);
+               /* replace alpha color */
+               if(hasalphacolor) {
+                   int x;
+                   for(x=0;x<header.width;x++) {
+                       if(dest[x*4+1] == alphacolor[0] &&
+                          dest[x*4+2] == alphacolor[1] &&
+                          dest[x*4+3] == alphacolor[2]) {
+                           *(U32*)&dest[x*4] = 0;
+                       }
+                   }
+               }
+           }
        }
+        free(imagedata);
     } else if(header.mode == 0 || header.mode == 3) {
        COL*rgba = 0;
        U8*tmpline = (U8*)malloc(header.width+1);
@@ -644,6 +670,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) {
@@ -664,6 +694,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;
+               }
            }
        }
 
@@ -705,6 +741,7 @@ int getPNG(char*sname, int*destwidth, int*destheight, unsigned char**destdata)
        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;
@@ -740,7 +777,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;
@@ -764,8 +805,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)
@@ -853,7 +899,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);