1 /*
2 * This file is part of the Advance project.
3 *
4 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004, 2005 Andrea Mazzoleni
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * In addition, as a special exception, Andrea Mazzoleni
21 * gives permission to link the code of this program with
22 * the MAME library (or with modified versions of MAME that use the
23 * same license as MAME), and distribute linked combinations including
24 * the two. You must obey the GNU General Public License in all
25 * respects for all of the code used other than MAME. If you modify
26 * this file, you may extend this exception to your version of the
27 * file, but you are not obligated to do so. If you do not wish to
28 * do so, delete this exception statement from your version.
29 */
30
31 #include "portable.h"
32
33 #include "png.h"
34 #include "endianrw.h"
35 #include "error.h"
36
37 /**************************************************************************************/
38 /* PNG */
39
40 static unsigned char PNG_Signature[] = "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A";
41
42 /**
43 * Read a PNG data chunk.
44 * \param f File to read.
45 * \param data Where to put the allocated data of the chunk.
46 * \param size Where to put the size of the chunk.
47 * \param type Where to put the type of the chunk.
48 */
adv_png_read_chunk(adv_fz * f,unsigned char ** data,unsigned * size,unsigned * type)49 adv_error adv_png_read_chunk(adv_fz* f, unsigned char** data, unsigned* size, unsigned* type)
50 {
51 unsigned char cl[4];
52 unsigned char ct[4];
53 unsigned char cc[4];
54
55 if (fzread(cl, 4, 1, f) != 1) {
56 error_set("Error reading the chunk size");
57 goto err;
58 }
59
60 *size = be_uint32_read(cl);
61
62 if (fzread(ct, 4, 1, f) != 1) {
63 error_set("Error reading the chunk type");
64 goto err;
65 }
66
67 *type = be_uint32_read(ct);
68
69 if (*size) {
70 *data = malloc(*size);
71 if (!*data) {
72 error_set("Low memory");
73 goto err;
74 }
75
76 if (fzread(*data, *size, 1, f) != 1) {
77 error_set("Error reading the chunk data");
78 goto err_data;
79 }
80 } else {
81 *data = 0;
82 }
83
84 if (fzread(cc, 4, 1, f) != 1) {
85 error_set("Error reading the chunk crc");
86 goto err_data;
87 }
88
89 return 0;
90 err_data:
91 free(*data);
92 err:
93 return -1;
94 }
95
96 /**
97 * Write a PNG data chunk.
98 * \param f File to write.
99 * \param type Type of the chunk.
100 * \param data Data of the chunk.
101 * \param size Size of the chunk.
102 * \param count Pointer at the incremental counter of bytes written. Use 0 for disabling it.
103 */
adv_png_write_chunk(adv_fz * f,unsigned type,const unsigned char * data,unsigned size,unsigned * count)104 adv_error adv_png_write_chunk(adv_fz* f, unsigned type, const unsigned char* data, unsigned size, unsigned* count)
105 {
106 unsigned char v[4];
107 unsigned crc;
108
109 be_uint32_write(v, size);
110 if (fzwrite(v, 4, 1, f) != 1) {
111 error_set("Error writing the chunk size");
112 return -1;
113 }
114
115 be_uint32_write(v, type);
116 if (fzwrite(v, 4, 1, f) != 1) {
117 error_set("Error writing the chunk type");
118 return -1;
119 }
120
121 crc = crc32(0, v, 4);
122 if (size > 0) {
123 if (fzwrite(data, size, 1, f) != 1) {
124 error_set("Error writing the chunk data");
125 return -1;
126 }
127
128 crc = crc32(crc, data, size);
129 }
130
131 be_uint32_write(v, crc);
132 if (fzwrite(v, 4, 1, f) != 1) {
133 error_set("Error writing the chunk crc");
134 return -1;
135 }
136
137 if (count)
138 *count += 4 + 4 + size + 4;
139
140 return 0;
141 }
142
143 /**
144 * Read the PNG file signature.
145 * \param f File to read.
146 */
adv_png_read_signature(adv_fz * f)147 adv_error adv_png_read_signature(adv_fz* f)
148 {
149 unsigned char signature[8];
150
151 if (fzread(signature, 8, 1, f) != 1) {
152 error_set("Error reading the signature");
153 return -1;
154 }
155
156 if (memcmp(signature, PNG_Signature, 8)!=0) {
157 error_set("Invalid PNG signature");
158 return -1;
159 }
160
161 return 0;
162 }
163
164 /**
165 * Write the PNG file signature.
166 * \param f File to write.
167 * \param count Pointer at the incremental counter of bytes written. Use 0 for disabling it.
168 */
adv_png_write_signature(adv_fz * f,unsigned * count)169 adv_error adv_png_write_signature(adv_fz* f, unsigned* count)
170 {
171 if (fzwrite(PNG_Signature, 8, 1, f) != 1) {
172 error_set("Error writing the signature");
173 return -1;
174 }
175
176 if (count)
177 *count += 8;
178
179 return 0;
180 }
181
182 /**
183 * Expand a 4 bits per pixel image to a 8 bits per pixel image.
184 * \param width Width of the image.
185 * \param height Height of the image.
186 * \param ptr Data pointer. It must point at the first filter type byte.
187 */
adv_png_expand_4(unsigned width,unsigned height,unsigned char * ptr)188 void adv_png_expand_4(unsigned width, unsigned height, unsigned char* ptr)
189 {
190 unsigned i, j;
191 unsigned char* p8 = ptr + height * (width + 1) - 1;
192 unsigned char* p4 = ptr + height * (width / 2 + 1) - 1;
193
194 width /= 2;
195 for(i=0;i<height;++i) {
196 for(j=0;j<width;++j) {
197 unsigned char v = *p4;
198 *p8-- = v & 0xF;
199 *p8-- = v >> 4;
200 --p4;
201 }
202 --p8;
203 --p4;
204 }
205 }
206
207 /**
208 * Expand a 2 bits per pixel image to a 8 bits per pixel image.
209 * \param width Width of the image.
210 * \param height Height of the image.
211 * \param ptr Data pointer. It must point at the first filter type byte.
212 */
adv_png_expand_2(unsigned width,unsigned height,unsigned char * ptr)213 void adv_png_expand_2(unsigned width, unsigned height, unsigned char* ptr)
214 {
215 unsigned i, j;
216 unsigned char* p8 = ptr + height * (width + 1) - 1;
217 unsigned char* p2 = ptr + height * (width / 4 + 1) - 1;
218
219 width /= 4;
220 for(i=0;i<height;++i) {
221 for(j=0;j<width;++j) {
222 unsigned char v = *p2;
223 *p8-- = v & 0x3;
224 *p8-- = (v >> 2) & 0x3;
225 *p8-- = (v >> 4) & 0x3;
226 *p8-- = v >> 6;
227 --p2;
228 }
229 --p8;
230 --p2;
231 }
232 }
233
234 /**
235 * Expand a 1 bit per pixel image to a 8 bit per pixel image.
236 * \param width Width of the image.
237 * \param height Height of the image.
238 * \param ptr Data pointer. It must point at the first filter type byte.
239 */
adv_png_expand_1(unsigned width,unsigned height,unsigned char * ptr)240 void adv_png_expand_1(unsigned width, unsigned height, unsigned char* ptr)
241 {
242 unsigned i, j;
243 unsigned char* p8 = ptr + height * (width + 1) - 1;
244 unsigned char* p1 = ptr + height * (width / 8 + 1) - 1;
245
246 width /= 8;
247 for(i=0;i<height;++i) {
248 for(j=0;j<width;++j) {
249 unsigned char v = *p1;
250 *p8-- = v & 0x1;
251 *p8-- = (v >> 1) & 0x1;
252 *p8-- = (v >> 2) & 0x1;
253 *p8-- = (v >> 3) & 0x1;
254 *p8-- = (v >> 4) & 0x1;
255 *p8-- = (v >> 5) & 0x1;
256 *p8-- = (v >> 6) & 0x1;
257 *p8-- = v >> 7;
258 --p1;
259 }
260 --p8;
261 --p1;
262 }
263 }
264
265 /**
266 * Unfilter a 8 bit image.
267 * \param width With of the image.
268 * \param height Height of the image.
269 * \param p Data pointer. It must point at the first filter type byte.
270 * \param line Scanline size of row.
271 */
adv_png_unfilter_8(unsigned width,unsigned height,unsigned char * p,unsigned line)272 void adv_png_unfilter_8(unsigned width, unsigned height, unsigned char* p, unsigned line)
273 {
274 unsigned i, j;
275
276 for(i=0;i<height;++i) {
277 unsigned char f = *p++;
278
279 if (f == 0) { /* none */
280 p += width;
281 } else if (f == 1) { /* sub */
282 ++p;
283 for(j=1;j<width;++j) {
284 p[0] += p[-1];
285 ++p;
286 }
287 } else if (f == 2) { /* up */
288 if (i) {
289 unsigned char* u = p - line;
290 for(j=0;j<width;++j) {
291 *p += *u;
292 ++p;
293 ++u;
294 }
295 } else {
296 p += width;
297 }
298 } else if (f == 3) { /* average */
299 if (i) {
300 unsigned char* u = p - line;
301 p[0] += u[0] / 2;
302 ++p;
303 ++u;
304 for(j=1;j<width;++j) {
305 unsigned a = (unsigned)u[0] + (unsigned)p[-1];
306 p[0] += a >> 1;
307 ++p;
308 ++u;
309 }
310 } else {
311 ++p;
312 for(j=1;j<width;++j) {
313 p[0] += p[-1] / 2;
314 ++p;
315 }
316 }
317 } else if (f == 4) { /* paeth */
318 unsigned char* u = p - line;
319 for(j=0;j<width;++j) {
320 unsigned a, b, c;
321 int v;
322 int da, db, dc;
323 a = j<1 ? 0 : p[-1];
324 b = i<1 ? 0 : u[0];
325 c = (j<1 || i<1) ? 0 : u[-1];
326 v = a + b - c;
327 da = v - a;
328 if (da < 0)
329 da = -da;
330 db = v - b;
331 if (db < 0)
332 db = -db;
333 dc = v - c;
334 if (dc < 0)
335 dc = -dc;
336 if (da <= db && da <= dc)
337 p[0] += a;
338 else if (db <= dc)
339 p[0] += b;
340 else
341 p[0] += c;
342 ++p;
343 ++u;
344 }
345 }
346
347 p += line - width - 1;
348 }
349 }
350
351 /**
352 * Unfilter a 24 bit image.
353 * \param width With of the image.
354 * \param height Height of the image.
355 * \param p Data pointer. It must point at the first filter type byte.
356 * \param line Scanline size of row.
357 */
adv_png_unfilter_24(unsigned width,unsigned height,unsigned char * p,unsigned line)358 void adv_png_unfilter_24(unsigned width, unsigned height, unsigned char* p, unsigned line)
359 {
360 unsigned i, j;
361
362 for(i=0;i<height;++i) {
363 unsigned char f = *p++;
364
365 if (f == 0) { /* none */
366 p += width;
367 } else if (f == 1) { /* sub */
368 p += 3;
369 for(j=3;j<width;++j) {
370 p[0] += p[-3];
371 ++p;
372 }
373 } else if (f == 2) { /* up */
374 if (i) {
375 unsigned char* u = p - line;
376 for(j=0;j<width;++j) {
377 *p += *u;
378 ++p;
379 ++u;
380 }
381 } else {
382 p += width;
383 }
384 } else if (f == 3) { /* average */
385 if (i) {
386 unsigned char* u = p - line;
387 p[0] += u[0] / 2;
388 p[1] += u[1] / 2;
389 p[2] += u[2] / 2;
390 p += 3;
391 u += 3;
392 for(j=3;j<width;++j) {
393 unsigned a = (unsigned)u[0] + (unsigned)p[-3];
394 p[0] += a >> 1;
395 ++p;
396 ++u;
397 }
398 } else {
399 p += 3;
400 for(j=3;j<width;++j) {
401 p[0] += p[-3] / 2;
402 ++p;
403 }
404 }
405 } else if (f == 4) { /* paeth */
406 unsigned char* u = p - line;
407 for(j=0;j<width;++j) {
408 unsigned a, b, c;
409 int v;
410 int da, db, dc;
411 a = j<3 ? 0 : p[-3];
412 b = i<1 ? 0 : u[0];
413 c = (j<3 || i<1) ? 0 : u[-3];
414 v = a + b - c;
415 da = v - a;
416 if (da < 0)
417 da = -da;
418 db = v - b;
419 if (db < 0)
420 db = -db;
421 dc = v - c;
422 if (dc < 0)
423 dc = -dc;
424 if (da <= db && da <= dc)
425 p[0] += a;
426 else if (db <= dc)
427 p[0] += b;
428 else
429 p[0] += c;
430 ++p;
431 ++u;
432 }
433 }
434
435 p += line - width - 1;
436 }
437 }
438
439 /**
440 * Unfilter a 32 bit image.
441 * \param width With of the image.
442 * \param height Height of the image.
443 * \param p Data pointer. It must point at the first filter type byte.
444 * \param line Scanline size of row.
445 */
adv_png_unfilter_32(unsigned width,unsigned height,unsigned char * p,unsigned line)446 void adv_png_unfilter_32(unsigned width, unsigned height, unsigned char* p, unsigned line)
447 {
448 unsigned i, j;
449
450 for(i=0;i<height;++i) {
451 unsigned char f = *p++;
452
453 if (f == 0) { /* none */
454 p += width;
455 } else if (f == 1) { /* sub */
456 p += 4;
457 for(j=4;j<width;++j) {
458 p[0] += p[-4];
459 ++p;
460 }
461 } else if (f == 2) { /* up */
462 if (i) {
463 unsigned char* u = p - line;
464 for(j=0;j<width;++j) {
465 *p += *u;
466 ++p;
467 ++u;
468 }
469 } else {
470 p += width;
471 }
472 } else if (f == 3) { /* average */
473 if (i) {
474 unsigned char* u = p - line;
475 p[0] += u[0] / 2;
476 p[1] += u[1] / 2;
477 p[2] += u[2] / 2;
478 p[3] += u[3] / 2;
479 p += 4;
480 u += 4;
481 for(j=4;j<width;++j) {
482 unsigned a = (unsigned)u[0] + (unsigned)p[-4];
483 p[0] += a >> 1;
484 ++p;
485 ++u;
486 }
487 } else {
488 p += 4;
489 for(j=4;j<width;++j) {
490 p[0] += p[-4] / 2;
491 ++p;
492 }
493 }
494 } else if (f == 4) { /* paeth */
495 unsigned char* u = p - line;
496 for(j=0;j<width;++j) {
497 unsigned a, b, c;
498 int v;
499 int da, db, dc;
500 a = j<4 ? 0 : p[-4];
501 b = i<1 ? 0 : u[0];
502 c = (j<4 || i<1) ? 0 : u[-4];
503 v = a + b - c;
504 da = v - a;
505 if (da < 0)
506 da = -da;
507 db = v - b;
508 if (db < 0)
509 db = -db;
510 dc = v - c;
511 if (dc < 0)
512 dc = -dc;
513 if (da <= db && da <= dc)
514 p[0] += a;
515 else if (db <= dc)
516 p[0] += b;
517 else
518 p[0] += c;
519 ++p;
520 ++u;
521 }
522 }
523
524 p += line - width - 1;
525 }
526 }
527
528 /**
529 * Read until the PNG_CN_IEND is found.
530 * \param f File to read.
531 * \param data Pointer at the first chunk to analyze. This chunk is not deallocated.
532 * \param data_size Size of the data chunk.
533 * \param type Type of the data chunk.
534 */
adv_png_read_iend(adv_fz * f,const unsigned char * data,unsigned data_size,unsigned type)535 adv_error adv_png_read_iend(adv_fz* f, const unsigned char* data, unsigned data_size, unsigned type)
536 {
537 if (type == ADV_PNG_CN_IEND)
538 return 0;
539
540 /* ancillary bit. bit 5 of first byte. 0 (uppercase) = critical, 1 (lowercase) = ancillary. */
541 if ((type & 0x20000000) == 0) {
542 char buf[4];
543 be_uint32_write(buf, type);
544 error_unsupported_set("Unsupported critical chunk '%c%c%c%c'", buf[0], buf[1], buf[2], buf[3]);
545 return -1;
546 }
547
548 while (1) {
549 unsigned char* ptr;
550 unsigned ptr_size;
551
552 /* read next */
553 if (adv_png_read_chunk(f, &ptr, &ptr_size, &type) != 0) {
554 return -1;
555 }
556
557 free(ptr);
558
559 if (type == ADV_PNG_CN_IEND)
560 break;
561
562 /* ancillary bit. bit 5 of first byte. 0 (uppercase) = critical, 1 (lowercase) = ancillary. */
563 if ((type & 0x20000000) == 0) {
564 char buf[4];
565 be_uint32_write(buf, type);
566 error_unsupported_set("Unsupported critical chunk '%c%c%c%c'", buf[0], buf[1], buf[2], buf[3]);
567 return -1;
568 }
569 }
570
571 return 0;
572 }
573
574 /**
575 * Read from the PNG_CN_IHDR chunk to the PNG_CN_IEND chunk.
576 * \param pix_width Where to put the image width.
577 * \param pix_height Where to put the image height.
578 * \param pix_pixel Where to put the image bytes per pixel.
579 * \param dat_ptr Where to put the allocated data pointer.
580 * \param dat_size Where to put the allocated data size.
581 * \param pix_ptr Where to put pointer at the start of the image data.
582 * \param pix_scanline Where to put the length of a scanline in bytes.
583 * \param pal_ptr Where to put the allocated palette data pointer. Set to 0 if the image is RGB.
584 * \param pal_size Where to put the palette size in bytes. Set to 0 if the image is RGB.
585 * \param rns_ptr Where to put the allocated transparency data pointer. Set to 0 if the image hasn't transparency.
586 * \param rns_size Where to put the transparency size in number of bytes. Set to 0 if the image hasn't transparency.
587 * \param f File to read.
588 * \param data Pointer at the IHDR chunk. This chunk is not deallocated.
589 * \param data_size Size of the IHDR chuck.
590 */
adv_png_read_ihdr(unsigned * pix_width,unsigned * pix_height,unsigned * pix_pixel,unsigned char ** dat_ptr,unsigned * dat_size,unsigned char ** pix_ptr,unsigned * pix_scanline,unsigned char ** pal_ptr,unsigned * pal_size,unsigned char ** rns_ptr,unsigned * rns_size,adv_fz * f,const unsigned char * data,unsigned data_size)591 adv_error adv_png_read_ihdr(
592 unsigned* pix_width, unsigned* pix_height, unsigned* pix_pixel,
593 unsigned char** dat_ptr, unsigned* dat_size,
594 unsigned char** pix_ptr, unsigned* pix_scanline,
595 unsigned char** pal_ptr, unsigned* pal_size,
596 unsigned char** rns_ptr, unsigned* rns_size,
597 adv_fz* f, const unsigned char* data, unsigned data_size)
598 {
599 unsigned char* ptr;
600 unsigned ptr_size;
601 unsigned type;
602 unsigned long res_size;
603 unsigned pixel;
604 unsigned width;
605 unsigned width_align;
606 unsigned scanline;
607 unsigned height;
608 unsigned depth;
609 int r;
610 z_stream z;
611 adv_bool has_palette;
612
613 *dat_ptr = 0;
614 *pix_ptr = 0;
615 *pal_ptr = 0;
616 *pal_size = 0;
617 *rns_ptr = 0;
618 *rns_size = 0;
619
620 if (data_size != 13) {
621 error_set("Invalid IHDR size %d instead of 13", data_size);
622 goto err;
623 }
624
625 *pix_width = width = be_uint32_read(data + 0);
626 *pix_height = height = be_uint32_read(data + 4);
627
628 depth = data[8];
629 if (data[9] == 3 && depth == 8) {
630 pixel = 1;
631 width_align = width;
632 has_palette = 1;
633 } else if (data[9] == 3 && depth == 4) {
634 pixel = 1;
635 width_align = (width + 1) & ~1;
636 has_palette = 1;
637 } else if (data[9] == 3 && depth == 2) {
638 pixel = 1;
639 width_align = (width + 3) & ~3;
640 has_palette = 1;
641 } else if (data[9] == 3 && depth == 1) {
642 pixel = 1;
643 width_align = (width + 7) & ~7;
644 has_palette = 1;
645 } else if (data[9] == 2 && depth == 8) {
646 pixel = 3;
647 width_align = width;
648 has_palette = 0;
649 } else if (data[9] == 6 && depth == 8) {
650 pixel = 4;
651 width_align = width;
652 has_palette = 0;
653 } else {
654 error_unsupported_set("Unsupported bit depth/color type, %d/%d", (unsigned)data[8], (unsigned)data[9]);
655 goto err;
656 }
657 *pix_pixel = pixel;
658
659 if (width_align < width) {
660 error_unsupported_set("Invalid image size");
661 goto err;
662 }
663
664 if (data[10] != 0) { /* compression */
665 error_unsupported_set("Unsupported compression, %d instead of 0", (unsigned)data[10]);
666 goto err;
667 }
668 if (data[11] != 0) { /* filter */
669 error_unsupported_set("Unsupported filter, %d instead of 0", (unsigned)data[11]);
670 goto err;
671 }
672 if (data[12] != 0) { /* interlace */
673 error_unsupported_set("Unsupported interlace %d", (unsigned)data[12]);
674 goto err;
675 }
676
677 if (adv_png_read_chunk(f, &ptr, &ptr_size, &type) != 0)
678 goto err;
679
680 while (type != ADV_PNG_CN_IDAT) {
681 if (type == ADV_PNG_CN_PLTE) {
682 if (ptr_size > 256*3) {
683 error_set("Invalid palette size in PLTE chunk");
684 goto err_ptr;
685 }
686
687 if (*pal_ptr) {
688 error_set("Double palette specification");
689 goto err_ptr;
690 }
691
692 *pal_ptr = ptr;
693 *pal_size = ptr_size;
694 } else if (type == ADV_PNG_CN_tRNS) {
695 if (*rns_ptr) {
696 error_set("Double rns specification");
697 goto err_ptr;
698 }
699
700 *rns_ptr = ptr;
701 *rns_size = ptr_size;
702 } else {
703 /* ancillary bit. bit 5 of first byte. 0 (uppercase) = critical, 1 (lowercase) = ancillary. */
704 if ((type & 0x20000000) == 0) {
705 char buf[4];
706 be_uint32_write(buf, type);
707 error_unsupported_set("Unsupported critical chunk '%c%c%c%c'", buf[0], buf[1], buf[2], buf[3]);
708 goto err_ptr;
709 }
710
711 free(ptr);
712 }
713
714 if (adv_png_read_chunk(f, &ptr, &ptr_size, &type) != 0)
715 goto err;
716 }
717
718 if (has_palette && !*pal_ptr) {
719 error_set("Missing PLTE chunk");
720 goto err_ptr;
721 }
722
723 if (!has_palette && *pal_ptr) {
724 error_set("Unexpected PLTE chunk");
725 goto err_ptr;
726 }
727
728 /* check for overflow */
729 if (pixel == 0 || width_align >= UINT_MAX / pixel) {
730 error_set("Invalid image size");
731 goto err_ptr;
732 }
733
734 scanline = width_align * pixel + 1;
735
736 /* check for overflow */
737 if (scanline == 0 || height >= UINT_MAX / scanline) {
738 error_set("Invalid image size");
739 goto err_ptr;
740 }
741
742 *dat_size = height * scanline;
743 *dat_ptr = malloc(*dat_size);
744 *pix_scanline = scanline;
745 *pix_ptr = *dat_ptr + 1;
746
747 z.zalloc = 0;
748 z.zfree = 0;
749 z.next_out = *dat_ptr;
750 z.avail_out = *dat_size;
751 z.next_in = 0;
752 z.avail_in = 0;
753
754 r = inflateInit(&z);
755
756 while (r == Z_OK && type == ADV_PNG_CN_IDAT) {
757 z.next_in = ptr;
758 z.avail_in = ptr_size;
759
760 r = inflate(&z, Z_NO_FLUSH);
761
762 free(ptr);
763
764 if (adv_png_read_chunk(f, &ptr, &ptr_size, &type) != 0) {
765 inflateEnd(&z);
766 goto err;
767 }
768 }
769
770 res_size = z.total_out;
771
772 inflateEnd(&z);
773
774 if (r != Z_STREAM_END) {
775 error_set("Invalid compressed data");
776 goto err_ptr;
777 }
778
779 if (depth == 8) {
780 if (res_size != *dat_size) {
781 error_set("Invalid decompressed size");
782 goto err_ptr;
783 }
784
785 if (pixel == 1)
786 adv_png_unfilter_8(width * pixel, height, *dat_ptr, width_align * pixel + 1);
787 else if (pixel == 3)
788 adv_png_unfilter_24(width * pixel, height, *dat_ptr, width_align * pixel + 1);
789 else if (pixel == 4)
790 adv_png_unfilter_32(width * pixel, height, *dat_ptr, width_align * pixel + 1);
791 else {
792 error_set("Unsupported format");
793 goto err_ptr;
794 }
795 } else if (depth == 4) {
796 if (res_size != height * (width_align / 2 + 1)) {
797 error_set("Invalid decompressed size");
798 goto err_ptr;
799 }
800
801 adv_png_unfilter_8(width_align / 2, height, *dat_ptr, width_align / 2 + 1);
802
803 adv_png_expand_4(width_align, height, *dat_ptr);
804 } else if (depth == 2) {
805 if (res_size != height * (width_align / 4 + 1)) {
806 error_set("Invalid decompressed size");
807 goto err_ptr;
808 }
809
810 adv_png_unfilter_8(width_align / 4, height, *dat_ptr, width_align / 4 + 1);
811
812 adv_png_expand_2(width_align, height, *dat_ptr);
813 } else if (depth == 1) {
814 if (res_size != height * (width_align / 8 + 1)) {
815 error_set("Invalid decompressed size");
816 goto err_ptr;
817 }
818
819 adv_png_unfilter_8(width_align / 8, height, *dat_ptr, width_align / 8 + 1);
820
821 adv_png_expand_1(width_align, height, *dat_ptr);
822 }
823
824 if (adv_png_read_iend(f, ptr, ptr_size, type)!=0) {
825 goto err_ptr;
826 }
827
828 free(ptr);
829 return 0;
830
831 err_ptr:
832 free(ptr);
833 err:
834 free(*dat_ptr);
835 free(*pal_ptr);
836 free(*rns_ptr);
837 return -1;
838 }
839
840 /**
841 * Load a PNG image.
842 * The image is stored in memory as present in the PNG format. It imply that the row scanline
843 * is generally greater than the row size.
844 * \param pix_width Where to put the image width.
845 * \param pix_height Where to put the image height.
846 * \param pix_pixel Where to put the image bytes per pixel.
847 * \param dat_ptr Where to put the allocated data pointer.
848 * \param dat_size Where to put the allocated data size.
849 * \param pix_ptr Where to put pointer at the start of the image data.
850 * \param pix_scanline Where to put the length of a scanline in bytes.
851 * \param pal_ptr Where to put the allocated palette data pointer. Set to 0 if the image is RGB.
852 * \param pal_size Where to put the palette size in bytes. Set to 0 if the image is RGB.
853 * \param rns_ptr Where to put the allocated transparency data pointer. Set to 0 if the image hasn't transparency.
854 * \param rns_size Where to put the transparency size in number of bytes. Set to 0 if the image hasn't transparency.
855 * \param f File to read.
856 */
adv_png_read_rns(unsigned * pix_width,unsigned * pix_height,unsigned * pix_pixel,unsigned char ** dat_ptr,unsigned * dat_size,unsigned char ** pix_ptr,unsigned * pix_scanline,unsigned char ** pal_ptr,unsigned * pal_size,unsigned char ** rns_ptr,unsigned * rns_size,adv_fz * f)857 adv_error adv_png_read_rns(
858 unsigned* pix_width, unsigned* pix_height, unsigned* pix_pixel,
859 unsigned char** dat_ptr, unsigned* dat_size,
860 unsigned char** pix_ptr, unsigned* pix_scanline,
861 unsigned char** pal_ptr, unsigned* pal_size,
862 unsigned char** rns_ptr, unsigned* rns_size,
863 adv_fz* f)
864 {
865 unsigned char* data;
866 unsigned type;
867 unsigned size;
868
869 if (adv_png_read_signature(f) != 0) {
870 goto err;
871 }
872
873 do {
874 if (adv_png_read_chunk(f, &data, &size, &type) != 0) {
875 goto err;
876 }
877
878 switch (type) {
879 case ADV_PNG_CN_IHDR :
880 if (adv_png_read_ihdr(pix_width, pix_height, pix_pixel, dat_ptr, dat_size, pix_ptr, pix_scanline, pal_ptr, pal_size, rns_ptr, rns_size, f, data, size) != 0)
881 goto err_data;
882 free(data);
883 return 0;
884 default :
885 /* ancillary bit. bit 5 of first byte. 0 (uppercase) = critical, 1 (lowercase) = ancillary. */
886 if ((type & 0x20000000) == 0) {
887 char buf[4];
888 be_uint32_write(buf, type);
889 error_unsupported_set("Unsupported critical chunk '%c%c%c%c'", buf[0], buf[1], buf[2], buf[3]);
890 goto err_data;
891 }
892 /* ignored */
893 break;
894 }
895
896 free(data);
897
898 } while (type != ADV_PNG_CN_IEND);
899
900 error_set("Invalid PNG file");
901 return -1;
902
903 err_data:
904 free(data);
905 err:
906 return -1;
907 }
908
909 /**
910 * Load a PNG image.
911 * Like png_read_rns() but without transparency.
912 */
adv_png_read(unsigned * pix_width,unsigned * pix_height,unsigned * pix_pixel,unsigned char ** dat_ptr,unsigned * dat_size,unsigned char ** pix_ptr,unsigned * pix_scanline,unsigned char ** pal_ptr,unsigned * pal_size,adv_fz * f)913 adv_error adv_png_read(
914 unsigned* pix_width, unsigned* pix_height, unsigned* pix_pixel,
915 unsigned char** dat_ptr, unsigned* dat_size,
916 unsigned char** pix_ptr, unsigned* pix_scanline,
917 unsigned char** pal_ptr, unsigned* pal_size,
918 adv_fz* f)
919 {
920 adv_error r;
921 unsigned char* rns_ptr;
922 unsigned rns_size;
923
924 r = adv_png_read_rns(pix_width, pix_height, pix_pixel, dat_ptr, dat_size, pix_ptr, pix_scanline, pal_ptr, pal_size, &rns_ptr, &rns_size, f);
925
926 if (r == 0)
927 free(rns_ptr);
928
929 return r;
930 }
931
932 /**
933 * Write the PNG IHDR chunk.
934 * \param f File to write.
935 * \param count Pointer at the incremental counter of bytes written. Use 0 for disabling it.
936 */
adv_png_write_ihdr(unsigned pix_width,unsigned pix_height,unsigned pix_depth,unsigned pix_type,adv_fz * f,unsigned * count)937 adv_error adv_png_write_ihdr(
938 unsigned pix_width, unsigned pix_height,
939 unsigned pix_depth, unsigned pix_type,
940 adv_fz* f, unsigned* count)
941 {
942 uint8 ihdr[13];
943
944 be_uint32_write(ihdr, pix_width);
945 be_uint32_write(ihdr+4, pix_height);
946
947 ihdr[8] = pix_depth;
948 ihdr[9] = pix_type;
949 ihdr[10] = 0; /* compression */
950 ihdr[11] = 0; /* filter */
951 ihdr[12] = 0; /* interlace */
952
953 if (adv_png_write_chunk(f, ADV_PNG_CN_IHDR, ihdr, 13, count)!=0)
954 return -1;
955
956 return 0;
957 }
958
adv_png_write_iend(adv_fz * f,unsigned * count)959 adv_error adv_png_write_iend(adv_fz* f, unsigned* count)
960 {
961 if (adv_png_write_chunk(f, ADV_PNG_CN_IEND, 0, 0, count)!=0)
962 return -1;
963
964 return 0;
965 }
966
967 /**
968 * Write the PNG IDAT chunk.
969 * \param f File to write.
970 * \param count Pointer at the incremental counter of bytes written. Use 0 for disabling it.
971 */
adv_png_write_idat(unsigned pix_width,unsigned pix_height,unsigned pix_pixel,const uint8 * pix_ptr,int pix_pixel_pitch,int pix_scanline_pitch,adv_bool fast,adv_fz * f,unsigned * count)972 adv_error adv_png_write_idat(
973 unsigned pix_width, unsigned pix_height, unsigned pix_pixel,
974 const uint8* pix_ptr, int pix_pixel_pitch, int pix_scanline_pitch,
975 adv_bool fast,
976 adv_fz* f, unsigned* count)
977 {
978 uint8* z_ptr;
979 uint8* r_ptr;
980 unsigned char filter;
981 unsigned long z_size;
982 unsigned res_size;
983 const uint8* p;
984 unsigned i;
985 int method;
986 z_stream z;
987 int r;
988
989 z_size = pix_height * (pix_width * (pix_pixel+1)) * 103 / 100 + 12;
990
991 if (pix_pixel_pitch != pix_pixel) {
992 r_ptr = (uint8*)malloc(pix_width * pix_pixel);
993 if (!r_ptr)
994 goto err;
995 } else {
996 r_ptr = 0;
997 }
998
999 z_ptr = (uint8*)malloc(z_size);
1000 if (!z_ptr)
1001 goto err_row;
1002
1003 if (fast)
1004 method = Z_BEST_SPEED;
1005 else
1006 method = Z_DEFAULT_COMPRESSION;
1007
1008 z.zalloc = 0;
1009 z.zfree = 0;
1010 z.next_out = z_ptr;
1011 z.avail_out = z_size;
1012 z.next_in = 0;
1013 z.avail_in = 0;
1014
1015 p = pix_ptr;
1016 filter = 0;
1017
1018 r = deflateInit(&z, method);
1019
1020 for(i=0;i<pix_height;++i) {
1021 z.next_in = &filter; /* filter byte */
1022 z.avail_in = 1;
1023
1024 r = deflate(&z, Z_NO_FLUSH);
1025 if (r != Z_OK) {
1026 error_set("Error compressing data");
1027 goto err_free;
1028 }
1029
1030 if (r_ptr) {
1031 unsigned char* r = r_ptr;
1032 unsigned j;
1033 for(j=0;j<pix_width;++j) {
1034 unsigned k;
1035 for(k=0;k<pix_pixel;++k) {
1036 *r++ = *p++;
1037 }
1038 p += pix_pixel_pitch - pix_pixel;
1039 }
1040 z.next_in = r_ptr; /* pixel data */
1041 z.avail_in = pix_width * pix_pixel;
1042 p += pix_scanline_pitch - pix_width * pix_pixel_pitch;
1043 } else {
1044 z.next_in = (uint8*)p; /* pixel data */
1045 z.avail_in = pix_width * pix_pixel;
1046 p += pix_scanline_pitch;
1047 }
1048
1049 r = deflate(&z, Z_NO_FLUSH);
1050 if (r != Z_OK) {
1051 error_set("Error compressing data");
1052 goto err_free;
1053 }
1054 }
1055
1056 r = deflate(&z, Z_FINISH);
1057 if (r != Z_STREAM_END) {
1058 error_set("Error compressing data");
1059 goto err_free;
1060 }
1061
1062 res_size = z.total_out;
1063
1064 r = deflateEnd(&z);
1065 if (r != Z_OK) {
1066 error_set("Error compressing data");
1067 goto err_free;
1068 }
1069
1070 if (adv_png_write_chunk(f, ADV_PNG_CN_IDAT, z_ptr, res_size, count)!=0)
1071 goto err_free;
1072
1073 free(z_ptr);
1074 if (r_ptr)
1075 free(r_ptr);
1076
1077 return 0;
1078
1079 err_free:
1080 free(z_ptr);
1081 err_row:
1082 if (r_ptr)
1083 free(r_ptr);
1084 err:
1085 return -1;
1086 }
1087
1088 /**
1089 * Save a partial PNG image.
1090 * \param pix_width Image width.
1091 * \param pix_height Image height.
1092 * \param pix_pixel Image bytes per pixel.
1093 * \param pix_ptr Pointer at the start of the image data.
1094 * \param pix_pixel_pitch Pitch for the next pixel. It may differ from pix_pixel.
1095 * \param pix_scanline_pitch Pitch for the next scanline.
1096 * \param pal_ptr Palette data pointer. Use 0 for RGB image.
1097 * \param pal_size Palette size in bytes. Use 0 for RGB image.
1098 * \param rns_ptr Transparency data pointer. Use 0 for no transparency.
1099 * \param rns_size Transparency size in number of bytes. Use 0 for no transparency.
1100 * \param f File to write.
1101 * \param count Pointer at the incremental counter of bytes written. Use 0 for disabling it.
1102 */
adv_png_write_raw(unsigned pix_width,unsigned pix_height,unsigned pix_pixel,const unsigned char * pix_ptr,int pix_pixel_pitch,int pix_scanline_pitch,const unsigned char * pal_ptr,unsigned pal_size,const unsigned char * rns_ptr,unsigned rns_size,adv_bool fast,adv_fz * f,unsigned * count)1103 adv_error adv_png_write_raw(
1104 unsigned pix_width, unsigned pix_height, unsigned pix_pixel,
1105 const unsigned char* pix_ptr, int pix_pixel_pitch, int pix_scanline_pitch,
1106 const unsigned char* pal_ptr, unsigned pal_size,
1107 const unsigned char* rns_ptr, unsigned rns_size,
1108 adv_bool fast,
1109 adv_fz* f, unsigned* count)
1110 {
1111 unsigned color;
1112 unsigned depth;
1113
1114 if (pix_pixel == 1 && pal_size != 0) {
1115 color = 3;
1116 depth = 8;
1117 } else if (pix_pixel == 1 && pal_size == 0) {
1118 color = 1;
1119 depth = 8;
1120 } else if (pix_pixel == 3 && pal_size == 0) {
1121 color = 2;
1122 depth = 8;
1123 } else if (pix_pixel == 4 && pal_size == 0) {
1124 color = 6;
1125 depth = 8;
1126 } else {
1127 error_unsupported_set("Unsupported bit depth/color");
1128 goto err;
1129 }
1130
1131 if (adv_png_write_ihdr(pix_width, pix_height, depth, color, f, count) != 0) {
1132 goto err;
1133 }
1134
1135 if (pal_size) {
1136 if (adv_png_write_chunk(f, ADV_PNG_CN_PLTE, pal_ptr, pal_size, count) != 0) {
1137 goto err;
1138 }
1139 }
1140
1141 if (rns_size) {
1142 if (adv_png_write_chunk(f, ADV_PNG_CN_tRNS, rns_ptr, rns_size, count) != 0) {
1143 goto err;
1144 }
1145 }
1146
1147 if (adv_png_write_idat(pix_width, pix_height, pix_pixel, pix_ptr, pix_pixel_pitch, pix_scanline_pitch, 0, f, count) != 0) {
1148 goto err;
1149 }
1150
1151 if (adv_png_write_iend(f, count) != 0) {
1152 goto err;
1153 }
1154
1155 return 0;
1156
1157 err:
1158 return -1;
1159 }
1160
1161 /**
1162 * Save a complete PNG image with transparency.
1163 * \param pix_width Image width.
1164 * \param pix_height Image height.
1165 * \param pix_pixel Image bytes per pixel.
1166 * \param pix_ptr Pointer at the start of the image data.
1167 * \param pix_pixel_pitch Pitch for the next pixel. It may differ from pix_pixel.
1168 * \param pix_scanline_pitch Pitch for the next scanline.
1169 * \param pal_ptr Palette data pointer. Use 0 for RGB image.
1170 * \param pal_size Palette size in bytes. Use 0 for RGB image.
1171 * \param rns_ptr Transparency data pointer. Use 0 for no transparency.
1172 * \param rns_size Transparency size in number of bytes. Use 0 for no transparency.
1173 * \param f File to write.
1174 * \param count Pointer at the incremental counter of bytes written. Use 0 for disabling it.
1175 */
adv_png_write_rns(unsigned pix_width,unsigned pix_height,unsigned pix_pixel,const unsigned char * pix_ptr,int pix_pixel_pitch,int pix_scanline_pitch,const unsigned char * pal_ptr,unsigned pal_size,const unsigned char * rns_ptr,unsigned rns_size,adv_bool fast,adv_fz * f,unsigned * count)1176 adv_error adv_png_write_rns(
1177 unsigned pix_width, unsigned pix_height, unsigned pix_pixel,
1178 const unsigned char* pix_ptr, int pix_pixel_pitch, int pix_scanline_pitch,
1179 const unsigned char* pal_ptr, unsigned pal_size,
1180 const unsigned char* rns_ptr, unsigned rns_size,
1181 adv_bool fast,
1182 adv_fz* f, unsigned* count)
1183 {
1184 if (adv_png_write_signature(f, count) != 0) {
1185 return -1;
1186 }
1187
1188 return adv_png_write_raw(
1189 pix_width, pix_height, pix_pixel,
1190 pix_ptr, pix_pixel_pitch, pix_scanline_pitch,
1191 pal_ptr, pal_size,
1192 rns_ptr, rns_size,
1193 fast,
1194 f, count
1195 );
1196 }
1197
1198 /**
1199 * Save a complete PNG image.
1200 * \param pix_width Image width.
1201 * \param pix_height Image height.
1202 * \param pix_pixel Image bytes per pixel.
1203 * \param pix_ptr Pointer at the start of the image data.
1204 * \param pix_pixel_pitch Pitch for the next pixel. It may differ from pix_pixel.
1205 * \param pix_scanline_pitch Pitch for the next scanline.
1206 * \param pal_ptr Palette data pointer. Use 0 for RGB image.
1207 * \param pal_size Palette size in bytes. Use 0 for RGB image.
1208 * \param f File to write.
1209 * \param count Pointer at the incremental counter of bytes written. Use 0 for disabling it.
1210 */
adv_png_write(unsigned pix_width,unsigned pix_height,unsigned pix_pixel,const unsigned char * pix_ptr,int pix_pixel_pitch,int pix_scanline_pitch,const unsigned char * pal_ptr,unsigned pal_size,adv_bool fast,adv_fz * f,unsigned * count)1211 adv_error adv_png_write(
1212 unsigned pix_width, unsigned pix_height, unsigned pix_pixel,
1213 const unsigned char* pix_ptr, int pix_pixel_pitch, int pix_scanline_pitch,
1214 const unsigned char* pal_ptr, unsigned pal_size,
1215 adv_bool fast,
1216 adv_fz* f, unsigned* count)
1217 {
1218 if (adv_png_write_signature(f, count) != 0) {
1219 return -1;
1220 }
1221
1222 return adv_png_write_raw(
1223 pix_width, pix_height, pix_pixel,
1224 pix_ptr, pix_pixel_pitch, pix_scanline_pitch,
1225 pal_ptr, pal_size,
1226 0, 0,
1227 fast,
1228 f, count
1229 );
1230 }
1231
1232