1/*
2 * Based on APNG Disassembler 2.3
3 *
4 * Copyright (c) 2009 Max Stepin
5 * maxst at users.sourceforge.net
6 *
7 * GNU LGPL information
8 * --------------------
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <memory.h>
29#include <zlib.h>
30#include "apngloader.h"
31#include <iostream>
32#include <sstream>
33#include <fstream>
34
35#if defined(_MSC_VER) && _MSC_VER >= 1300
36#define swap16(data) _byteswap_ushort(data)
37#define swap32(data) _byteswap_ulong(data)
38#elif __linux__
39#include <byteswap.h>
40#define swap16(data) bswap_16(data)
41#define swap32(data) bswap_32(data)
42#else
43#define swap16(data) (((data >> 8) & 255) | ((data & 255) << 8))
44#define swap32(data) ((swap16(data) << 16) | swap16(data >> 16))
45#endif
46
47#define PNG_ZBUF_SIZE 32768
48
49#define PNG_DISPOSE_OP_NONE 0x00
50#define PNG_DISPOSE_OP_BACKGROUND 0x01
51#define PNG_DISPOSE_OP_PREVIOUS 0x02
52
53#define PNG_BLEND_OP_SOURCE 0x00
54#define PNG_BLEND_OP_OVER 0x01
55
56#define notabc(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
57
58#define ROWBYTES(pixel_bits, width) \
59((pixel_bits) >= 8 ? \
60((width) * (((unsigned int)(pixel_bits)) >> 3)) : \
61(( ((width) * ((unsigned int)(pixel_bits))) + 7) >> 3) )
62
63unsigned char png_sign[8] = {137, 80, 78, 71, 13, 10, 26, 10};
64
65int mask4[2]={240,15};
66int shift4[2]={4,0};
67
68int mask2[4]={192,48,12,3};
69int shift2[4]={6,4,2,0};
70
71int mask1[8]={128,64,32,16,8,4,2,1};
72int shift1[8]={7,6,5,4,3,2,1,0};
73
74unsigned int keep_original = 1;
75unsigned char pal[256][3];
76unsigned char trns[256];
77unsigned int palsize, trnssize;
78unsigned int hasTRNS;
79unsigned short trns1, trns2, trns3;
80
81unsigned int read32(std::istream& f1)
82{
83 unsigned char a, b, c, d;
84 f1.read((char*)&a, 1);
85 f1.read((char*)&b, 1);
86 f1.read((char*)&c, 1);
87 f1.read((char*)&d, 1);
88 return ((unsigned int)a<<24)+((unsigned int)b<<16)+((unsigned int)c<<8)+(unsigned int)d;
89}
90
91unsigned short read16(std::istream& f1)
92{
93 unsigned char a, b;
94 f1.read((char*)&a, 1);
95 f1.read((char*)&b, 1);
96 return ((unsigned short)a<<8)+(unsigned short)b;
97}
98
99unsigned short readshort(unsigned char * p)
100{
101 return ((unsigned short)(*p)<<8)+(unsigned short)(*(p+1));
102}
103
104void read_sub_row(unsigned char * row, unsigned int rowbytes, unsigned int bpp)
105{
106 unsigned int i;
107
108 for (i=bpp; i<rowbytes; i++)
109 row[i] += row[i-bpp];
110}
111
112void read_up_row(unsigned char * row, unsigned char * prev_row, unsigned int rowbytes, unsigned int bpp)
113{
114 unsigned int i;
115
116 if (prev_row)
117 for (i=0; i<rowbytes; i++)
118 row[i] += prev_row[i];
119}
120
121void read_average_row(unsigned char * row, unsigned char * prev_row, unsigned int rowbytes, unsigned int bpp)
122{
123 unsigned int i;
124
125 if (prev_row)
126 {
127 for (i=0; i<bpp; i++)
128 row[i] += prev_row[i]>>1;
129 for (i=bpp; i<rowbytes; i++)
130 row[i] += (prev_row[i] + row[i-bpp])>>1;
131 }
132 else
133 {
134 for (i=bpp; i<rowbytes; i++)
135 row[i] += row[i-bpp]>>1;
136 }
137}
138
139void read_paeth_row(unsigned char * row, unsigned char * prev_row, unsigned int rowbytes, unsigned int bpp)
140{
141 unsigned int i;
142 int a, b, c, pa, pb, pc, p;
143
144 if (prev_row)
145 {
146 for (i=0; i<bpp; i++)
147 row[i] += prev_row[i];
148 for (i=bpp; i<rowbytes; i++)
149 {
150 a = row[i-bpp];
151 b = prev_row[i];
152 c = prev_row[i-bpp];
153 p = b - c;
154 pc = a - c;
155 pa = abs(p);
156 pb = abs(pc);
157 pc = abs(p + pc);
158 row[i] += ((pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c);
159 }
160 }
161 else
162 {
163 for (i=bpp; i<rowbytes; i++)
164 row[i] += row[i-bpp];
165 }
166}
167
168void unpack(z_stream& zstream, unsigned char * dst, unsigned int dst_size, unsigned char * src, unsigned int src_size, unsigned int h, unsigned int rowbytes, unsigned char bpp)
169{
170 unsigned int j;
171 unsigned char * row = dst;
172 unsigned char * prev_row = NULL;
173
174 zstream.next_out = dst;
175 zstream.avail_out = dst_size;
176 zstream.next_in = src;
177 zstream.avail_in = src_size;
178 inflate(&zstream, Z_FINISH);
179 inflateReset(&zstream);
180
181 for (j=0; j<h; j++)
182 {
183 switch (*row++)
184 {
185 case 0: break;
186 case 1: read_sub_row(row, rowbytes, bpp); break;
187 case 2: read_up_row(row, prev_row, rowbytes, bpp); break;
188 case 3: read_average_row(row, prev_row, rowbytes, bpp); break;
189 case 4: read_paeth_row(row, prev_row, rowbytes, bpp); break;
190 }
191 prev_row = row;
192 row += rowbytes;
193 }
194}
195
196void compose0(unsigned char * dst1, unsigned int dstbytes1, unsigned char * dst2, unsigned int dstbytes2, unsigned char * src, unsigned int srcbytes, unsigned int w, unsigned int h, unsigned int bop, unsigned char depth)
197{
198 unsigned int i, j, g, a;
199 unsigned char * sp;
200 unsigned char * dp1;
201 unsigned int * dp2;
202
203 for (j=0; j<h; j++)
204 {
205 sp = src+1;
206 dp1 = dst1;
207 dp2 = (unsigned int*)dst2;
208
209 if (bop == PNG_BLEND_OP_SOURCE)
210 {
211 switch (depth)
212 {
213 case 16: for (i=0; i<w; i++) { a = 0xFF; if (hasTRNS && readshort(sp)==trns1) a = 0; *dp1++ = *sp; *dp2++ = (a << 24) + (*sp << 16) + (*sp << 8) + *sp; sp+=2; } break;
214 case 8: for (i=0; i<w; i++) { a = 0xFF; if (hasTRNS && *sp==trns1) a = 0; *dp1++ = *sp; *dp2++ = (a << 24) + (*sp << 16) + (*sp << 8) + *sp; sp++; } break;
215 case 4: for (i=0; i<w; i++) { g = (sp[i>>1] & mask4[i&1]) >> shift4[i&1]; a = 0xFF; if (hasTRNS && g==trns1) a = 0; *dp1++ = g*0x11; *dp2++ = (a<<24) + g*0x111111; } break;
216 case 2: for (i=0; i<w; i++) { g = (sp[i>>2] & mask2[i&3]) >> shift2[i&3]; a = 0xFF; if (hasTRNS && g==trns1) a = 0; *dp1++ = g*0x55; *dp2++ = (a<<24) + g*0x555555; } break;
217 case 1: for (i=0; i<w; i++) { g = (sp[i>>3] & mask1[i&7]) >> shift1[i&7]; a = 0xFF; if (hasTRNS && g==trns1) a = 0; *dp1++ = g*0xFF; *dp2++ = (a<<24) + g*0xFFFFFF; } break;
218 }
219 }
220 else /* PNG_BLEND_OP_OVER */
221 {
222 switch (depth)
223 {
224 case 16: for (i=0; i<w; i++, dp1++, dp2++) { if (readshort(sp) != trns1) { *dp1 = *sp; *dp2 = 0xFF000000 + (*sp << 16) + (*sp << 8) + *sp; } sp+=2; } break;
225 case 8: for (i=0; i<w; i++, dp1++, dp2++) { if (*sp != trns1) { *dp1 = *sp; *dp2 = 0xFF000000 + (*sp << 16) + (*sp << 8) + *sp; } sp++; } break;
226 case 4: for (i=0; i<w; i++, dp1++, dp2++) { g = (sp[i>>1] & mask4[i&1]) >> shift4[i&1]; if (g != trns1) { *dp1 = g*0x11; *dp2 = 0xFF000000+g*0x111111; } } break;
227 case 2: for (i=0; i<w; i++, dp1++, dp2++) { g = (sp[i>>2] & mask2[i&3]) >> shift2[i&3]; if (g != trns1) { *dp1 = g*0x55; *dp2 = 0xFF000000+g*0x555555; } } break;
228 case 1: for (i=0; i<w; i++, dp1++, dp2++) { g = (sp[i>>3] & mask1[i&7]) >> shift1[i&7]; if (g != trns1) { *dp1 = g*0xFF; *dp2 = 0xFF000000+g*0xFFFFFF; } } break;
229 }
230 }
231
232 src += srcbytes;
233 dst1 += dstbytes1;
234 dst2 += dstbytes2;
235 }
236}
237
238void compose2(unsigned char * dst1, unsigned int dstbytes1, unsigned char * dst2, unsigned int dstbytes2, unsigned char * src, unsigned int srcbytes, unsigned int w, unsigned int h, unsigned int bop, unsigned char depth)
239{
240 unsigned int i, j;
241 unsigned int r, g, b, a;
242 unsigned char * sp;
243 unsigned char * dp1;
244 unsigned int * dp2;
245
246 for (j=0; j<h; j++)
247 {
248 sp = src+1;
249 dp1 = dst1;
250 dp2 = (unsigned int*)dst2;
251
252 if (bop == PNG_BLEND_OP_SOURCE)
253 {
254 if (depth == 8)
255 {
256 for (i=0; i<w; i++)
257 {
258 b = *sp++;
259 g = *sp++;
260 r = *sp++;
261 a = 0xFF;
262 if (hasTRNS && b==trns1 && g==trns2 && r==trns3)
263 a = 0;
264 *dp1++ = b; *dp1++ = g; *dp1++ = r;
265 *dp2++ = (a << 24) + (r << 16) + (g << 8) + b;
266 }
267 }
268 else
269 {
270 for (i=0; i<w; i++, sp+=6)
271 {
272 b = *sp;
273 g = *(sp+2);
274 r = *(sp+4);
275 a = 0xFF;
276 if (hasTRNS && readshort(sp)==trns1 && readshort(sp+2)==trns2 && readshort(sp+4)==trns3)
277 a = 0;
278 *dp1++ = b; *dp1++ = g; *dp1++ = r;
279 *dp2++ = (a << 24) + (r << 16) + (g << 8) + b;
280 }
281 }
282 }
283 else /* PNG_BLEND_OP_OVER */
284 {
285 if (depth == 8)
286 {
287 for (i=0; i<w; i++, sp+=3, dp1+=3, dp2++)
288 if ((*sp != trns1) || (*(sp+1) != trns2) || (*(sp+2) != trns3))
289 {
290 *dp1 = *sp; *(dp1+1) = *(sp+1); *(dp1+2) = *(sp+2);
291 *dp2 = 0xFF000000 + (*(sp+2) << 16) + (*(sp+1) << 8) + *sp;
292 }
293 }
294 else
295 {
296 for (i=0; i<w; i++, sp+=6, dp1+=3, dp2++)
297 if ((readshort(sp) != trns1) || (readshort(sp+2) != trns2) || (readshort(sp+4) != trns3))
298 {
299 *dp1 = *sp; *(dp1+1) = *(sp+2); *(dp1+2) = *(sp+4);
300 *dp2 = 0xFF000000 + (*(sp+4) << 16) + (*(sp+2) << 8) + *sp;
301 }
302 }
303 }
304 src += srcbytes;
305 dst1 += dstbytes1;
306 dst2 += dstbytes2;
307 }
308}
309
310void compose3(unsigned char * dst1, unsigned int dstbytes1, unsigned char * dst2, unsigned int dstbytes2, unsigned char * src, unsigned int srcbytes, unsigned int w, unsigned int h, unsigned int bop, unsigned char depth)
311{
312 unsigned int i, j;
313 unsigned int r, g, b, a;
314 unsigned int r2, g2, b2, a2;
315 int u, v, al;
316 unsigned char col = 0;
317 unsigned char * sp;
318 unsigned char * dp1;
319 unsigned int * dp2;
320
321 for (j=0; j<h; j++)
322 {
323 sp = src+1;
324 dp1 = dst1;
325 dp2 = (unsigned int*)dst2;
326
327 for (i=0; i<w; i++)
328 {
329 switch (depth)
330 {
331 case 8: col = sp[i]; break;
332 case 4: col = (sp[i>>1] & mask4[i&1]) >> shift4[i&1]; break;
333 case 2: col = (sp[i>>2] & mask2[i&3]) >> shift2[i&3]; break;
334 case 1: col = (sp[i>>3] & mask1[i&7]) >> shift1[i&7]; break;
335 }
336
337 b = pal[col][0];
338 g = pal[col][1];
339 r = pal[col][2];
340 a = trns[col];
341
342 if (bop == PNG_BLEND_OP_SOURCE)
343 {
344 *dp1++ = col;
345 *dp2++ = (a << 24) + (r << 16) + (g << 8) + b;
346 }
347 else /* PNG_BLEND_OP_OVER */
348 {
349 if (a == 255)
350 {
351 *dp1++ = col;
352 *dp2++ = (a << 24) + (r << 16) + (g << 8) + b;
353 }
354 else
355 if (a != 0)
356 {
357 if ((a2 = (*dp2)>>24))
358 {
359 keep_original = 0;
360 u = a*255;
361 v = (255-a)*a2;
362 al = 255*255-(255-a)*(255-a2);
363 b2 = ((*dp2)&255);
364 g2 = (((*dp2)>>8)&255);
365 r2 = (((*dp2)>>16)&255);
366 b = (b*u + b2*v)/al;
367 g = (g*u + g2*v)/al;
368 r = (r*u + r2*v)/al;
369 a = al/255;
370 }
371 *dp1++ = col;
372 *dp2++ = (a << 24) + (r << 16) + (g << 8) + b;
373 }
374 else
375 {
376 dp1++;
377 dp2++;
378 }
379 }
380 }
381 src += srcbytes;
382 dst1 += dstbytes1;
383 dst2 += dstbytes2;
384 }
385}
386
387void compose4(unsigned char * dst, unsigned int dstbytes, unsigned char * src, unsigned int srcbytes, unsigned int w, unsigned int h, unsigned int bop, unsigned char depth)
388{
389 unsigned int i, j, step;
390 unsigned int g, a, g2, a2;
391 int u, v, al;
392 unsigned char * sp;
393 unsigned char * dp;
394
395 step = (depth+7)/8;
396
397 for (j=0; j<h; j++)
398 {
399 sp = src+1;
400 dp = dst;
401
402 if (bop == PNG_BLEND_OP_SOURCE)
403 {
404 for (i=0; i<w; i++)
405 {
406 g = *sp; sp += step;
407 a = *sp; sp += step;
408 *dp++ = g;
409 *dp++ = a;
410 }
411 }
412 else /* PNG_BLEND_OP_OVER */
413 {
414 for (i=0; i<w; i++)
415 {
416 g = *sp; sp += step;
417 a = *sp; sp += step;
418 if (a == 255)
419 {
420 *dp++ = g;
421 *dp++ = a;
422 }
423 else
424 if (a != 0)
425 {
426 if ((a2 = *(dp+1)))
427 {
428 u = a*255;
429 v = (255-a)*a2;
430 al = 255*255-(255-a)*(255-a2);
431 g2 = ((*dp)&255);
432 g = (g*u + g2*v)/al;
433 a = al/255;
434 }
435 *dp++ = g;
436 *dp++ = a;
437 }
438 else
439 dp+=2;
440 }
441 }
442 src += srcbytes;
443 dst += dstbytes;
444 }
445}
446
447void compose6(unsigned char * dst, unsigned int dstbytes, unsigned char * src, unsigned int srcbytes, unsigned int w, unsigned int h, unsigned int bop, unsigned char depth)
448{
449 unsigned int i, j, step;
450 unsigned int r, g, b, a;
451 unsigned int r2, g2, b2, a2;
452 int u, v, al;
453 unsigned char * sp;
454 unsigned int * dp;
455
456 step = (depth+7)/8;
457
458 for (j=0; j<h; j++)
459 {
460 sp = src+1;
461 dp = (unsigned int*)dst;
462
463 if (bop == PNG_BLEND_OP_SOURCE)
464 {
465 for (i=0; i<w; i++)
466 {
467 b = *sp; sp += step;
468 g = *sp; sp += step;
469 r = *sp; sp += step;
470 a = *sp; sp += step;
471 *dp++ = (a << 24) + (r << 16) + (g << 8) + b;
472 }
473 }
474 else /* PNG_BLEND_OP_OVER */
475 {
476 for (i=0; i<w; i++)
477 {
478 b = *sp; sp += step;
479 g = *sp; sp += step;
480 r = *sp; sp += step;
481 a = *sp; sp += step;
482 if (a == 255)
483 *dp++ = (a << 24) + (r << 16) + (g << 8) + b;
484 else
485 if (a != 0)
486 {
487 if ((a2 = (*dp)>>24))
488 {
489 u = a*255;
490 v = (255-a)*a2;
491 al = 255*255-(255-a)*(255-a2);
492 b2 = ((*dp)&255);
493 g2 = (((*dp)>>8)&255);
494 r2 = (((*dp)>>16)&255);
495 b = (b*u + b2*v)/al;
496 g = (g*u + g2*v)/al;
497 r = (r*u + r2*v)/al;
498 a = al/255;
499 }
500 *dp++ = (a << 24) + (r << 16) + (g << 8) + b;
501 }
502 else
503 dp++;
504 }
505 }
506 src += srcbytes;
507 dst += dstbytes;
508 }
509}
510
511int load_apng(std::stringstream& file, struct apng_data *apng)
512{
513 unsigned int i, j;
514 unsigned int rowbytes;
515 int imagesize, zbuf_size, zsize, trns_idx;
516 unsigned int len, chunk/*, crc, seq*/;
517 unsigned int w, h, w0, h0, x0, y0;
518 unsigned int frames, loops, first_frame, cur_frame;
519 unsigned int outrow1, outrow2, outimg1, outimg2;
520 unsigned short d1, d2;
521 unsigned char c, dop, bop;
522 unsigned char channels, depth, pixeldepth, bpp;
523 unsigned char coltype, compr, filter, interl;
524 z_stream zstream;
525 memset(apng, 0, sizeof(struct apng_data));
526
527 for (i=0; i<256; i++)
528 {
529 pal[i][0] = i;
530 pal[i][1] = i;
531 pal[i][2] = i;
532 trns[i] = 255;
533 }
534
535 zstream.zalloc = Z_NULL;
536 zstream.zfree = Z_NULL;
537 zstream.opaque = Z_NULL;
538 inflateInit(&zstream);
539
540 frames = 1;
541 first_frame = 0;
542 cur_frame = 0;
543 zsize = 0;
544 hasTRNS = 0;
545 trns_idx = -1;
546 x0 = 0;
547 y0 = 0;
548 loops = 0;
549 bop = PNG_BLEND_OP_SOURCE;
550
551 unsigned char sig[8];
552 unsigned char * pOut1;
553 unsigned char * pOut2;
554 unsigned char * pTemp;
555 unsigned char * pData;
556 unsigned char * pImg1;
557 unsigned char * pImg2;
558 unsigned char * pDst1;
559 unsigned char * pDst2;
560 unsigned short* frames_delay;
561
562 file.read((char*)sig, 8);
563 if(!file.eof() && memcmp(sig, png_sign, 8) == 0) {
564 len = read32(file);
565 chunk = read32(file);
566
567 if ((len == 13) && (chunk == 0x49484452)) /* IHDR */
568 {
569 w = w0 = read32(file);
570 h = h0 = read32(file);
571 file.read((char*)&depth, 1);
572 file.read((char*)&coltype, 1);
573 file.read((char*)&compr, 1);
574 file.read((char*)&filter, 1);
575 file.read((char*)&interl, 1);
576 /*crc = */read32(file);
577
578 channels = 1;
579 if (coltype == 2)
580 channels = 3;
581 else if (coltype == 4)
582 channels = 2;
583 else if (coltype == 6)
584 channels = 4;
585
586 pixeldepth = depth*channels;
587 bpp = (pixeldepth + 7) >> 3;
588 rowbytes = ROWBYTES(pixeldepth, w);
589
590 imagesize = (rowbytes + 1) * h;
591 zbuf_size = imagesize + ((imagesize + 7) >> 3) + ((imagesize + 63) >> 6) + 11;
592
593 /*
594 * We'll render into 2 output buffers, first in original coltype,
595 * second in RGBA.
596 *
597 * It's better to try to keep the original coltype, but if dispose/blend
598 * operations will make it impossible, then we'll save RGBA version instead.
599 */
600
601 outrow1 = w*channels; /* output coltype = input coltype */
602 outrow2 = w*4; /* output coltype = RGBA */
603 outimg1 = h*outrow1;
604 outimg2 = h*outrow2;
605
606 pOut1=(unsigned char *)malloc(outimg1);
607 pOut2=(unsigned char *)malloc(outimg2);
608 pTemp=(unsigned char *)malloc(imagesize);
609 pData=(unsigned char *)malloc(zbuf_size);
610 pImg1=pOut1;
611 pImg2=pOut2;
612 frames_delay = NULL;
613
614 /* apng decoding - begin */
615 memset(pOut1, 0, outimg1);
616 memset(pOut2, 0, outimg2);
617
618 while (!file.eof())
619 {
620 len = read32(file);
621 chunk = read32(file);
622
623 if (chunk == 0x504C5445) /* PLTE */
624 {
625 unsigned int col;
626 for (i=0; i<len; i++)
627 {
628 file.read((char*)&c, 1);
629 col = i/3;
630 if (col<256)
631 {
632 pal[col][i%3] = c;
633 palsize = col+1;
634 }
635 }
636 /*crc = */read32(file);
637 }
638 else if (chunk == 0x74524E53) /* tRNS */
639 {
640 hasTRNS = 1;
641 for (i=0; i<len; i++)
642 {
643 file.read((char*)&c, 1);
644 if (i<256)
645 {
646 trns[i] = c;
647 trnssize = i+1;
648 if (c == 0 && coltype == 3 && trns_idx == -1)
649 trns_idx = i;
650 }
651 }
652 if (coltype == 0)
653 {
654 trns1 = readshort(&trns[0]);
655 if (depth == 16)
656 {
657 trns[1] = trns[0]; trns[0] = 0;
658 }
659 }
660 else
661 if (coltype == 2)
662 {
663 trns1 = readshort(&trns[0]);
664 trns2 = readshort(&trns[2]);
665 trns3 = readshort(&trns[4]);
666 if (depth == 16)
667 {
668 trns[1] = trns[0]; trns[0] = 0;
669 trns[3] = trns[2]; trns[2] = 0;
670 trns[5] = trns[4]; trns[4] = 0;
671 }
672 }
673 /*crc = */read32(file);
674 }
675 else if (chunk == 0x6163544C) /* acTL */
676 {
677 frames = read32(file);
678 if(frames_delay)
679 free(frames_delay);
680 frames_delay = (unsigned short*)malloc(frames*sizeof(int));
681 loops = read32(file);
682 /*crc = */read32(file);
683 if (pOut1)
684 free(pOut1);
685 if (pOut2)
686 free(pOut2);
687 pOut1 = (unsigned char *)malloc((frames+1)*outimg1);
688 pOut2 = (unsigned char *)malloc((frames+1)*outimg2);
689 pImg1 = pOut1;
690 pImg2 = pOut2;
691 memset(pOut1, 0, outimg1);
692 memset(pOut2, 0, outimg2);
693 }
694 else if (chunk == 0x6663544C) /* fcTL */
695 {
696 if (zsize == 0)
697 first_frame = 1;
698 else
699 {
700 if (dop == PNG_DISPOSE_OP_PREVIOUS)
701 {
702 if (coltype != 6)
703 memcpy(pImg1 + outimg1, pImg1, outimg1);
704 if (coltype != 4)
705 memcpy(pImg2 + outimg2, pImg2, outimg2);
706 }
707
708 pDst1 = pImg1 + y0*outrow1 + x0*channels;
709 pDst2 = pImg2 + y0*outrow2 + x0*4;
710 unpack(zstream, pTemp, imagesize, pData, zsize, h0, rowbytes, bpp);
711 switch (coltype)
712 {
713 case 0: compose0(pDst1, outrow1, pDst2, outrow2, pTemp, rowbytes+1, w0, h0, bop, depth); break;
714 case 2: compose2(pDst1, outrow1, pDst2, outrow2, pTemp, rowbytes+1, w0, h0, bop, depth); break;
715 case 3: compose3(pDst1, outrow1, pDst2, outrow2, pTemp, rowbytes+1, w0, h0, bop, depth); break;
716 case 4: compose4(pDst1, outrow1, pTemp, rowbytes+1, w0, h0, bop, depth); break;
717 case 6: compose6( pDst2, outrow2, pTemp, rowbytes+1, w0, h0, bop, depth); break;
718 }
719 zsize = 0;
720
721 if (dop != PNG_DISPOSE_OP_PREVIOUS)
722 {
723 if (coltype != 6)
724 memcpy(pImg1 + outimg1, pImg1, outimg1);
725 if (coltype != 4)
726 memcpy(pImg2 + outimg2, pImg2, outimg2);
727
728 if (dop == PNG_DISPOSE_OP_BACKGROUND)
729 {
730 pDst1 += outimg1;
731 pDst2 += outimg2;
732
733 for (j=0; j<h0; j++)
734 {
735 switch (coltype)
736 {
737 case 0: memset(pDst2, 0, w0*4); if (hasTRNS) memset(pDst1, trns[1], w0); else keep_original = 0; break;
738 case 2: memset(pDst2, 0, w0*4); if (hasTRNS) for (i=0; i<w0; i++) { pDst1[i*3] = trns[1]; pDst1[i*3+1] = trns[3]; pDst1[i*3+2] = trns[5]; } else keep_original = 0; break;
739 case 3: memset(pDst2, 0, w0*4); if (trns_idx >= 0) memset(pDst1, trns_idx, w0); else keep_original = 0; break;
740 case 4: memset(pDst1, 0, w0*2); break;
741 case 6: memset(pDst2, 0, w0*4); break;
742 }
743 pDst1 += outrow1;
744 pDst2 += outrow2;
745 }
746 }
747 }
748 }
749
750 /*seq = */read32(file);
751 w0 = read32(file);
752 h0 = read32(file);
753 x0 = read32(file);
754 y0 = read32(file);
755 d1 = read16(file);
756 d2 = read16(file);
757 file.read((char*)&dop, 1);
758 file.read((char*)&bop, 1);
759 /*crc = */read32(file);
760
761 if(d2 == 0)
762 d2 = 100;
763 frames_delay[cur_frame] = (d1 * 1000)/d2;
764
765 if (cur_frame == 0)
766 {
767 bop = PNG_BLEND_OP_SOURCE;
768 if (dop == PNG_DISPOSE_OP_PREVIOUS)
769 dop = PNG_DISPOSE_OP_BACKGROUND;
770 }
771
772 if (!(coltype & 4) && !(hasTRNS))
773 bop = PNG_BLEND_OP_SOURCE;
774
775 rowbytes = ROWBYTES(pixeldepth, w0);
776 cur_frame++;
777 pImg1 += outimg1;
778 pImg2 += outimg2;
779 }
780 else if (chunk == 0x49444154) /* IDAT */
781 {
782 file.read((char*)(pData + zsize), len);
783 zsize += len;
784 /*crc = */read32(file);
785 }
786 else if (chunk == 0x66644154) /* fdAT */
787 {
788 /*seq = */read32(file);
789 len -= 4;
790 file.read((char*)(pData + zsize), len);
791 zsize += len;
792 /*crc = */read32(file);
793 }
794 else if (chunk == 0x49454E44) /* IEND */
795 {
796 pDst1 = pImg1 + y0*outrow1 + x0*channels;
797 pDst2 = pImg2 + y0*outrow2 + x0*4;
798 unpack(zstream, pTemp, imagesize, pData, zsize, h0, rowbytes, bpp);
799 switch (coltype)
800 {
801 case 0: compose0(pDst1, outrow1, pDst2, outrow2, pTemp, rowbytes+1, w0, h0, bop, depth); break;
802 case 2: compose2(pDst1, outrow1, pDst2, outrow2, pTemp, rowbytes+1, w0, h0, bop, depth); break;
803 case 3: compose3(pDst1, outrow1, pDst2, outrow2, pTemp, rowbytes+1, w0, h0, bop, depth); break;
804 case 4: compose4(pDst1, outrow1, pTemp, rowbytes+1, w0, h0, bop, depth); break;
805 case 6: compose6( pDst2, outrow2, pTemp, rowbytes+1, w0, h0, bop, depth); break;
806 }
807 break;
808 }
809 else
810 {
811 c = (unsigned char)(chunk>>24);
812 if (notabc(c)) break;
813 c = (unsigned char)((chunk>>16) & 0xFF);
814 if (notabc(c)) break;
815 c = (unsigned char)((chunk>>8) & 0xFF);
816 if (notabc(c)) break;
817 c = (unsigned char)(chunk & 0xFF);
818 if (notabc(c)) break;
819
820 file.seekg(len, std::ios_base::cur);
821 /*crc = */read32(file);
822 }
823 }
824 /* apng decoding - end */
825
826 if (coltype == 0)
827 {
828 switch (depth)
829 {
830 case 4: trns[1] *= 0x11; break;
831 case 2: trns[1] *= 0x55; break;
832 case 1: trns[1] *= 0xFF; break;
833 }
834 }
835
836 inflateEnd(&zstream);
837
838 apng->bpp = channels;
839 apng->coltype = coltype;
840 apng->last_frame = cur_frame;
841 apng->first_frame = first_frame;
842 apng->height = h;
843 apng->width = w;
844 apng->num_frames = frames;
845 apng->num_plays = loops;
846 apng->frames_delay = frames_delay;
847 apng->pdata = pOut2;
848 apng->bpp = 4;
849 apng->coltype = 6;
850
851 if(pData)
852 free(pData);
853 if(pTemp)
854 free(pTemp);
855 if(pOut1)
856 free(pOut1);
857 } else
858 return -1;
859 } else
860 return -1;
861
862 return 0;
863}
864
865void write_chunk(std::ostream& f, const char* name, unsigned char* data, unsigned int length)
866{
867 unsigned int crc = crc32(0, Z_NULL, 0);
868 unsigned int len = swap32(length);
869
870 f.write((char*)&len, 4);
871 f.write(name, 4);
872 crc = crc32(crc, (const Bytef*)name, 4);
873
874 if(data != NULL && length > 0) {
875 f.write((char*)data, length);
876 crc = crc32(crc, data, length);
877 }
878
879 crc = swap32(crc);
880 f.write((char*)&crc, 4);
881}
882
883void write_IDATs(std::ostream& f, unsigned char* data, unsigned int length, unsigned int idat_size)
884{
885 unsigned int z_cmf = data[0];
886
887 if((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) {
888 if(length >= 2) {
889 unsigned int z_cinfo = z_cmf >> 4;
890 unsigned int half_z_window_size = 1 << (z_cinfo + 7);
891
892 while(idat_size <= half_z_window_size && half_z_window_size >= 256) {
893 z_cinfo--;
894 half_z_window_size >>= 1;
895 }
896
897 z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
898
899 if(data[0] != (unsigned char)z_cmf) {
900 data[0] = (unsigned char)z_cmf;
901 data[1] &= 0xe0;
902 data[1] += (unsigned char)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f);
903 }
904 }
905 }
906
907 while(length > 0) {
908 unsigned int ds = length;
909
910 if(ds > PNG_ZBUF_SIZE)
911 ds = PNG_ZBUF_SIZE;
912
913 write_chunk(f, "IDAT", data, ds);
914
915 data += ds;
916 length -= ds;
917 }
918}
919
920void save_png(std::stringstream& f, unsigned int width, unsigned int height, int channels, unsigned char *pixels)
921{
922 unsigned int bpp = 4;
923 unsigned char coltype = 0;
924
925 if(channels == 3)
926 coltype = 2;
927 else if (channels == 2)
928 coltype = 4;
929 else if (channels == 4)
930 coltype = 6;
931
932 struct IHDR {
933 unsigned int mWidth;
934 unsigned int mHeight;
935 unsigned char mDepth;
936 unsigned char mColorType;
937 unsigned char mCompression;
938 unsigned char mFilterMethod;
939 unsigned char mInterlaceMethod;
940 } ihdr = { swap32(width), swap32(height), 8, coltype, 0, 0, 0 };
941
942 z_stream zstream1;
943 z_stream zstream2;
944 unsigned int i, j;
945
946 unsigned int rowbytes = width * bpp;
947 unsigned int idat_size = (rowbytes + 1) * height;
948 unsigned int zbuf_size = idat_size + ((idat_size + 7) >> 3) + ((idat_size + 63) >> 6) + 11;
949
950 unsigned char* row_buf = (unsigned char*)malloc(rowbytes + 1);
951 unsigned char* sub_row = (unsigned char*)malloc(rowbytes + 1);
952 unsigned char* up_row = (unsigned char*)malloc(rowbytes + 1);
953 unsigned char* avg_row = (unsigned char*)malloc(rowbytes + 1);
954 unsigned char* paeth_row = (unsigned char*)malloc(rowbytes + 1);
955 unsigned char* zbuf1 = (unsigned char*)malloc(zbuf_size);
956 unsigned char* zbuf2 = (unsigned char*)malloc(zbuf_size);
957
958 if(!row_buf || !sub_row || !up_row || !avg_row || !paeth_row || !zbuf1 || !zbuf2)
959 return;
960
961 row_buf[0] = 0;
962 sub_row[0] = 1;
963 up_row[0] = 2;
964 avg_row[0] = 3;
965 paeth_row[0] = 4;
966
967 zstream1.data_type = Z_BINARY;
968 zstream1.zalloc = Z_NULL;
969 zstream1.zfree = Z_NULL;
970 zstream1.opaque = Z_NULL;
971 deflateInit2(&zstream1, 3, 8, 15, 8, Z_DEFAULT_STRATEGY);
972
973 zstream2.data_type = Z_BINARY;
974 zstream2.zalloc = Z_NULL;
975 zstream2.zfree = Z_NULL;
976 zstream2.opaque = Z_NULL;
977 deflateInit2(&zstream2, 3, 8, 15, 8, Z_FILTERED);
978
979 int a, b, c, pa, pb, pc, p, v;
980 unsigned char* prev;
981 unsigned char* row;
982
983 f.write((char*)png_sign, 8);
984 write_chunk(f, "IHDR", (unsigned char*)(&ihdr), 13);
985
986 if(palsize > 0)
987 write_chunk(f, "PLTE", (unsigned char*)(&pal), palsize * 3);
988
989 zstream1.next_out = zbuf1;
990 zstream1.avail_out = zbuf_size;
991 zstream2.next_out = zbuf2;
992 zstream2.avail_out = zbuf_size;
993
994 prev = NULL;
995 row = pixels;
996
997 for(j = 0; j < (unsigned int)height; j++) {
998 unsigned char* out;
999 unsigned int sum = 0;
1000 unsigned char* best_row = row_buf;
1001 unsigned int mins = ((unsigned int)(-1)) >> 1;
1002
1003 out = row_buf + 1;
1004
1005 for(i = 0; i < rowbytes; i++) {
1006 v = out[i] = row[i];
1007 sum += (v < 128) ? v : 256 - v;
1008 }
1009
1010 mins = sum;
1011
1012 sum = 0;
1013 out = sub_row + 1;
1014
1015 for(i = 0; i < bpp; i++) {
1016 v = out[i] = row[i];
1017 sum += (v < 128) ? v : 256 - v;
1018 }
1019
1020 for(i = bpp; i < rowbytes; i++) {
1021 v = out[i] = row[i] - row[i - bpp];
1022 sum += (v < 128) ? v : 256 - v;
1023
1024 if(sum > mins) break;
1025 }
1026
1027 if(sum < mins) {
1028 mins = sum;
1029 best_row = sub_row;
1030 }
1031
1032 if(prev) {
1033 sum = 0;
1034 out = up_row + 1;
1035
1036 for(i = 0; i < rowbytes; i++) {
1037 v = out[i] = row[i] - prev[i];
1038 sum += (v < 128) ? v : 256 - v;
1039
1040 if(sum > mins) break;
1041 }
1042
1043 if(sum < mins) {
1044 mins = sum;
1045 best_row = up_row;
1046 }
1047
1048 sum = 0;
1049 out = avg_row + 1;
1050
1051 for(i = 0; i < bpp; i++) {
1052 v = out[i] = row[i] - prev[i] / 2;
1053 sum += (v < 128) ? v : 256 - v;
1054 }
1055
1056 for(i = bpp; i < rowbytes; i++) {
1057 v = out[i] = row[i] - (prev[i] + row[i - bpp]) / 2;
1058 sum += (v < 128) ? v : 256 - v;
1059
1060 if(sum > mins) break;
1061 }
1062
1063 if(sum < mins) {
1064 mins = sum;
1065 best_row = avg_row;
1066 }
1067
1068 sum = 0;
1069 out = paeth_row + 1;
1070
1071 for(i = 0; i < bpp; i++) {
1072 v = out[i] = row[i] - prev[i];
1073 sum += (v < 128) ? v : 256 - v;
1074 }
1075
1076 for(i = bpp; i < rowbytes; i++) {
1077 a = row[i - bpp];
1078 b = prev[i];
1079 c = prev[i - bpp];
1080 p = b - c;
1081 pc = a - c;
1082 pa = abs(p);
1083 pb = abs(pc);
1084 pc = abs(p + pc);
1085 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
1086 v = out[i] = row[i] - p;
1087 sum += (v < 128) ? v : 256 - v;
1088
1089 if(sum > mins) break;
1090 }
1091
1092 if(sum < mins) {
1093 best_row = paeth_row;
1094 }
1095 }
1096
1097 zstream1.next_in = row_buf;
1098 zstream1.avail_in = rowbytes + 1;
1099 deflate(&zstream1, Z_NO_FLUSH);
1100
1101 zstream2.next_in = best_row;
1102 zstream2.avail_in = rowbytes + 1;
1103 deflate(&zstream2, Z_NO_FLUSH);
1104
1105 prev = row;
1106 row += rowbytes;
1107 }
1108
1109 deflate(&zstream1, Z_FINISH);
1110 deflate(&zstream2, Z_FINISH);
1111
1112 if(zstream1.total_out <= zstream2.total_out)
1113 write_IDATs(f, zbuf1, zstream1.total_out, idat_size);
1114 else
1115 write_IDATs(f, zbuf2, zstream2.total_out, idat_size);
1116
1117 deflateReset(&zstream1);
1118 zstream1.data_type = Z_BINARY;
1119 deflateReset(&zstream2);
1120 zstream2.data_type = Z_BINARY;
1121
1122 write_chunk(f, "IEND", 0, 0);
1123
1124 deflateEnd(&zstream1);
1125 deflateEnd(&zstream2);
1126 free(zbuf1);
1127 free(zbuf2);
1128 free(row_buf);
1129 free(sub_row);
1130 free(up_row);
1131 free(avg_row);
1132 free(paeth_row);
1133}
1134
1135void free_apng(struct apng_data *apng)
1136{
1137 if(apng->pdata)
1138 free(apng->pdata);
1139 if(apng->frames_delay)
1140 free(apng->frames_delay);
1141}
1142
1143