if(!fread(head, 4, 1, fi))
return 0;
len = REVERSESWAP32(len);
- printf("id: %.4s len: %d\n", head, len);
if(destlen) *destlen = len;
if(destdata) {
if(len)
while(png_read_chunk(&id, &len, &data, fi))
{
- printf("%c%c%c%c %d\n", id[0],id[1],id[2],id[3],len);
+ if(VERBOSE(2))
+ printf("%c%c%c%c %d\n", id[0],id[1],id[2],id[3],len);
if(!strncasecmp(id, "IHDR", 4)) {
char a,b,c,f,i;
if(len < 8) exit(1);
c = data[10]; // compression mode (0)
f = data[11]; // filter mode (0)
i = data[12]; // interlace mode (0)
- printf("%08xx%08x %d %d %d %d %d\n",header->width, header->height, a,b,c,f,i);
+
+ if(b!=2 && b!=3) {
+ fprintf(stderr, "Image mode %d not supported!\n", b);
+ exit(1);
+ }
+ if(a!=8) {
+ fprintf(stderr, "Bpp %d not supported!\n", a);
+ exit(1);
+ }
+ if(c!=0) {
+ fprintf(stderr, "Compression mode %d not supported!\n", c);
+ exit(1);
+ }
+ if(f!=0) {
+ fprintf(stderr, "Filter mode %d not supported!\n", f);
+ exit(1);
+ }
+ if(i!=0) {
+ fprintf(stderr, "Interlace mode %d not supported!\n", i);
+ exit(1);
+ }
+ if(VERBOSE(2))
+ 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;
return 0;
}
+typedef unsigned char byte;
+#define ABS(a) ((a)>0?(a):(-(a)))
+byte inline PaethPredictor (byte a,byte b,byte c)
+{
+ // a = left, b = above, c = upper left
+ int p = a + b - c; // initial estimate
+ int pa = ABS(p - a); // distances to a, b, c
+ int pb = ABS(p - b);
+ int pc = ABS(p - c);
+ // return nearest of a,b,c,
+ // breaking ties in order a,b,c.
+ if (pa <= pb && pa <= pc)
+ return a;
+ else if (pb <= pc)
+ return b;
+ else return c;
+}
+
+void applyfilter(int mode, U8*src, U8*old, U8*dest, int width)
+{
+ int x;
+ unsigned char lastr=0;
+ unsigned char lastg=0;
+ unsigned char lastb=0;
+ unsigned char upperlastr=0;
+ unsigned char upperlastg=0;
+ unsigned char upperlastb=0;
+
+ if(mode==0) {
+ for(x=0;x<width;x++) {
+ dest[0] = 255;
+ dest[1] = src[0];
+ dest[2] = src[1];
+ dest[3] = src[2];
+ dest+=4;
+ src+=3;
+ }
+ }
+ else if(mode==1) {
+ for(x=0;x<width;x++) {
+ dest[0] = 255;
+ dest[1] = src[0]+lastr;
+ dest[2] = src[1]+lastg;
+ dest[3] = src[2]+lastb;
+ lastr = dest[1];
+ lastg = dest[2];
+ lastb = dest[3];
+ dest+=4;
+ src+=3;
+ }
+ }
+ else if(mode==2) {
+ for(x=0;x<width;x++) {
+ dest[0] = 255;
+ dest[1] = src[0]+old[1];
+ dest[2] = src[1]+old[2];
+ dest[3] = src[2]+old[3];
+ dest+=4;
+ old+=4;
+ src+=3;
+ }
+ }
+ else if(mode==3) {
+ for(x=0;x<width;x++) {
+ dest[0] = 255;
+ dest[1] = src[0]+(old[1]+lastr)/2;
+ dest[2] = src[1]+(old[2]+lastg)/2;
+ dest[3] = src[2]+(old[3]+lastb)/2;
+ lastr = dest[1];
+ lastg = dest[2];
+ lastb = dest[3];
+ dest+=4;
+ old+=4;
+ src+=3;
+ }
+ }
+ else if(mode==4) {
+ for(x=0;x<width;x++) {
+ dest[0] = 255;
+ dest[1] = src[0]+PaethPredictor(lastr,old[1],upperlastr);
+ dest[2] = src[1]+PaethPredictor(lastg,old[2],upperlastg);
+ dest[3] = src[2]+PaethPredictor(lastb,old[3],upperlastb);
+ lastr = dest[1];
+ lastg = dest[2];
+ lastb = dest[3];
+ upperlastr = old[1];
+ upperlastg = old[2];
+ upperlastb = old[3];
+ dest+=4;
+ old+=4;
+ src+=3;
+ }
+ }
+
+}
+
+void applyfilter1(int mode, U8*src, U8*old, U8*dest, int width)
+{
+ int x;
+ unsigned char last=0;
+ unsigned char upperlast=0;
+
+ if(mode==0) {
+ for(x=0;x<width;x++) {
+ *dest = *src;
+ dest++;
+ src++;
+ }
+ }
+ else if(mode==1) {
+ for(x=0;x<width;x++) {
+ *dest = *src+last;
+ last = *dest;
+ dest++;
+ src++;
+ }
+ }
+ else if(mode==2) {
+ for(x=0;x<width;x++) {
+ *dest = *src+*old;
+ dest++;
+ old++;
+ src++;
+ }
+ }
+ else if(mode==3) {
+ for(x=0;x<width;x++) {
+ *dest = *src+(*old+last)/2;
+ dest++;
+ old++;
+ src++;
+ }
+ }
+ else if(mode==4) {
+ for(x=0;x<width;x++) {
+ *dest = *src+PaethPredictor(last,*old,upperlast);
+ last = *dest;
+ upperlast = *old;
+ dest++;
+ old++;
+ src++;
+ }
+ }
+
+}
+
TAG *MovieAddFrame(SWF * swf, TAG * t, char *sname, int id)
{
SHAPE *s;
palette = data;
palettelen = len/3;
data = 0;
- printf("%d palette\n", len);
+ if(VERBOSE(2))
+ printf("%d colors in palette\n", palettelen);
}
if(!strncmp(tagid, "IDAT", 4)) {
if(uncompress(imagedata, &imagedatalen, data, len) != Z_OK) {
fprintf(stderr, "Couldn't uncompress %s!\n", sname);
return 0;
}
- printf("IDAT %d -> %d\n", len, imagedatalen);
}
if(data)
free(data);
int pos=0;
/* 24->32 bit conversion */
for(y=0;y<header.height;y++) {
- pos++; // filter mode
- for(x=0;x<header.width;x++) {
- U8*src = &imagedata[pos];
- U8*dest = &data2[(y*header.width+x)*4];
- dest[0] = 255;
- dest[1] = src[0];
- dest[2] = src[1];
- dest[3] = src[2];
- pos+=3;
+ int mode = imagedata[pos++]; //filter mode
+
+ U8*src = &imagedata[pos];
+ U8*dest = &data2[(y*header.width)*4];
+ U8*old;
+ if(!y) {
+ memset(data2,0,header.width*4);
+ old = &data2[y*header.width*4];
+ } else {
+ old = &data2[(y-1)*header.width*4];
}
+ applyfilter(mode, src, old, dest, header.width);
+ pos+=header.width*3;
}
swf_SetLosslessBits(t, header.width, header.height, data2, BMF_32BIT);
free(data2);
}
else {
RGBA*rgba = (RGBA*)malloc(palettelen*sizeof(RGBA));
- U8*data2 = malloc((header.width+4)*header.height);
+ int swf_width = BYTES_PER_SCANLINE(header.width);
+ U8*data2 = malloc(swf_width*header.height);
int i,x,y;
int pos=0;
if(!palette) {
rgba[i].a = 255;
}
for(y=0;y<header.height;y++) {
- pos++; //filter mode
- for(x=0;x<header.width;x++) {
- data2[y*header.width+x] =
- imagedata[pos++];
+ int mode = imagedata[pos++]; //filter mode
+ U8*src = &imagedata[pos];
+ U8*dest = &data2[y*swf_width];
+ U8*old;
+ if(!y) {
+ memset(data2,0,swf_width);
+ old = &data2[y*swf_width];
+ } else {
+ old = &data2[(y-1)*swf_width];
}
+ applyfilter1(mode, src, old, dest, header.width);
+ pos+=header.width;
}
swf_SetLosslessBitsIndexed(t, header.width, header.height, data2, rgba, palettelen);
free(rgba);
fprintf(stderr, "%s is not a PNG file!\n", fname);
return -1;
}
- if(head.mode!=2 && head.mode!=3) {
- fprintf(stderr, "%s has unsupported mode %d\n", head.mode);
- return -1;
- }
- if(head.bpp!=8) {
- fprintf(stderr, "%s has unsupported bpp %d\n", head.bpp);
- return -1;
- }
if (global.max_image_width < head.width)
global.max_image_width = head.width;