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