implemented type 3 transparency.
[swftools.git] / src / png2swf.c
index 9092aac..4736939 100644 (file)
@@ -125,6 +125,7 @@ int png_read_header(FILE*fi, struct png_header*header)
 {
     char id[4];
     int len;
+    int ok=0;
     U8 head[8] = {137,80,78,71,13,10,26,10};
     U8 head2[8];
     U8*data;
@@ -172,13 +173,12 @@ int png_read_header(FILE*fi, struct png_header*header)
                printf("%dx%d %d %d %d %d %d\n",header->width, header->height, a,b,c,f,i);
            header->bpp = a;
            header->mode = b;
-           return 1;
-       } else {
-           fseek(fi, len, SEEK_CUR);
-       }
+           ok = 1;
+       } 
+       
        free(data);
     }
-    return 0;
+    return ok;
 }
 
 typedef unsigned char byte;
@@ -338,9 +338,13 @@ TAG *MovieAddFrame(SWF * swf, TAG * t, char *sname, int id)
     int len;
     U8*data;
     U8*imagedata;
+    U8*zimagedata=0;
     unsigned long int imagedatalen;
+    unsigned long int zimagedatalen=0;
     U8*palette = 0;
     int palettelen = 0;
+    U8*alphapalette = 0;
+    int alphapalettelen = 0;
     struct png_header header;
     int bypp;
 
@@ -375,20 +379,47 @@ TAG *MovieAddFrame(SWF * swf, TAG * t, char *sname, int id)
        if(!strncmp(tagid, "PLTE", 4)) {
            palette = data;
            palettelen = len/3;
-           data = 0;
+           data = 0; //don't free data
            if(VERBOSE(2))
                printf("%d colors in palette\n", palettelen);
        }
+       if(!strncmp(tagid, "tRNS", 4)) {
+           if(header.mode == 3) {
+               alphapalette = data;
+               alphapalettelen = len;
+               data = 0; //don't free data
+               if(VERBOSE(2))
+                   printf("found %d alpha colors\n", alphapalettelen);
+           }
+       }
        if(!strncmp(tagid, "IDAT", 4)) {
-           if(uncompress(imagedata, &imagedatalen, data, len) != Z_OK) {
-               fprintf(stderr, "Couldn't uncompress %s!\n", sname);
-               return 0;
+           if(!zimagedata) {
+               zimagedatalen = len;
+               zimagedata = malloc(len);
+               memcpy(zimagedata,data,len);
+           } else {
+               zimagedata = realloc(zimagedata, zimagedatalen+len);
+               memcpy(&zimagedata[zimagedatalen], data, len);
+               zimagedatalen += len;
            }
        }
        if(data)
            free(data);
     }
-    t = swf_InsertTag(t, ST_DEFINEBITSLOSSLESS);
+    
+    if(!zimagedata || uncompress(imagedata, &imagedatalen, zimagedata, zimagedatalen) != Z_OK) {
+       fprintf(stderr, "Couldn't uncompress %s!\n", sname);
+       if(zimagedata)
+           free(zimagedata);
+       return 0;
+    }
+    free(zimagedata);
+
+    if(alphapalette)
+       t = swf_InsertTag(t, ST_DEFINEBITSLOSSLESS2);
+    else
+       t = swf_InsertTag(t, ST_DEFINEBITSLOSSLESS);
+
     swf_SetU16(t, id);         // id
     if(header.mode == 2) {
        U8*data2 = malloc(header.width*header.height*4);
@@ -440,8 +471,20 @@ TAG *MovieAddFrame(SWF * swf, TAG * t, char *sname, int id)
            rgba[i].r = palette[i*3+0];
            rgba[i].g = palette[i*3+1];
            rgba[i].b = palette[i*3+2];
-           rgba[i].a = 255;
+           if(alphapalette && i<alphapalettelen) {
+               rgba[i].a = alphapalette[i];
+               if(alphapalette[i] == 0) {
+                   /* if the color is fully transparent, it doesn't matter
+                      what it's rgb values are. furthermore, all Flash 
+                      players up to Flash 5 can't deal with anything beyond
+                      one transparent color with value (00,00,00,00). */
+                   rgba[i].r = rgba[i].g = rgba[i].b = 0;
+               }
+           } else {
+               rgba[i].a = 255;
+           }
        }
+
        for(y=0;y<header.height;y++) {
            int mode = imagedata[pos++]; //filter mode
            U8*old;