blob: 5fd7d56bd9413afb6d96947deb53abfc0579b944 [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001
2/* pngrutil.c - utilities to read a PNG file
3 *
4 * libpng 1.2.5 - October 3, 2002
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2002 Glenn Randers-Pehrson
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9 *
10 * This file contains routines that are only called from within
11 * libpng itself during the course of reading an image.
12 */
13
14#define PNG_INTERNAL
15#include "png.h"
16
17#if defined(_WIN32_WCE)
18/* strtod() function is not supported on WindowsCE */
19# ifdef PNG_FLOATING_POINT_SUPPORTED
20__inline double strtod(const char *nptr, char **endptr)
21{
22 double result = 0;
23 int len;
24 wchar_t *str, *end;
25
26 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
27 str = (wchar_t *)malloc(len * sizeof(wchar_t));
28 if ( NULL != str )
29 {
30 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
31 result = wcstod(str, &end);
32 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
33 *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
34 free(str);
35 }
36 return result;
37}
38# endif
39#endif
40
41png_uint_32 /* PRIVATE */
42png_get_uint_31(png_structp png_ptr, png_bytep buf)
43{
44 png_uint_32 i = png_get_uint_32(buf);
45 if (i > PNG_UINT_31_MAX)
46 png_error(png_ptr, "PNG unsigned integer out of range.\n");
47 return (i);
48}
49#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
50/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
51png_uint_32 /* PRIVATE */
52png_get_uint_32(png_bytep buf)
53{
54 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
55 ((png_uint_32)(*(buf + 1)) << 16) +
56 ((png_uint_32)(*(buf + 2)) << 8) +
57 (png_uint_32)(*(buf + 3));
58
59 return (i);
60}
61
62#if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED)
63/* Grab a signed 32-bit integer from a buffer in big-endian format. The
64 * data is stored in the PNG file in two's complement format, and it is
65 * assumed that the machine format for signed integers is the same. */
66png_int_32 /* PRIVATE */
67png_get_int_32(png_bytep buf)
68{
69 png_int_32 i = ((png_int_32)(*buf) << 24) +
70 ((png_int_32)(*(buf + 1)) << 16) +
71 ((png_int_32)(*(buf + 2)) << 8) +
72 (png_int_32)(*(buf + 3));
73
74 return (i);
75}
76#endif /* PNG_READ_pCAL_SUPPORTED */
77
78/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
79png_uint_16 /* PRIVATE */
80png_get_uint_16(png_bytep buf)
81{
82 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
83 (png_uint_16)(*(buf + 1)));
84
85 return (i);
86}
87#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
88
89/* Read data, and (optionally) run it through the CRC. */
90void /* PRIVATE */
91png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
92{
93 png_read_data(png_ptr, buf, length);
94 png_calculate_crc(png_ptr, buf, length);
95}
96
97/* Optionally skip data and then check the CRC. Depending on whether we
98 are reading a ancillary or critical chunk, and how the program has set
99 things up, we may calculate the CRC on the data and print a message.
100 Returns '1' if there was a CRC error, '0' otherwise. */
101int /* PRIVATE */
102png_crc_finish(png_structp png_ptr, png_uint_32 skip)
103{
104 png_size_t i;
105 png_size_t istop = png_ptr->zbuf_size;
106
107 for (i = (png_size_t)skip; i > istop; i -= istop)
108 {
109 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
110 }
111 if (i)
112 {
113 png_crc_read(png_ptr, png_ptr->zbuf, i);
114 }
115
116 if (png_crc_error(png_ptr))
117 {
118 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
119 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
120 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
121 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
122 {
123 png_chunk_warning(png_ptr, "CRC error");
124 }
125 else
126 {
127 png_chunk_error(png_ptr, "CRC error");
128 }
129 return (1);
130 }
131
132 return (0);
133}
134
135/* Compare the CRC stored in the PNG file with that calculated by libpng from
136 the data it has read thus far. */
137int /* PRIVATE */
138png_crc_error(png_structp png_ptr)
139{
140 png_byte crc_bytes[4];
141 png_uint_32 crc;
142 int need_crc = 1;
143
144 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
145 {
146 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
147 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
148 need_crc = 0;
149 }
150 else /* critical */
151 {
152 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
153 need_crc = 0;
154 }
155
156 png_read_data(png_ptr, crc_bytes, 4);
157
158 if (need_crc)
159 {
160 crc = png_get_uint_32(crc_bytes);
161 return ((int)(crc != png_ptr->crc));
162 }
163 else
164 return (0);
165}
166
167#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
168 defined(PNG_READ_iCCP_SUPPORTED)
169/*
170 * Decompress trailing data in a chunk. The assumption is that chunkdata
171 * points at an allocated area holding the contents of a chunk with a
172 * trailing compressed part. What we get back is an allocated area
173 * holding the original prefix part and an uncompressed version of the
174 * trailing part (the malloc area passed in is freed).
175 */
176png_charp /* PRIVATE */
177png_decompress_chunk(png_structp png_ptr, int comp_type,
178 png_charp chunkdata, png_size_t chunklength,
179 png_size_t prefix_size, png_size_t *newlength)
180{
181 static char msg[] = "Error decoding compressed text";
182 png_charp text = NULL;
183 png_size_t text_size;
184
185 if (comp_type == PNG_COMPRESSION_TYPE_BASE)
186 {
187 int ret = Z_OK;
188 png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
189 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
190 png_ptr->zstream.next_out = png_ptr->zbuf;
191 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
192
193 text_size = 0;
194 text = NULL;
195
196 while (png_ptr->zstream.avail_in)
197 {
198 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
199 if (ret != Z_OK && ret != Z_STREAM_END)
200 {
201 if (png_ptr->zstream.msg != NULL)
202 png_warning(png_ptr, png_ptr->zstream.msg);
203 else
204 png_warning(png_ptr, msg);
205 inflateReset(&png_ptr->zstream);
206 png_ptr->zstream.avail_in = 0;
207
208 if (text == NULL)
209 {
210 text_size = prefix_size + sizeof(msg) + 1;
211 text = (png_charp)png_malloc_warn(png_ptr, text_size);
212 if (text == NULL)
213 {
214 png_free(png_ptr,chunkdata);
215 png_error(png_ptr,"Not enough memory to decompress chunk");
216 }
217 png_memcpy(text, chunkdata, prefix_size);
218 }
219
220 text[text_size - 1] = 0x00;
221
222 /* Copy what we can of the error message into the text chunk */
223 text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
224 text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
225 png_memcpy(text + prefix_size, msg, text_size + 1);
226 break;
227 }
228 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
229 {
230 if (text == NULL)
231 {
232 text_size = prefix_size +
233 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
234 text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
235 if (text == NULL)
236 {
237 png_free(png_ptr,chunkdata);
238 png_error(png_ptr,"Not enough memory to decompress chunk.");
239 }
240 png_memcpy(text + prefix_size, png_ptr->zbuf,
241 text_size - prefix_size);
242 png_memcpy(text, chunkdata, prefix_size);
243 *(text + text_size) = 0x00;
244 }
245 else
246 {
247 png_charp tmp;
248
249 tmp = text;
250 text = (png_charp)png_malloc_warn(png_ptr,
251 (png_uint_32)(text_size +
252 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
253 if (text == NULL)
254 {
255 png_free(png_ptr, tmp);
256 png_free(png_ptr, chunkdata);
257 png_error(png_ptr,"Not enough memory to decompress chunk..");
258 }
259 png_memcpy(text, tmp, text_size);
260 png_free(png_ptr, tmp);
261 png_memcpy(text + text_size, png_ptr->zbuf,
262 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
263 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
264 *(text + text_size) = 0x00;
265 }
266 if (ret == Z_STREAM_END)
267 break;
268 else
269 {
270 png_ptr->zstream.next_out = png_ptr->zbuf;
271 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
272 }
273 }
274 }
275 if (ret != Z_STREAM_END)
276 {
277#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
278 char umsg[50];
279
280 if (ret == Z_BUF_ERROR)
281 sprintf(umsg,"Buffer error in compressed datastream in %s chunk",
282 png_ptr->chunk_name);
283 else if (ret == Z_DATA_ERROR)
284 sprintf(umsg,"Data error in compressed datastream in %s chunk",
285 png_ptr->chunk_name);
286 else
287 sprintf(umsg,"Incomplete compressed datastream in %s chunk",
288 png_ptr->chunk_name);
289 png_warning(png_ptr, umsg);
290#else
291 png_warning(png_ptr,
292 "Incomplete compressed datastream in chunk other than IDAT");
293#endif
294 text_size=prefix_size;
295 if (text == NULL)
296 {
297 text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
298 if (text == NULL)
299 {
300 png_free(png_ptr, chunkdata);
301 png_error(png_ptr,"Not enough memory for text.");
302 }
303 png_memcpy(text, chunkdata, prefix_size);
304 }
305 *(text + text_size) = 0x00;
306 }
307
308 inflateReset(&png_ptr->zstream);
309 png_ptr->zstream.avail_in = 0;
310
311 png_free(png_ptr, chunkdata);
312 chunkdata = text;
313 *newlength=text_size;
314 }
315 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
316 {
317#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
318 char umsg[50];
319
320 sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
321 png_warning(png_ptr, umsg);
322#else
323 png_warning(png_ptr, "Unknown zTXt compression type");
324#endif
325
326 *(chunkdata + prefix_size) = 0x00;
327 *newlength=prefix_size;
328 }
329
330 return chunkdata;
331}
332#endif
333
334/* read and check the IDHR chunk */
335void /* PRIVATE */
336png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
337{
338 png_byte buf[13];
339 png_uint_32 width, height;
340 int bit_depth, color_type, compression_type, filter_type;
341 int interlace_type;
342
343 png_debug(1, "in png_handle_IHDR\n");
344
345 if (png_ptr->mode & PNG_HAVE_IHDR)
346 png_error(png_ptr, "Out of place IHDR");
347
348 /* check the length */
349 if (length != 13)
350 png_error(png_ptr, "Invalid IHDR chunk");
351
352 png_ptr->mode |= PNG_HAVE_IHDR;
353
354 png_crc_read(png_ptr, buf, 13);
355 png_crc_finish(png_ptr, 0);
356
357 width = png_get_uint_32(buf);
358 height = png_get_uint_32(buf + 4);
359 bit_depth = buf[8];
360 color_type = buf[9];
361 compression_type = buf[10];
362 filter_type = buf[11];
363 interlace_type = buf[12];
364
365
366 /* set internal variables */
367 png_ptr->width = width;
368 png_ptr->height = height;
369 png_ptr->bit_depth = (png_byte)bit_depth;
370 png_ptr->interlaced = (png_byte)interlace_type;
371 png_ptr->color_type = (png_byte)color_type;
372#if defined(PNG_MNG_FEATURES_SUPPORTED)
373 png_ptr->filter_type = (png_byte)filter_type;
374#endif
375
376 /* find number of channels */
377 switch (png_ptr->color_type)
378 {
379 case PNG_COLOR_TYPE_GRAY:
380 case PNG_COLOR_TYPE_PALETTE:
381 png_ptr->channels = 1;
382 break;
383 case PNG_COLOR_TYPE_RGB:
384 png_ptr->channels = 3;
385 break;
386 case PNG_COLOR_TYPE_GRAY_ALPHA:
387 png_ptr->channels = 2;
388 break;
389 case PNG_COLOR_TYPE_RGB_ALPHA:
390 png_ptr->channels = 4;
391 break;
392 }
393
394 /* set up other useful info */
395 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
396 png_ptr->channels);
397 png_ptr->rowbytes = ((png_ptr->width *
398 (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
399 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
400 png_debug1(3,"channels = %d\n", png_ptr->channels);
401 png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
402 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
403 color_type, interlace_type, compression_type, filter_type);
404}
405
406/* read and check the palette */
407void /* PRIVATE */
408png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
409{
410 png_color palette[PNG_MAX_PALETTE_LENGTH];
411 int num, i;
412#ifndef PNG_NO_POINTER_INDEXING
413 png_colorp pal_ptr;
414#endif
415
416 png_debug(1, "in png_handle_PLTE\n");
417
418 if (!(png_ptr->mode & PNG_HAVE_IHDR))
419 png_error(png_ptr, "Missing IHDR before PLTE");
420 else if (png_ptr->mode & PNG_HAVE_IDAT)
421 {
422 png_warning(png_ptr, "Invalid PLTE after IDAT");
423 png_crc_finish(png_ptr, length);
424 return;
425 }
426 else if (png_ptr->mode & PNG_HAVE_PLTE)
427 png_error(png_ptr, "Duplicate PLTE chunk");
428
429 png_ptr->mode |= PNG_HAVE_PLTE;
430
431 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
432 {
433 png_warning(png_ptr,
434 "Ignoring PLTE chunk in grayscale PNG");
435 png_crc_finish(png_ptr, length);
436 return;
437 }
438#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
439 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
440 {
441 png_crc_finish(png_ptr, length);
442 return;
443 }
444#endif
445
446 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
447 {
448 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
449 {
450 png_warning(png_ptr, "Invalid palette chunk");
451 png_crc_finish(png_ptr, length);
452 return;
453 }
454 else
455 {
456 png_error(png_ptr, "Invalid palette chunk");
457 }
458 }
459
460 num = (int)length / 3;
461
462#ifndef PNG_NO_POINTER_INDEXING
463 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
464 {
465 png_byte buf[3];
466
467 png_crc_read(png_ptr, buf, 3);
468 pal_ptr->red = buf[0];
469 pal_ptr->green = buf[1];
470 pal_ptr->blue = buf[2];
471 }
472#else
473 for (i = 0; i < num; i++)
474 {
475 png_byte buf[3];
476
477 png_crc_read(png_ptr, buf, 3);
478 /* don't depend upon png_color being any order */
479 palette[i].red = buf[0];
480 palette[i].green = buf[1];
481 palette[i].blue = buf[2];
482 }
483#endif
484
485 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
486 whatever the normal CRC configuration tells us. However, if we
487 have an RGB image, the PLTE can be considered ancillary, so
488 we will act as though it is. */
489#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
490 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
491#endif
492 {
493 png_crc_finish(png_ptr, 0);
494 }
495#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
496 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
497 {
498 /* If we don't want to use the data from an ancillary chunk,
499 we have two options: an error abort, or a warning and we
500 ignore the data in this chunk (which should be OK, since
501 it's considered ancillary for a RGB or RGBA image). */
502 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
503 {
504 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
505 {
506 png_chunk_error(png_ptr, "CRC error");
507 }
508 else
509 {
510 png_chunk_warning(png_ptr, "CRC error");
511 return;
512 }
513 }
514 /* Otherwise, we (optionally) emit a warning and use the chunk. */
515 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
516 {
517 png_chunk_warning(png_ptr, "CRC error");
518 }
519 }
520#endif
521
522 png_set_PLTE(png_ptr, info_ptr, palette, num);
523
524#if defined(PNG_READ_tRNS_SUPPORTED)
525 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
526 {
527 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
528 {
529 if (png_ptr->num_trans > (png_uint_16)num)
530 {
531 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
532 png_ptr->num_trans = (png_uint_16)num;
533 }
534 if (info_ptr->num_trans > (png_uint_16)num)
535 {
536 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
537 info_ptr->num_trans = (png_uint_16)num;
538 }
539 }
540 }
541#endif
542
543}
544
545void /* PRIVATE */
546png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
547{
548 png_debug(1, "in png_handle_IEND\n");
549
550 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
551 {
552 png_error(png_ptr, "No image in file");
553
554 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
555 }
556
557 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
558
559 if (length != 0)
560 {
561 png_warning(png_ptr, "Incorrect IEND chunk length");
562 }
563 png_crc_finish(png_ptr, length);
564}
565
566#if defined(PNG_READ_gAMA_SUPPORTED)
567void /* PRIVATE */
568png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
569{
570 png_fixed_point igamma;
571#ifdef PNG_FLOATING_POINT_SUPPORTED
572 float file_gamma;
573#endif
574 png_byte buf[4];
575
576 png_debug(1, "in png_handle_gAMA\n");
577
578 if (!(png_ptr->mode & PNG_HAVE_IHDR))
579 png_error(png_ptr, "Missing IHDR before gAMA");
580 else if (png_ptr->mode & PNG_HAVE_IDAT)
581 {
582 png_warning(png_ptr, "Invalid gAMA after IDAT");
583 png_crc_finish(png_ptr, length);
584 return;
585 }
586 else if (png_ptr->mode & PNG_HAVE_PLTE)
587 /* Should be an error, but we can cope with it */
588 png_warning(png_ptr, "Out of place gAMA chunk");
589
590 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
591#if defined(PNG_READ_sRGB_SUPPORTED)
592 && !(info_ptr->valid & PNG_INFO_sRGB)
593#endif
594 )
595 {
596 png_warning(png_ptr, "Duplicate gAMA chunk");
597 png_crc_finish(png_ptr, length);
598 return;
599 }
600
601 if (length != 4)
602 {
603 png_warning(png_ptr, "Incorrect gAMA chunk length");
604 png_crc_finish(png_ptr, length);
605 return;
606 }
607
608 png_crc_read(png_ptr, buf, 4);
609 if (png_crc_finish(png_ptr, 0))
610 return;
611
612 igamma = (png_fixed_point)png_get_uint_32(buf);
613 /* check for zero gamma */
614 if (igamma == 0)
615 {
616 png_warning(png_ptr,
617 "Ignoring gAMA chunk with gamma=0");
618 return;
619 }
620
621#if defined(PNG_READ_sRGB_SUPPORTED)
622 if (info_ptr->valid & PNG_INFO_sRGB)
623 if(igamma < 45000L || igamma > 46000L)
624 {
625 png_warning(png_ptr,
626 "Ignoring incorrect gAMA value when sRGB is also present");
627#ifndef PNG_NO_CONSOLE_IO
628 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
629#endif
630 return;
631 }
632#endif /* PNG_READ_sRGB_SUPPORTED */
633
634#ifdef PNG_FLOATING_POINT_SUPPORTED
635 file_gamma = (float)igamma / (float)100000.0;
636# ifdef PNG_READ_GAMMA_SUPPORTED
637 png_ptr->gamma = file_gamma;
638# endif
639 png_set_gAMA(png_ptr, info_ptr, file_gamma);
640#endif
641#ifdef PNG_FIXED_POINT_SUPPORTED
642 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
643#endif
644}
645#endif
646
647#if defined(PNG_READ_sBIT_SUPPORTED)
648void /* PRIVATE */
649png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
650{
651 png_size_t truelen;
652 png_byte buf[4];
653
654 png_debug(1, "in png_handle_sBIT\n");
655
656 buf[0] = buf[1] = buf[2] = buf[3] = 0;
657
658 if (!(png_ptr->mode & PNG_HAVE_IHDR))
659 png_error(png_ptr, "Missing IHDR before sBIT");
660 else if (png_ptr->mode & PNG_HAVE_IDAT)
661 {
662 png_warning(png_ptr, "Invalid sBIT after IDAT");
663 png_crc_finish(png_ptr, length);
664 return;
665 }
666 else if (png_ptr->mode & PNG_HAVE_PLTE)
667 {
668 /* Should be an error, but we can cope with it */
669 png_warning(png_ptr, "Out of place sBIT chunk");
670 }
671 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
672 {
673 png_warning(png_ptr, "Duplicate sBIT chunk");
674 png_crc_finish(png_ptr, length);
675 return;
676 }
677
678 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
679 truelen = 3;
680 else
681 truelen = (png_size_t)png_ptr->channels;
682
683 if (length != truelen)
684 {
685 png_warning(png_ptr, "Incorrect sBIT chunk length");
686 png_crc_finish(png_ptr, length);
687 return;
688 }
689
690 png_crc_read(png_ptr, buf, truelen);
691 if (png_crc_finish(png_ptr, 0))
692 return;
693
694 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
695 {
696 png_ptr->sig_bit.red = buf[0];
697 png_ptr->sig_bit.green = buf[1];
698 png_ptr->sig_bit.blue = buf[2];
699 png_ptr->sig_bit.alpha = buf[3];
700 }
701 else
702 {
703 png_ptr->sig_bit.gray = buf[0];
704 png_ptr->sig_bit.red = buf[0];
705 png_ptr->sig_bit.green = buf[0];
706 png_ptr->sig_bit.blue = buf[0];
707 png_ptr->sig_bit.alpha = buf[1];
708 }
709 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
710}
711#endif
712
713#if defined(PNG_READ_cHRM_SUPPORTED)
714void /* PRIVATE */
715png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
716{
717 png_byte buf[4];
718#ifdef PNG_FLOATING_POINT_SUPPORTED
719 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
720#endif
721 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
722 int_y_green, int_x_blue, int_y_blue;
723
724 png_uint_32 uint_x, uint_y;
725
726 png_debug(1, "in png_handle_cHRM\n");
727
728 if (!(png_ptr->mode & PNG_HAVE_IHDR))
729 png_error(png_ptr, "Missing IHDR before cHRM");
730 else if (png_ptr->mode & PNG_HAVE_IDAT)
731 {
732 png_warning(png_ptr, "Invalid cHRM after IDAT");
733 png_crc_finish(png_ptr, length);
734 return;
735 }
736 else if (png_ptr->mode & PNG_HAVE_PLTE)
737 /* Should be an error, but we can cope with it */
738 png_warning(png_ptr, "Missing PLTE before cHRM");
739
740 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
741#if defined(PNG_READ_sRGB_SUPPORTED)
742 && !(info_ptr->valid & PNG_INFO_sRGB)
743#endif
744 )
745 {
746 png_warning(png_ptr, "Duplicate cHRM chunk");
747 png_crc_finish(png_ptr, length);
748 return;
749 }
750
751 if (length != 32)
752 {
753 png_warning(png_ptr, "Incorrect cHRM chunk length");
754 png_crc_finish(png_ptr, length);
755 return;
756 }
757
758 png_crc_read(png_ptr, buf, 4);
759 uint_x = png_get_uint_32(buf);
760
761 png_crc_read(png_ptr, buf, 4);
762 uint_y = png_get_uint_32(buf);
763
764 if (uint_x > 80000L || uint_y > 80000L ||
765 uint_x + uint_y > 100000L)
766 {
767 png_warning(png_ptr, "Invalid cHRM white point");
768 png_crc_finish(png_ptr, 24);
769 return;
770 }
771 int_x_white = (png_fixed_point)uint_x;
772 int_y_white = (png_fixed_point)uint_y;
773
774 png_crc_read(png_ptr, buf, 4);
775 uint_x = png_get_uint_32(buf);
776
777 png_crc_read(png_ptr, buf, 4);
778 uint_y = png_get_uint_32(buf);
779
780 if (uint_x > 80000L || uint_y > 80000L ||
781 uint_x + uint_y > 100000L)
782 {
783 png_warning(png_ptr, "Invalid cHRM red point");
784 png_crc_finish(png_ptr, 16);
785 return;
786 }
787 int_x_red = (png_fixed_point)uint_x;
788 int_y_red = (png_fixed_point)uint_y;
789
790 png_crc_read(png_ptr, buf, 4);
791 uint_x = png_get_uint_32(buf);
792
793 png_crc_read(png_ptr, buf, 4);
794 uint_y = png_get_uint_32(buf);
795
796 if (uint_x > 80000L || uint_y > 80000L ||
797 uint_x + uint_y > 100000L)
798 {
799 png_warning(png_ptr, "Invalid cHRM green point");
800 png_crc_finish(png_ptr, 8);
801 return;
802 }
803 int_x_green = (png_fixed_point)uint_x;
804 int_y_green = (png_fixed_point)uint_y;
805
806 png_crc_read(png_ptr, buf, 4);
807 uint_x = png_get_uint_32(buf);
808
809 png_crc_read(png_ptr, buf, 4);
810 uint_y = png_get_uint_32(buf);
811
812 if (uint_x > 80000L || uint_y > 80000L ||
813 uint_x + uint_y > 100000L)
814 {
815 png_warning(png_ptr, "Invalid cHRM blue point");
816 png_crc_finish(png_ptr, 0);
817 return;
818 }
819 int_x_blue = (png_fixed_point)uint_x;
820 int_y_blue = (png_fixed_point)uint_y;
821
822#ifdef PNG_FLOATING_POINT_SUPPORTED
823 white_x = (float)int_x_white / (float)100000.0;
824 white_y = (float)int_y_white / (float)100000.0;
825 red_x = (float)int_x_red / (float)100000.0;
826 red_y = (float)int_y_red / (float)100000.0;
827 green_x = (float)int_x_green / (float)100000.0;
828 green_y = (float)int_y_green / (float)100000.0;
829 blue_x = (float)int_x_blue / (float)100000.0;
830 blue_y = (float)int_y_blue / (float)100000.0;
831#endif
832
833#if defined(PNG_READ_sRGB_SUPPORTED)
834 if (info_ptr->valid & PNG_INFO_sRGB)
835 {
836 if (abs(int_x_white - 31270L) > 1000 ||
837 abs(int_y_white - 32900L) > 1000 ||
838 abs(int_x_red - 64000L) > 1000 ||
839 abs(int_y_red - 33000L) > 1000 ||
840 abs(int_x_green - 30000L) > 1000 ||
841 abs(int_y_green - 60000L) > 1000 ||
842 abs(int_x_blue - 15000L) > 1000 ||
843 abs(int_y_blue - 6000L) > 1000)
844 {
845
846 png_warning(png_ptr,
847 "Ignoring incorrect cHRM value when sRGB is also present");
848#ifndef PNG_NO_CONSOLE_IO
849#ifdef PNG_FLOATING_POINT_SUPPORTED
850 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
851 white_x, white_y, red_x, red_y);
852 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
853 green_x, green_y, blue_x, blue_y);
854#else
855 fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
856 int_x_white, int_y_white, int_x_red, int_y_red);
857 fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
858 int_x_green, int_y_green, int_x_blue, int_y_blue);
859#endif
860#endif /* PNG_NO_CONSOLE_IO */
861 }
862 png_crc_finish(png_ptr, 0);
863 return;
864 }
865#endif /* PNG_READ_sRGB_SUPPORTED */
866
867#ifdef PNG_FLOATING_POINT_SUPPORTED
868 png_set_cHRM(png_ptr, info_ptr,
869 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
870#endif
871#ifdef PNG_FIXED_POINT_SUPPORTED
872 png_set_cHRM_fixed(png_ptr, info_ptr,
873 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
874 int_y_green, int_x_blue, int_y_blue);
875#endif
876 if (png_crc_finish(png_ptr, 0))
877 return;
878}
879#endif
880
881#if defined(PNG_READ_sRGB_SUPPORTED)
882void /* PRIVATE */
883png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
884{
885 int intent;
886 png_byte buf[1];
887
888 png_debug(1, "in png_handle_sRGB\n");
889
890 if (!(png_ptr->mode & PNG_HAVE_IHDR))
891 png_error(png_ptr, "Missing IHDR before sRGB");
892 else if (png_ptr->mode & PNG_HAVE_IDAT)
893 {
894 png_warning(png_ptr, "Invalid sRGB after IDAT");
895 png_crc_finish(png_ptr, length);
896 return;
897 }
898 else if (png_ptr->mode & PNG_HAVE_PLTE)
899 /* Should be an error, but we can cope with it */
900 png_warning(png_ptr, "Out of place sRGB chunk");
901
902 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
903 {
904 png_warning(png_ptr, "Duplicate sRGB chunk");
905 png_crc_finish(png_ptr, length);
906 return;
907 }
908
909 if (length != 1)
910 {
911 png_warning(png_ptr, "Incorrect sRGB chunk length");
912 png_crc_finish(png_ptr, length);
913 return;
914 }
915
916 png_crc_read(png_ptr, buf, 1);
917 if (png_crc_finish(png_ptr, 0))
918 return;
919
920 intent = buf[0];
921 /* check for bad intent */
922 if (intent >= PNG_sRGB_INTENT_LAST)
923 {
924 png_warning(png_ptr, "Unknown sRGB intent");
925 return;
926 }
927
928#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
929 if ((info_ptr->valid & PNG_INFO_gAMA))
930 {
931 int igamma;
932#ifdef PNG_FIXED_POINT_SUPPORTED
933 igamma=(int)info_ptr->int_gamma;
934#else
935# ifdef PNG_FLOATING_POINT_SUPPORTED
936 igamma=(int)(info_ptr->gamma * 100000.);
937# endif
938#endif
939 if(igamma < 45000L || igamma > 46000L)
940 {
941 png_warning(png_ptr,
942 "Ignoring incorrect gAMA value when sRGB is also present");
943#ifndef PNG_NO_CONSOLE_IO
944# ifdef PNG_FIXED_POINT_SUPPORTED
945 fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
946# else
947# ifdef PNG_FLOATING_POINT_SUPPORTED
948 fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
949# endif
950# endif
951#endif
952 }
953 }
954#endif /* PNG_READ_gAMA_SUPPORTED */
955
956#ifdef PNG_READ_cHRM_SUPPORTED
957#ifdef PNG_FIXED_POINT_SUPPORTED
958 if (info_ptr->valid & PNG_INFO_cHRM)
959 if (abs(info_ptr->int_x_white - 31270L) > 1000 ||
960 abs(info_ptr->int_y_white - 32900L) > 1000 ||
961 abs(info_ptr->int_x_red - 64000L) > 1000 ||
962 abs(info_ptr->int_y_red - 33000L) > 1000 ||
963 abs(info_ptr->int_x_green - 30000L) > 1000 ||
964 abs(info_ptr->int_y_green - 60000L) > 1000 ||
965 abs(info_ptr->int_x_blue - 15000L) > 1000 ||
966 abs(info_ptr->int_y_blue - 6000L) > 1000)
967 {
968 png_warning(png_ptr,
969 "Ignoring incorrect cHRM value when sRGB is also present");
970 }
971#endif /* PNG_FIXED_POINT_SUPPORTED */
972#endif /* PNG_READ_cHRM_SUPPORTED */
973
974 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
975}
976#endif /* PNG_READ_sRGB_SUPPORTED */
977
978#if defined(PNG_READ_iCCP_SUPPORTED)
979void /* PRIVATE */
980png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
981/* Note: this does not properly handle chunks that are > 64K under DOS */
982{
983 png_charp chunkdata;
984 png_byte compression_type;
985 png_bytep pC;
986 png_charp profile;
987 png_uint_32 skip = 0;
988 png_uint_32 profile_size, profile_length;
989 png_size_t slength, prefix_length, data_length;
990
991 png_debug(1, "in png_handle_iCCP\n");
992
993 if (!(png_ptr->mode & PNG_HAVE_IHDR))
994 png_error(png_ptr, "Missing IHDR before iCCP");
995 else if (png_ptr->mode & PNG_HAVE_IDAT)
996 {
997 png_warning(png_ptr, "Invalid iCCP after IDAT");
998 png_crc_finish(png_ptr, length);
999 return;
1000 }
1001 else if (png_ptr->mode & PNG_HAVE_PLTE)
1002 /* Should be an error, but we can cope with it */
1003 png_warning(png_ptr, "Out of place iCCP chunk");
1004
1005 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1006 {
1007 png_warning(png_ptr, "Duplicate iCCP chunk");
1008 png_crc_finish(png_ptr, length);
1009 return;
1010 }
1011
1012#ifdef PNG_MAX_MALLOC_64K
1013 if (length > (png_uint_32)65535L)
1014 {
1015 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1016 skip = length - (png_uint_32)65535L;
1017 length = (png_uint_32)65535L;
1018 }
1019#endif
1020
1021 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1022 slength = (png_size_t)length;
1023 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1024
1025 if (png_crc_finish(png_ptr, skip))
1026 {
1027 png_free(png_ptr, chunkdata);
1028 return;
1029 }
1030
1031 chunkdata[slength] = 0x00;
1032
1033 for (profile = chunkdata; *profile; profile++)
1034 /* empty loop to find end of name */ ;
1035
1036 ++profile;
1037
1038 /* there should be at least one zero (the compression type byte)
1039 following the separator, and we should be on it */
1040 if ( profile >= chunkdata + slength)
1041 {
1042 png_free(png_ptr, chunkdata);
1043 png_warning(png_ptr, "Malformed iCCP chunk");
1044 return;
1045 }
1046
1047 /* compression_type should always be zero */
1048 compression_type = *profile++;
1049 if (compression_type)
1050 {
1051 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1052 compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1053 wrote nonzero) */
1054 }
1055
1056 prefix_length = profile - chunkdata;
1057 chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
1058 slength, prefix_length, &data_length);
1059
1060 profile_length = data_length - prefix_length;
1061
1062 if ( prefix_length > data_length || profile_length < 4)
1063 {
1064 png_free(png_ptr, chunkdata);
1065 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1066 return;
1067 }
1068
1069 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1070 pC = (png_bytep)(chunkdata+prefix_length);
1071 profile_size = ((*(pC ))<<24) |
1072 ((*(pC+1))<<16) |
1073 ((*(pC+2))<< 8) |
1074 ((*(pC+3)) );
1075
1076 if(profile_size < profile_length)
1077 profile_length = profile_size;
1078
1079 if(profile_size > profile_length)
1080 {
1081 png_free(png_ptr, chunkdata);
1082 png_warning(png_ptr, "Ignoring truncated iCCP profile.\n");
1083 return;
1084 }
1085
1086 png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
1087 chunkdata + prefix_length, profile_length);
1088 png_free(png_ptr, chunkdata);
1089}
1090#endif /* PNG_READ_iCCP_SUPPORTED */
1091
1092#if defined(PNG_READ_sPLT_SUPPORTED)
1093void /* PRIVATE */
1094png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1095/* Note: this does not properly handle chunks that are > 64K under DOS */
1096{
1097 png_bytep chunkdata;
1098 png_bytep entry_start;
1099 png_sPLT_t new_palette;
1100#ifdef PNG_NO_POINTER_INDEXING
1101 png_sPLT_entryp pp;
1102#endif
1103 int data_length, entry_size, i;
1104 png_uint_32 skip = 0;
1105 png_size_t slength;
1106
1107 png_debug(1, "in png_handle_sPLT\n");
1108
1109 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1110 png_error(png_ptr, "Missing IHDR before sPLT");
1111 else if (png_ptr->mode & PNG_HAVE_IDAT)
1112 {
1113 png_warning(png_ptr, "Invalid sPLT after IDAT");
1114 png_crc_finish(png_ptr, length);
1115 return;
1116 }
1117
1118#ifdef PNG_MAX_MALLOC_64K
1119 if (length > (png_uint_32)65535L)
1120 {
1121 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1122 skip = length - (png_uint_32)65535L;
1123 length = (png_uint_32)65535L;
1124 }
1125#endif
1126
1127 chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
1128 slength = (png_size_t)length;
1129 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1130
1131 if (png_crc_finish(png_ptr, skip))
1132 {
1133 png_free(png_ptr, chunkdata);
1134 return;
1135 }
1136
1137 chunkdata[slength] = 0x00;
1138
1139 for (entry_start = chunkdata; *entry_start; entry_start++)
1140 /* empty loop to find end of name */ ;
1141 ++entry_start;
1142
1143 /* a sample depth should follow the separator, and we should be on it */
1144 if (entry_start > chunkdata + slength)
1145 {
1146 png_free(png_ptr, chunkdata);
1147 png_warning(png_ptr, "malformed sPLT chunk");
1148 return;
1149 }
1150
1151 new_palette.depth = *entry_start++;
1152 entry_size = (new_palette.depth == 8 ? 6 : 10);
1153 data_length = (slength - (entry_start - chunkdata));
1154
1155 /* integrity-check the data length */
1156 if (data_length % entry_size)
1157 {
1158 png_free(png_ptr, chunkdata);
1159 png_warning(png_ptr, "sPLT chunk has bad length");
1160 return;
1161 }
1162
1163 new_palette.nentries = data_length / entry_size;
1164 if (new_palette.nentries > PNG_SIZE_MAX / sizeof(png_sPLT_entry))
1165 {
1166 png_warning(png_ptr, "sPLT chunk too long");
1167 return;
1168 }
1169 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1170 png_ptr, new_palette.nentries * sizeof(png_sPLT_entry));
1171 if (new_palette.entries == NULL)
1172 {
1173 png_warning(png_ptr, "sPLT chunk requires too much memory");
1174 return;
1175 }
1176
1177#ifndef PNG_NO_POINTER_INDEXING
1178 for (i = 0; i < new_palette.nentries; i++)
1179 {
1180 png_sPLT_entryp pp = new_palette.entries + i;
1181
1182 if (new_palette.depth == 8)
1183 {
1184 pp->red = *entry_start++;
1185 pp->green = *entry_start++;
1186 pp->blue = *entry_start++;
1187 pp->alpha = *entry_start++;
1188 }
1189 else
1190 {
1191 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1192 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1193 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1194 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1195 }
1196 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1197 }
1198#else
1199 pp = new_palette.entries;
1200 for (i = 0; i < new_palette.nentries; i++)
1201 {
1202
1203 if (new_palette.depth == 8)
1204 {
1205 pp[i].red = *entry_start++;
1206 pp[i].green = *entry_start++;
1207 pp[i].blue = *entry_start++;
1208 pp[i].alpha = *entry_start++;
1209 }
1210 else
1211 {
1212 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1213 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1214 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1215 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1216 }
1217 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1218 }
1219#endif
1220
1221 /* discard all chunk data except the name and stash that */
1222 new_palette.name = (png_charp)chunkdata;
1223
1224 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1225
1226 png_free(png_ptr, chunkdata);
1227 png_free(png_ptr, new_palette.entries);
1228}
1229#endif /* PNG_READ_sPLT_SUPPORTED */
1230
1231#if defined(PNG_READ_tRNS_SUPPORTED)
1232void /* PRIVATE */
1233png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1234{
1235 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1236
1237 png_debug(1, "in png_handle_tRNS\n");
1238
1239 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1240 png_error(png_ptr, "Missing IHDR before tRNS");
1241 else if (png_ptr->mode & PNG_HAVE_IDAT)
1242 {
1243 png_warning(png_ptr, "Invalid tRNS after IDAT");
1244 png_crc_finish(png_ptr, length);
1245 return;
1246 }
1247 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1248 {
1249 png_warning(png_ptr, "Duplicate tRNS chunk");
1250 png_crc_finish(png_ptr, length);
1251 return;
1252 }
1253
1254 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1255 {
1256 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1257 {
1258 /* Should be an error, but we can cope with it */
1259 png_warning(png_ptr, "Missing PLTE before tRNS");
1260 }
1261 if (length > (png_uint_32)png_ptr->num_palette ||
1262 length > PNG_MAX_PALETTE_LENGTH)
1263 {
1264 png_warning(png_ptr, "Incorrect tRNS chunk length");
1265 png_crc_finish(png_ptr, length);
1266 return;
1267 }
1268 if (length == 0)
1269 {
1270 png_warning(png_ptr, "Zero length tRNS chunk");
1271 png_crc_finish(png_ptr, length);
1272 return;
1273 }
1274
1275 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1276 png_ptr->num_trans = (png_uint_16)length;
1277 }
1278 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1279 {
1280 png_byte buf[6];
1281
1282 if (length != 6)
1283 {
1284 png_warning(png_ptr, "Incorrect tRNS chunk length");
1285 png_crc_finish(png_ptr, length);
1286 return;
1287 }
1288
1289 png_crc_read(png_ptr, buf, (png_size_t)length);
1290 png_ptr->num_trans = 1;
1291 png_ptr->trans_values.red = png_get_uint_16(buf);
1292 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1293 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1294 }
1295 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1296 {
1297 png_byte buf[6];
1298
1299 if (length != 2)
1300 {
1301 png_warning(png_ptr, "Incorrect tRNS chunk length");
1302 png_crc_finish(png_ptr, length);
1303 return;
1304 }
1305
1306 png_crc_read(png_ptr, buf, 2);
1307 png_ptr->num_trans = 1;
1308 png_ptr->trans_values.gray = png_get_uint_16(buf);
1309 }
1310 else
1311 {
1312 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1313 png_crc_finish(png_ptr, length);
1314 return;
1315 }
1316
1317 if (png_crc_finish(png_ptr, 0))
1318 return;
1319
1320 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1321 &(png_ptr->trans_values));
1322}
1323#endif
1324
1325#if defined(PNG_READ_bKGD_SUPPORTED)
1326void /* PRIVATE */
1327png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1328{
1329 png_size_t truelen;
1330 png_byte buf[6];
1331
1332 png_debug(1, "in png_handle_bKGD\n");
1333
1334 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1335 png_error(png_ptr, "Missing IHDR before bKGD");
1336 else if (png_ptr->mode & PNG_HAVE_IDAT)
1337 {
1338 png_warning(png_ptr, "Invalid bKGD after IDAT");
1339 png_crc_finish(png_ptr, length);
1340 return;
1341 }
1342 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1343 !(png_ptr->mode & PNG_HAVE_PLTE))
1344 {
1345 png_warning(png_ptr, "Missing PLTE before bKGD");
1346 png_crc_finish(png_ptr, length);
1347 return;
1348 }
1349 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1350 {
1351 png_warning(png_ptr, "Duplicate bKGD chunk");
1352 png_crc_finish(png_ptr, length);
1353 return;
1354 }
1355
1356 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1357 truelen = 1;
1358 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1359 truelen = 6;
1360 else
1361 truelen = 2;
1362
1363 if (length != truelen)
1364 {
1365 png_warning(png_ptr, "Incorrect bKGD chunk length");
1366 png_crc_finish(png_ptr, length);
1367 return;
1368 }
1369
1370 png_crc_read(png_ptr, buf, truelen);
1371 if (png_crc_finish(png_ptr, 0))
1372 return;
1373
1374 /* We convert the index value into RGB components so that we can allow
1375 * arbitrary RGB values for background when we have transparency, and
1376 * so it is easy to determine the RGB values of the background color
1377 * from the info_ptr struct. */
1378 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1379 {
1380 png_ptr->background.index = buf[0];
1381 if(info_ptr->num_palette)
1382 {
1383 if(buf[0] > info_ptr->num_palette)
1384 {
1385 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1386 return;
1387 }
1388 png_ptr->background.red =
1389 (png_uint_16)png_ptr->palette[buf[0]].red;
1390 png_ptr->background.green =
1391 (png_uint_16)png_ptr->palette[buf[0]].green;
1392 png_ptr->background.blue =
1393 (png_uint_16)png_ptr->palette[buf[0]].blue;
1394 }
1395 }
1396 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1397 {
1398 png_ptr->background.red =
1399 png_ptr->background.green =
1400 png_ptr->background.blue =
1401 png_ptr->background.gray = png_get_uint_16(buf);
1402 }
1403 else
1404 {
1405 png_ptr->background.red = png_get_uint_16(buf);
1406 png_ptr->background.green = png_get_uint_16(buf + 2);
1407 png_ptr->background.blue = png_get_uint_16(buf + 4);
1408 }
1409
1410 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1411}
1412#endif
1413
1414#if defined(PNG_READ_hIST_SUPPORTED)
1415void /* PRIVATE */
1416png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1417{
1418 int num, i;
1419 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1420
1421 png_debug(1, "in png_handle_hIST\n");
1422
1423 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1424 png_error(png_ptr, "Missing IHDR before hIST");
1425 else if (png_ptr->mode & PNG_HAVE_IDAT)
1426 {
1427 png_warning(png_ptr, "Invalid hIST after IDAT");
1428 png_crc_finish(png_ptr, length);
1429 return;
1430 }
1431 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1432 {
1433 png_warning(png_ptr, "Missing PLTE before hIST");
1434 png_crc_finish(png_ptr, length);
1435 return;
1436 }
1437 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1438 {
1439 png_warning(png_ptr, "Duplicate hIST chunk");
1440 png_crc_finish(png_ptr, length);
1441 return;
1442 }
1443
1444 num = (int)length / 2 ;
1445 if (num != png_ptr->num_palette)
1446 {
1447 png_warning(png_ptr, "Incorrect hIST chunk length");
1448 png_crc_finish(png_ptr, length);
1449 return;
1450 }
1451
1452 for (i = 0; i < num; i++)
1453 {
1454 png_byte buf[2];
1455
1456 png_crc_read(png_ptr, buf, 2);
1457 readbuf[i] = png_get_uint_16(buf);
1458 }
1459
1460 if (png_crc_finish(png_ptr, 0))
1461 return;
1462
1463 png_set_hIST(png_ptr, info_ptr, readbuf);
1464}
1465#endif
1466
1467#if defined(PNG_READ_pHYs_SUPPORTED)
1468void /* PRIVATE */
1469png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1470{
1471 png_byte buf[9];
1472 png_uint_32 res_x, res_y;
1473 int unit_type;
1474
1475 png_debug(1, "in png_handle_pHYs\n");
1476
1477 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1478 png_error(png_ptr, "Missing IHDR before pHYs");
1479 else if (png_ptr->mode & PNG_HAVE_IDAT)
1480 {
1481 png_warning(png_ptr, "Invalid pHYs after IDAT");
1482 png_crc_finish(png_ptr, length);
1483 return;
1484 }
1485 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1486 {
1487 png_warning(png_ptr, "Duplicate pHYs chunk");
1488 png_crc_finish(png_ptr, length);
1489 return;
1490 }
1491
1492 if (length != 9)
1493 {
1494 png_warning(png_ptr, "Incorrect pHYs chunk length");
1495 png_crc_finish(png_ptr, length);
1496 return;
1497 }
1498
1499 png_crc_read(png_ptr, buf, 9);
1500 if (png_crc_finish(png_ptr, 0))
1501 return;
1502
1503 res_x = png_get_uint_32(buf);
1504 res_y = png_get_uint_32(buf + 4);
1505 unit_type = buf[8];
1506 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1507}
1508#endif
1509
1510#if defined(PNG_READ_oFFs_SUPPORTED)
1511void /* PRIVATE */
1512png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1513{
1514 png_byte buf[9];
1515 png_int_32 offset_x, offset_y;
1516 int unit_type;
1517
1518 png_debug(1, "in png_handle_oFFs\n");
1519
1520 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1521 png_error(png_ptr, "Missing IHDR before oFFs");
1522 else if (png_ptr->mode & PNG_HAVE_IDAT)
1523 {
1524 png_warning(png_ptr, "Invalid oFFs after IDAT");
1525 png_crc_finish(png_ptr, length);
1526 return;
1527 }
1528 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1529 {
1530 png_warning(png_ptr, "Duplicate oFFs chunk");
1531 png_crc_finish(png_ptr, length);
1532 return;
1533 }
1534
1535 if (length != 9)
1536 {
1537 png_warning(png_ptr, "Incorrect oFFs chunk length");
1538 png_crc_finish(png_ptr, length);
1539 return;
1540 }
1541
1542 png_crc_read(png_ptr, buf, 9);
1543 if (png_crc_finish(png_ptr, 0))
1544 return;
1545
1546 offset_x = png_get_int_32(buf);
1547 offset_y = png_get_int_32(buf + 4);
1548 unit_type = buf[8];
1549 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1550}
1551#endif
1552
1553#if defined(PNG_READ_pCAL_SUPPORTED)
1554/* read the pCAL chunk (described in the PNG Extensions document) */
1555void /* PRIVATE */
1556png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1557{
1558 png_charp purpose;
1559 png_int_32 X0, X1;
1560 png_byte type, nparams;
1561 png_charp buf, units, endptr;
1562 png_charpp params;
1563 png_size_t slength;
1564 int i;
1565
1566 png_debug(1, "in png_handle_pCAL\n");
1567
1568 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1569 png_error(png_ptr, "Missing IHDR before pCAL");
1570 else if (png_ptr->mode & PNG_HAVE_IDAT)
1571 {
1572 png_warning(png_ptr, "Invalid pCAL after IDAT");
1573 png_crc_finish(png_ptr, length);
1574 return;
1575 }
1576 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1577 {
1578 png_warning(png_ptr, "Duplicate pCAL chunk");
1579 png_crc_finish(png_ptr, length);
1580 return;
1581 }
1582
1583 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
1584 length + 1);
1585 purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
1586 if (purpose == NULL)
1587 {
1588 png_warning(png_ptr, "No memory for pCAL purpose.");
1589 return;
1590 }
1591 slength = (png_size_t)length;
1592 png_crc_read(png_ptr, (png_bytep)purpose, slength);
1593
1594 if (png_crc_finish(png_ptr, 0))
1595 {
1596 png_free(png_ptr, purpose);
1597 return;
1598 }
1599
1600 purpose[slength] = 0x00; /* null terminate the last string */
1601
1602 png_debug(3, "Finding end of pCAL purpose string\n");
1603 for (buf = purpose; *buf; buf++)
1604 /* empty loop */ ;
1605
1606 endptr = purpose + slength;
1607
1608 /* We need to have at least 12 bytes after the purpose string
1609 in order to get the parameter information. */
1610 if (endptr <= buf + 12)
1611 {
1612 png_warning(png_ptr, "Invalid pCAL data");
1613 png_free(png_ptr, purpose);
1614 return;
1615 }
1616
1617 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1618 X0 = png_get_int_32((png_bytep)buf+1);
1619 X1 = png_get_int_32((png_bytep)buf+5);
1620 type = buf[9];
1621 nparams = buf[10];
1622 units = buf + 11;
1623
1624 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1625 /* Check that we have the right number of parameters for known
1626 equation types. */
1627 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1628 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1629 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1630 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1631 {
1632 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1633 png_free(png_ptr, purpose);
1634 return;
1635 }
1636 else if (type >= PNG_EQUATION_LAST)
1637 {
1638 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1639 }
1640
1641 for (buf = units; *buf; buf++)
1642 /* Empty loop to move past the units string. */ ;
1643
1644 png_debug(3, "Allocating pCAL parameters array\n");
1645 params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
1646 *sizeof(png_charp))) ;
1647 if (params == NULL)
1648 {
1649 png_free(png_ptr, purpose);
1650 png_warning(png_ptr, "No memory for pCAL params.");
1651 return;
1652 }
1653
1654 /* Get pointers to the start of each parameter string. */
1655 for (i = 0; i < (int)nparams; i++)
1656 {
1657 buf++; /* Skip the null string terminator from previous parameter. */
1658
1659 png_debug1(3, "Reading pCAL parameter %d\n", i);
1660 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
1661 /* Empty loop to move past each parameter string */ ;
1662
1663 /* Make sure we haven't run out of data yet */
1664 if (buf > endptr)
1665 {
1666 png_warning(png_ptr, "Invalid pCAL data");
1667 png_free(png_ptr, purpose);
1668 png_free(png_ptr, params);
1669 return;
1670 }
1671 }
1672
1673 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1674 units, params);
1675
1676 png_free(png_ptr, purpose);
1677 png_free(png_ptr, params);
1678}
1679#endif
1680
1681#if defined(PNG_READ_sCAL_SUPPORTED)
1682/* read the sCAL chunk */
1683void /* PRIVATE */
1684png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1685{
1686 png_charp buffer, ep;
1687#ifdef PNG_FLOATING_POINT_SUPPORTED
1688 double width, height;
1689 png_charp vp;
1690#else
1691#ifdef PNG_FIXED_POINT_SUPPORTED
1692 png_charp swidth, sheight;
1693#endif
1694#endif
1695 png_size_t slength;
1696
1697 png_debug(1, "in png_handle_sCAL\n");
1698
1699 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1700 png_error(png_ptr, "Missing IHDR before sCAL");
1701 else if (png_ptr->mode & PNG_HAVE_IDAT)
1702 {
1703 png_warning(png_ptr, "Invalid sCAL after IDAT");
1704 png_crc_finish(png_ptr, length);
1705 return;
1706 }
1707 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1708 {
1709 png_warning(png_ptr, "Duplicate sCAL chunk");
1710 png_crc_finish(png_ptr, length);
1711 return;
1712 }
1713
1714 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1715 length + 1);
1716 buffer = (png_charp)png_malloc_warn(png_ptr, length + 1);
1717 if (buffer == NULL)
1718 {
1719 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
1720 return;
1721 }
1722 slength = (png_size_t)length;
1723 png_crc_read(png_ptr, (png_bytep)buffer, slength);
1724
1725 if (png_crc_finish(png_ptr, 0))
1726 {
1727 png_free(png_ptr, buffer);
1728 return;
1729 }
1730
1731 buffer[slength] = 0x00; /* null terminate the last string */
1732
1733 ep = buffer + 1; /* skip unit byte */
1734
1735#ifdef PNG_FLOATING_POINT_SUPPORTED
1736 width = strtod(ep, &vp);
1737 if (*vp)
1738 {
1739 png_warning(png_ptr, "malformed width string in sCAL chunk");
1740 return;
1741 }
1742#else
1743#ifdef PNG_FIXED_POINT_SUPPORTED
1744 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1745 if (swidth == NULL)
1746 {
1747 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
1748 return;
1749 }
1750 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1751#endif
1752#endif
1753
1754 for (ep = buffer; *ep; ep++)
1755 /* empty loop */ ;
1756 ep++;
1757
1758#ifdef PNG_FLOATING_POINT_SUPPORTED
1759 height = strtod(ep, &vp);
1760 if (*vp)
1761 {
1762 png_warning(png_ptr, "malformed height string in sCAL chunk");
1763 return;
1764 }
1765#else
1766#ifdef PNG_FIXED_POINT_SUPPORTED
1767 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1768 if (swidth == NULL)
1769 {
1770 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
1771 return;
1772 }
1773 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1774#endif
1775#endif
1776
1777 if (buffer + slength < ep
1778#ifdef PNG_FLOATING_POINT_SUPPORTED
1779 || width <= 0. || height <= 0.
1780#endif
1781 )
1782 {
1783 png_warning(png_ptr, "Invalid sCAL data");
1784 png_free(png_ptr, buffer);
1785#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1786 png_free(png_ptr, swidth);
1787 png_free(png_ptr, sheight);
1788#endif
1789 return;
1790 }
1791
1792
1793#ifdef PNG_FLOATING_POINT_SUPPORTED
1794 png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1795#else
1796#ifdef PNG_FIXED_POINT_SUPPORTED
1797 png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1798#endif
1799#endif
1800
1801 png_free(png_ptr, buffer);
1802#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1803 png_free(png_ptr, swidth);
1804 png_free(png_ptr, sheight);
1805#endif
1806}
1807#endif
1808
1809#if defined(PNG_READ_tIME_SUPPORTED)
1810void /* PRIVATE */
1811png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1812{
1813 png_byte buf[7];
1814 png_time mod_time;
1815
1816 png_debug(1, "in png_handle_tIME\n");
1817
1818 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1819 png_error(png_ptr, "Out of place tIME chunk");
1820 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1821 {
1822 png_warning(png_ptr, "Duplicate tIME chunk");
1823 png_crc_finish(png_ptr, length);
1824 return;
1825 }
1826
1827 if (png_ptr->mode & PNG_HAVE_IDAT)
1828 png_ptr->mode |= PNG_AFTER_IDAT;
1829
1830 if (length != 7)
1831 {
1832 png_warning(png_ptr, "Incorrect tIME chunk length");
1833 png_crc_finish(png_ptr, length);
1834 return;
1835 }
1836
1837 png_crc_read(png_ptr, buf, 7);
1838 if (png_crc_finish(png_ptr, 0))
1839 return;
1840
1841 mod_time.second = buf[6];
1842 mod_time.minute = buf[5];
1843 mod_time.hour = buf[4];
1844 mod_time.day = buf[3];
1845 mod_time.month = buf[2];
1846 mod_time.year = png_get_uint_16(buf);
1847
1848 png_set_tIME(png_ptr, info_ptr, &mod_time);
1849}
1850#endif
1851
1852#if defined(PNG_READ_tEXt_SUPPORTED)
1853/* Note: this does not properly handle chunks that are > 64K under DOS */
1854void /* PRIVATE */
1855png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1856{
1857 png_textp text_ptr;
1858 png_charp key;
1859 png_charp text;
1860 png_uint_32 skip = 0;
1861 png_size_t slength;
1862 int ret;
1863
1864 png_debug(1, "in png_handle_tEXt\n");
1865
1866 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1867 png_error(png_ptr, "Missing IHDR before tEXt");
1868
1869 if (png_ptr->mode & PNG_HAVE_IDAT)
1870 png_ptr->mode |= PNG_AFTER_IDAT;
1871
1872#ifdef PNG_MAX_MALLOC_64K
1873 if (length > (png_uint_32)65535L)
1874 {
1875 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1876 skip = length - (png_uint_32)65535L;
1877 length = (png_uint_32)65535L;
1878 }
1879#endif
1880
1881 key = (png_charp)png_malloc_warn(png_ptr, length + 1);
1882 if (key == NULL)
1883 {
1884 png_warning(png_ptr, "No memory to process text chunk.");
1885 return;
1886 }
1887 slength = (png_size_t)length;
1888 png_crc_read(png_ptr, (png_bytep)key, slength);
1889
1890 if (png_crc_finish(png_ptr, skip))
1891 {
1892 png_free(png_ptr, key);
1893 return;
1894 }
1895
1896 key[slength] = 0x00;
1897
1898 for (text = key; *text; text++)
1899 /* empty loop to find end of key */ ;
1900
1901 if (text != key + slength)
1902 text++;
1903
1904 text_ptr = (png_textp)png_malloc_warn(png_ptr, (png_uint_32)sizeof(png_text));
1905 if (text_ptr == NULL)
1906 {
1907 png_warning(png_ptr, "Not enough memory to process text chunk.");
1908 png_free(png_ptr, key);
1909 return;
1910 }
1911 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1912 text_ptr->key = key;
1913#ifdef PNG_iTXt_SUPPORTED
1914 text_ptr->lang = NULL;
1915 text_ptr->lang_key = NULL;
1916 text_ptr->itxt_length = 0;
1917#endif
1918 text_ptr->text = text;
1919 text_ptr->text_length = png_strlen(text);
1920
1921 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
1922
1923 png_free(png_ptr, key);
1924 png_free(png_ptr, text_ptr);
1925 if (ret)
1926 png_warning(png_ptr, "Insufficient memory to process text chunk.");
1927}
1928#endif
1929
1930#if defined(PNG_READ_zTXt_SUPPORTED)
1931/* note: this does not correctly handle chunks that are > 64K under DOS */
1932void /* PRIVATE */
1933png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1934{
1935 png_textp text_ptr;
1936 png_charp chunkdata;
1937 png_charp text;
1938 int comp_type;
1939 int ret;
1940 png_size_t slength, prefix_len, data_len;
1941
1942 png_debug(1, "in png_handle_zTXt\n");
1943 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1944 png_error(png_ptr, "Missing IHDR before zTXt");
1945
1946 if (png_ptr->mode & PNG_HAVE_IDAT)
1947 png_ptr->mode |= PNG_AFTER_IDAT;
1948
1949#ifdef PNG_MAX_MALLOC_64K
1950 /* We will no doubt have problems with chunks even half this size, but
1951 there is no hard and fast rule to tell us where to stop. */
1952 if (length > (png_uint_32)65535L)
1953 {
1954 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1955 png_crc_finish(png_ptr, length);
1956 return;
1957 }
1958#endif
1959
1960 chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1961 if (chunkdata == NULL)
1962 {
1963 png_warning(png_ptr,"Out of memory processing zTXt chunk.");
1964 return;
1965 }
1966 slength = (png_size_t)length;
1967 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1968 if (png_crc_finish(png_ptr, 0))
1969 {
1970 png_free(png_ptr, chunkdata);
1971 return;
1972 }
1973
1974 chunkdata[slength] = 0x00;
1975
1976 for (text = chunkdata; *text; text++)
1977 /* empty loop */ ;
1978
1979 /* zTXt must have some text after the chunkdataword */
1980 if (text == chunkdata + slength)
1981 {
1982 comp_type = PNG_TEXT_COMPRESSION_NONE;
1983 png_warning(png_ptr, "Zero length zTXt chunk");
1984 }
1985 else
1986 {
1987 comp_type = *(++text);
1988 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
1989 {
1990 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
1991 comp_type = PNG_TEXT_COMPRESSION_zTXt;
1992 }
1993 text++; /* skip the compression_method byte */
1994 }
1995 prefix_len = text - chunkdata;
1996
1997 chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
1998 (png_size_t)length, prefix_len, &data_len);
1999
2000 text_ptr = (png_textp)png_malloc_warn(png_ptr, (png_uint_32)sizeof(png_text));
2001 if (text_ptr == NULL)
2002 {
2003 png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
2004 png_free(png_ptr, chunkdata);
2005 return;
2006 }
2007 text_ptr->compression = comp_type;
2008 text_ptr->key = chunkdata;
2009#ifdef PNG_iTXt_SUPPORTED
2010 text_ptr->lang = NULL;
2011 text_ptr->lang_key = NULL;
2012 text_ptr->itxt_length = 0;
2013#endif
2014 text_ptr->text = chunkdata + prefix_len;
2015 text_ptr->text_length = data_len;
2016
2017 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2018
2019 png_free(png_ptr, text_ptr);
2020 png_free(png_ptr, chunkdata);
2021 if (ret)
2022 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2023}
2024#endif
2025
2026#if defined(PNG_READ_iTXt_SUPPORTED)
2027/* note: this does not correctly handle chunks that are > 64K under DOS */
2028void /* PRIVATE */
2029png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2030{
2031 png_textp text_ptr;
2032 png_charp chunkdata;
2033 png_charp key, lang, text, lang_key;
2034 int comp_flag;
2035 int comp_type = 0;
2036 int ret;
2037 png_size_t slength, prefix_len, data_len;
2038
2039 png_debug(1, "in png_handle_iTXt\n");
2040
2041 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2042 png_error(png_ptr, "Missing IHDR before iTXt");
2043
2044 if (png_ptr->mode & PNG_HAVE_IDAT)
2045 png_ptr->mode |= PNG_AFTER_IDAT;
2046
2047#ifdef PNG_MAX_MALLOC_64K
2048 /* We will no doubt have problems with chunks even half this size, but
2049 there is no hard and fast rule to tell us where to stop. */
2050 if (length > (png_uint_32)65535L)
2051 {
2052 png_warning(png_ptr,"iTXt chunk too large to fit in memory");
2053 png_crc_finish(png_ptr, length);
2054 return;
2055 }
2056#endif
2057
2058 chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2059 if (chunkdata == NULL)
2060 {
2061 png_warning(png_ptr, "No memory to process iTXt chunk.");
2062 return;
2063 }
2064 slength = (png_size_t)length;
2065 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
2066 if (png_crc_finish(png_ptr, 0))
2067 {
2068 png_free(png_ptr, chunkdata);
2069 return;
2070 }
2071
2072 chunkdata[slength] = 0x00;
2073
2074 for (lang = chunkdata; *lang; lang++)
2075 /* empty loop */ ;
2076 lang++; /* skip NUL separator */
2077
2078 /* iTXt must have a language tag (possibly empty), two compression bytes,
2079 translated keyword (possibly empty), and possibly some text after the
2080 keyword */
2081
2082 if (lang >= chunkdata + slength)
2083 {
2084 comp_flag = PNG_TEXT_COMPRESSION_NONE;
2085 png_warning(png_ptr, "Zero length iTXt chunk");
2086 }
2087 else
2088 {
2089 comp_flag = *lang++;
2090 comp_type = *lang++;
2091 }
2092
2093 for (lang_key = lang; *lang_key; lang_key++)
2094 /* empty loop */ ;
2095 lang_key++; /* skip NUL separator */
2096
2097 for (text = lang_key; *text; text++)
2098 /* empty loop */ ;
2099 text++; /* skip NUL separator */
2100
2101 prefix_len = text - chunkdata;
2102
2103 key=chunkdata;
2104 if (comp_flag)
2105 chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
2106 (size_t)length, prefix_len, &data_len);
2107 else
2108 data_len=png_strlen(chunkdata + prefix_len);
2109 text_ptr = (png_textp)png_malloc_warn(png_ptr, (png_uint_32)sizeof(png_text));
2110 if (text_ptr == NULL)
2111 {
2112 png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
2113 png_free(png_ptr, chunkdata);
2114 return;
2115 }
2116 text_ptr->compression = (int)comp_flag + 1;
2117 text_ptr->lang_key = chunkdata+(lang_key-key);
2118 text_ptr->lang = chunkdata+(lang-key);
2119 text_ptr->itxt_length = data_len;
2120 text_ptr->text_length = 0;
2121 text_ptr->key = chunkdata;
2122 text_ptr->text = chunkdata + prefix_len;
2123
2124 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2125
2126 png_free(png_ptr, text_ptr);
2127 png_free(png_ptr, chunkdata);
2128 if (ret)
2129 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
2130}
2131#endif
2132
2133/* This function is called when we haven't found a handler for a
2134 chunk. If there isn't a problem with the chunk itself (ie bad
2135 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2136 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2137 case it will be saved away to be written out later. */
2138void /* PRIVATE */
2139png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2140{
2141 png_uint_32 skip = 0;
2142
2143 png_debug(1, "in png_handle_unknown\n");
2144
2145 if (png_ptr->mode & PNG_HAVE_IDAT)
2146 {
2147#ifdef PNG_USE_LOCAL_ARRAYS
2148 PNG_IDAT;
2149#endif
2150 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2151 png_ptr->mode |= PNG_AFTER_IDAT;
2152 }
2153
2154 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
2155
2156 if (!(png_ptr->chunk_name[0] & 0x20))
2157 {
2158#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2159 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2160 HANDLE_CHUNK_ALWAYS
2161#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2162 && png_ptr->read_user_chunk_fn == NULL
2163#endif
2164 )
2165#endif
2166 png_chunk_error(png_ptr, "unknown critical chunk");
2167 }
2168
2169#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2170 if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
2171 {
2172 png_unknown_chunk chunk;
2173
2174#ifdef PNG_MAX_MALLOC_64K
2175 if (length > (png_uint_32)65535L)
2176 {
2177 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2178 skip = length - (png_uint_32)65535L;
2179 length = (png_uint_32)65535L;
2180 }
2181#endif
2182 png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
2183 chunk.data = (png_bytep)png_malloc(png_ptr, length);
2184 chunk.size = (png_size_t)length;
2185 png_crc_read(png_ptr, (png_bytep)chunk.data, length);
2186#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2187 if(png_ptr->read_user_chunk_fn != NULL)
2188 {
2189 /* callback to user unknown chunk handler */
2190 if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
2191 {
2192 if (!(png_ptr->chunk_name[0] & 0x20))
2193 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2194 HANDLE_CHUNK_ALWAYS)
2195 {
2196 png_free(png_ptr, chunk.data);
2197 png_chunk_error(png_ptr, "unknown critical chunk");
2198 }
2199 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2200 }
2201 }
2202 else
2203#endif
2204 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2205 png_free(png_ptr, chunk.data);
2206 }
2207 else
2208#endif
2209 skip = length;
2210
2211 png_crc_finish(png_ptr, skip);
2212
2213#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2214 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
2215#endif
2216}
2217
2218/* This function is called to verify that a chunk name is valid.
2219 This function can't have the "critical chunk check" incorporated
2220 into it, since in the future we will need to be able to call user
2221 functions to handle unknown critical chunks after we check that
2222 the chunk name itself is valid. */
2223
2224#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
2225
2226void /* PRIVATE */
2227png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2228{
2229 png_debug(1, "in png_check_chunk_name\n");
2230 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2231 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2232 {
2233 png_chunk_error(png_ptr, "invalid chunk type");
2234 }
2235}
2236
2237/* Combines the row recently read in with the existing pixels in the
2238 row. This routine takes care of alpha and transparency if requested.
2239 This routine also handles the two methods of progressive display
2240 of interlaced images, depending on the mask value.
2241 The mask value describes which pixels are to be combined with
2242 the row. The pattern always repeats every 8 pixels, so just 8
2243 bits are needed. A one indicates the pixel is to be combined,
2244 a zero indicates the pixel is to be skipped. This is in addition
2245 to any alpha or transparency value associated with the pixel. If
2246 you want all pixels to be combined, pass 0xff (255) in mask. */
2247#ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
2248void /* PRIVATE */
2249png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2250{
2251 png_debug(1,"in png_combine_row\n");
2252 if (mask == 0xff)
2253 {
2254 png_memcpy(row, png_ptr->row_buf + 1,
2255 (png_size_t)((png_ptr->width *
2256 png_ptr->row_info.pixel_depth + 7) >> 3));
2257 }
2258 else
2259 {
2260 switch (png_ptr->row_info.pixel_depth)
2261 {
2262 case 1:
2263 {
2264 png_bytep sp = png_ptr->row_buf + 1;
2265 png_bytep dp = row;
2266 int s_inc, s_start, s_end;
2267 int m = 0x80;
2268 int shift;
2269 png_uint_32 i;
2270 png_uint_32 row_width = png_ptr->width;
2271
2272#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2273 if (png_ptr->transformations & PNG_PACKSWAP)
2274 {
2275 s_start = 0;
2276 s_end = 7;
2277 s_inc = 1;
2278 }
2279 else
2280#endif
2281 {
2282 s_start = 7;
2283 s_end = 0;
2284 s_inc = -1;
2285 }
2286
2287 shift = s_start;
2288
2289 for (i = 0; i < row_width; i++)
2290 {
2291 if (m & mask)
2292 {
2293 int value;
2294
2295 value = (*sp >> shift) & 0x01;
2296 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2297 *dp |= (png_byte)(value << shift);
2298 }
2299
2300 if (shift == s_end)
2301 {
2302 shift = s_start;
2303 sp++;
2304 dp++;
2305 }
2306 else
2307 shift += s_inc;
2308
2309 if (m == 1)
2310 m = 0x80;
2311 else
2312 m >>= 1;
2313 }
2314 break;
2315 }
2316 case 2:
2317 {
2318 png_bytep sp = png_ptr->row_buf + 1;
2319 png_bytep dp = row;
2320 int s_start, s_end, s_inc;
2321 int m = 0x80;
2322 int shift;
2323 png_uint_32 i;
2324 png_uint_32 row_width = png_ptr->width;
2325 int value;
2326
2327#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2328 if (png_ptr->transformations & PNG_PACKSWAP)
2329 {
2330 s_start = 0;
2331 s_end = 6;
2332 s_inc = 2;
2333 }
2334 else
2335#endif
2336 {
2337 s_start = 6;
2338 s_end = 0;
2339 s_inc = -2;
2340 }
2341
2342 shift = s_start;
2343
2344 for (i = 0; i < row_width; i++)
2345 {
2346 if (m & mask)
2347 {
2348 value = (*sp >> shift) & 0x03;
2349 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2350 *dp |= (png_byte)(value << shift);
2351 }
2352
2353 if (shift == s_end)
2354 {
2355 shift = s_start;
2356 sp++;
2357 dp++;
2358 }
2359 else
2360 shift += s_inc;
2361 if (m == 1)
2362 m = 0x80;
2363 else
2364 m >>= 1;
2365 }
2366 break;
2367 }
2368 case 4:
2369 {
2370 png_bytep sp = png_ptr->row_buf + 1;
2371 png_bytep dp = row;
2372 int s_start, s_end, s_inc;
2373 int m = 0x80;
2374 int shift;
2375 png_uint_32 i;
2376 png_uint_32 row_width = png_ptr->width;
2377 int value;
2378
2379#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2380 if (png_ptr->transformations & PNG_PACKSWAP)
2381 {
2382 s_start = 0;
2383 s_end = 4;
2384 s_inc = 4;
2385 }
2386 else
2387#endif
2388 {
2389 s_start = 4;
2390 s_end = 0;
2391 s_inc = -4;
2392 }
2393 shift = s_start;
2394
2395 for (i = 0; i < row_width; i++)
2396 {
2397 if (m & mask)
2398 {
2399 value = (*sp >> shift) & 0xf;
2400 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2401 *dp |= (png_byte)(value << shift);
2402 }
2403
2404 if (shift == s_end)
2405 {
2406 shift = s_start;
2407 sp++;
2408 dp++;
2409 }
2410 else
2411 shift += s_inc;
2412 if (m == 1)
2413 m = 0x80;
2414 else
2415 m >>= 1;
2416 }
2417 break;
2418 }
2419 default:
2420 {
2421 png_bytep sp = png_ptr->row_buf + 1;
2422 png_bytep dp = row;
2423 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2424 png_uint_32 i;
2425 png_uint_32 row_width = png_ptr->width;
2426 png_byte m = 0x80;
2427
2428
2429 for (i = 0; i < row_width; i++)
2430 {
2431 if (m & mask)
2432 {
2433 png_memcpy(dp, sp, pixel_bytes);
2434 }
2435
2436 sp += pixel_bytes;
2437 dp += pixel_bytes;
2438
2439 if (m == 1)
2440 m = 0x80;
2441 else
2442 m >>= 1;
2443 }
2444 break;
2445 }
2446 }
2447 }
2448}
2449#endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
2450
2451#ifdef PNG_READ_INTERLACING_SUPPORTED
2452#ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */
2453/* OLD pre-1.0.9 interface:
2454void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2455 png_uint_32 transformations)
2456 */
2457void /* PRIVATE */
2458png_do_read_interlace(png_structp png_ptr)
2459{
2460 png_row_infop row_info = &(png_ptr->row_info);
2461 png_bytep row = png_ptr->row_buf + 1;
2462 int pass = png_ptr->pass;
2463 png_uint_32 transformations = png_ptr->transformations;
2464#ifdef PNG_USE_LOCAL_ARRAYS
2465 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2466 /* offset to next interlace block */
2467 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2468#endif
2469
2470 png_debug(1,"in png_do_read_interlace (stock C version)\n");
2471 if (row != NULL && row_info != NULL)
2472 {
2473 png_uint_32 final_width;
2474
2475 final_width = row_info->width * png_pass_inc[pass];
2476
2477 switch (row_info->pixel_depth)
2478 {
2479 case 1:
2480 {
2481 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2482 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2483 int sshift, dshift;
2484 int s_start, s_end, s_inc;
2485 int jstop = png_pass_inc[pass];
2486 png_byte v;
2487 png_uint_32 i;
2488 int j;
2489
2490#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2491 if (transformations & PNG_PACKSWAP)
2492 {
2493 sshift = (int)((row_info->width + 7) & 0x07);
2494 dshift = (int)((final_width + 7) & 0x07);
2495 s_start = 7;
2496 s_end = 0;
2497 s_inc = -1;
2498 }
2499 else
2500#endif
2501 {
2502 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2503 dshift = 7 - (int)((final_width + 7) & 0x07);
2504 s_start = 0;
2505 s_end = 7;
2506 s_inc = 1;
2507 }
2508
2509 for (i = 0; i < row_info->width; i++)
2510 {
2511 v = (png_byte)((*sp >> sshift) & 0x01);
2512 for (j = 0; j < jstop; j++)
2513 {
2514 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2515 *dp |= (png_byte)(v << dshift);
2516 if (dshift == s_end)
2517 {
2518 dshift = s_start;
2519 dp--;
2520 }
2521 else
2522 dshift += s_inc;
2523 }
2524 if (sshift == s_end)
2525 {
2526 sshift = s_start;
2527 sp--;
2528 }
2529 else
2530 sshift += s_inc;
2531 }
2532 break;
2533 }
2534 case 2:
2535 {
2536 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2537 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2538 int sshift, dshift;
2539 int s_start, s_end, s_inc;
2540 int jstop = png_pass_inc[pass];
2541 png_uint_32 i;
2542
2543#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2544 if (transformations & PNG_PACKSWAP)
2545 {
2546 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2547 dshift = (int)(((final_width + 3) & 0x03) << 1);
2548 s_start = 6;
2549 s_end = 0;
2550 s_inc = -2;
2551 }
2552 else
2553#endif
2554 {
2555 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2556 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2557 s_start = 0;
2558 s_end = 6;
2559 s_inc = 2;
2560 }
2561
2562 for (i = 0; i < row_info->width; i++)
2563 {
2564 png_byte v;
2565 int j;
2566
2567 v = (png_byte)((*sp >> sshift) & 0x03);
2568 for (j = 0; j < jstop; j++)
2569 {
2570 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2571 *dp |= (png_byte)(v << dshift);
2572 if (dshift == s_end)
2573 {
2574 dshift = s_start;
2575 dp--;
2576 }
2577 else
2578 dshift += s_inc;
2579 }
2580 if (sshift == s_end)
2581 {
2582 sshift = s_start;
2583 sp--;
2584 }
2585 else
2586 sshift += s_inc;
2587 }
2588 break;
2589 }
2590 case 4:
2591 {
2592 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2593 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2594 int sshift, dshift;
2595 int s_start, s_end, s_inc;
2596 png_uint_32 i;
2597 int jstop = png_pass_inc[pass];
2598
2599#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2600 if (transformations & PNG_PACKSWAP)
2601 {
2602 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2603 dshift = (int)(((final_width + 1) & 0x01) << 2);
2604 s_start = 4;
2605 s_end = 0;
2606 s_inc = -4;
2607 }
2608 else
2609#endif
2610 {
2611 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2612 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2613 s_start = 0;
2614 s_end = 4;
2615 s_inc = 4;
2616 }
2617
2618 for (i = 0; i < row_info->width; i++)
2619 {
2620 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2621 int j;
2622
2623 for (j = 0; j < jstop; j++)
2624 {
2625 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2626 *dp |= (png_byte)(v << dshift);
2627 if (dshift == s_end)
2628 {
2629 dshift = s_start;
2630 dp--;
2631 }
2632 else
2633 dshift += s_inc;
2634 }
2635 if (sshift == s_end)
2636 {
2637 sshift = s_start;
2638 sp--;
2639 }
2640 else
2641 sshift += s_inc;
2642 }
2643 break;
2644 }
2645 default:
2646 {
2647 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2648 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2649 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2650
2651 int jstop = png_pass_inc[pass];
2652 png_uint_32 i;
2653
2654 for (i = 0; i < row_info->width; i++)
2655 {
2656 png_byte v[8];
2657 int j;
2658
2659 png_memcpy(v, sp, pixel_bytes);
2660 for (j = 0; j < jstop; j++)
2661 {
2662 png_memcpy(dp, v, pixel_bytes);
2663 dp -= pixel_bytes;
2664 }
2665 sp -= pixel_bytes;
2666 }
2667 break;
2668 }
2669 }
2670 row_info->width = final_width;
2671 row_info->rowbytes = ((final_width *
2672 (png_uint_32)row_info->pixel_depth + 7) >> 3);
2673 }
2674#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2675 transformations = transformations; /* silence compiler warning */
2676#endif
2677}
2678#endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
2679#endif /* PNG_READ_INTERLACING_SUPPORTED */
2680
2681#ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
2682void /* PRIVATE */
2683png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2684 png_bytep prev_row, int filter)
2685{
2686 png_debug(1, "in png_read_filter_row\n");
2687 png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
2688 switch (filter)
2689 {
2690 case PNG_FILTER_VALUE_NONE:
2691 break;
2692 case PNG_FILTER_VALUE_SUB:
2693 {
2694 png_uint_32 i;
2695 png_uint_32 istop = row_info->rowbytes;
2696 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2697 png_bytep rp = row + bpp;
2698 png_bytep lp = row;
2699
2700 for (i = bpp; i < istop; i++)
2701 {
2702 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2703 rp++;
2704 }
2705 break;
2706 }
2707 case PNG_FILTER_VALUE_UP:
2708 {
2709 png_uint_32 i;
2710 png_uint_32 istop = row_info->rowbytes;
2711 png_bytep rp = row;
2712 png_bytep pp = prev_row;
2713
2714 for (i = 0; i < istop; i++)
2715 {
2716 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2717 rp++;
2718 }
2719 break;
2720 }
2721 case PNG_FILTER_VALUE_AVG:
2722 {
2723 png_uint_32 i;
2724 png_bytep rp = row;
2725 png_bytep pp = prev_row;
2726 png_bytep lp = row;
2727 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2728 png_uint_32 istop = row_info->rowbytes - bpp;
2729
2730 for (i = 0; i < bpp; i++)
2731 {
2732 *rp = (png_byte)(((int)(*rp) +
2733 ((int)(*pp++) / 2 )) & 0xff);
2734 rp++;
2735 }
2736
2737 for (i = 0; i < istop; i++)
2738 {
2739 *rp = (png_byte)(((int)(*rp) +
2740 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2741 rp++;
2742 }
2743 break;
2744 }
2745 case PNG_FILTER_VALUE_PAETH:
2746 {
2747 png_uint_32 i;
2748 png_bytep rp = row;
2749 png_bytep pp = prev_row;
2750 png_bytep lp = row;
2751 png_bytep cp = prev_row;
2752 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2753 png_uint_32 istop=row_info->rowbytes - bpp;
2754
2755 for (i = 0; i < bpp; i++)
2756 {
2757 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2758 rp++;
2759 }
2760
2761 for (i = 0; i < istop; i++) /* use leftover rp,pp */
2762 {
2763 int a, b, c, pa, pb, pc, p;
2764
2765 a = *lp++;
2766 b = *pp++;
2767 c = *cp++;
2768
2769 p = b - c;
2770 pc = a - c;
2771
2772#ifdef PNG_USE_ABS
2773 pa = abs(p);
2774 pb = abs(pc);
2775 pc = abs(p + pc);
2776#else
2777 pa = p < 0 ? -p : p;
2778 pb = pc < 0 ? -pc : pc;
2779 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2780#endif
2781
2782 /*
2783 if (pa <= pb && pa <= pc)
2784 p = a;
2785 else if (pb <= pc)
2786 p = b;
2787 else
2788 p = c;
2789 */
2790
2791 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2792
2793 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2794 rp++;
2795 }
2796 break;
2797 }
2798 default:
2799 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2800 *row=0;
2801 break;
2802 }
2803}
2804#endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
2805
2806void /* PRIVATE */
2807png_read_finish_row(png_structp png_ptr)
2808{
2809#ifdef PNG_USE_LOCAL_ARRAYS
2810 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2811
2812 /* start of interlace block */
2813 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2814
2815 /* offset to next interlace block */
2816 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2817
2818 /* start of interlace block in the y direction */
2819 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2820
2821 /* offset to next interlace block in the y direction */
2822 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2823#endif
2824
2825 png_debug(1, "in png_read_finish_row\n");
2826 png_ptr->row_number++;
2827 if (png_ptr->row_number < png_ptr->num_rows)
2828 return;
2829
2830 if (png_ptr->interlaced)
2831 {
2832 png_ptr->row_number = 0;
2833 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
2834 do
2835 {
2836 png_ptr->pass++;
2837 if (png_ptr->pass >= 7)
2838 break;
2839 png_ptr->iwidth = (png_ptr->width +
2840 png_pass_inc[png_ptr->pass] - 1 -
2841 png_pass_start[png_ptr->pass]) /
2842 png_pass_inc[png_ptr->pass];
2843 png_ptr->irowbytes = ((png_ptr->iwidth *
2844 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2845
2846 if (!(png_ptr->transformations & PNG_INTERLACE))
2847 {
2848 png_ptr->num_rows = (png_ptr->height +
2849 png_pass_yinc[png_ptr->pass] - 1 -
2850 png_pass_ystart[png_ptr->pass]) /
2851 png_pass_yinc[png_ptr->pass];
2852 if (!(png_ptr->num_rows))
2853 continue;
2854 }
2855 else /* if (png_ptr->transformations & PNG_INTERLACE) */
2856 break;
2857 } while (png_ptr->iwidth == 0);
2858
2859 if (png_ptr->pass < 7)
2860 return;
2861 }
2862
2863 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
2864 {
2865#ifdef PNG_USE_LOCAL_ARRAYS
2866 PNG_IDAT;
2867#endif
2868 char extra;
2869 int ret;
2870
2871 png_ptr->zstream.next_out = (Byte *)&extra;
2872 png_ptr->zstream.avail_out = (uInt)1;
2873 for(;;)
2874 {
2875 if (!(png_ptr->zstream.avail_in))
2876 {
2877 while (!png_ptr->idat_size)
2878 {
2879 png_byte chunk_length[4];
2880
2881 png_crc_finish(png_ptr, 0);
2882
2883 png_read_data(png_ptr, chunk_length, 4);
2884 png_ptr->idat_size = png_get_uint_32(chunk_length);
2885
2886 png_reset_crc(png_ptr);
2887 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2888 if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
2889 png_error(png_ptr, "Not enough image data");
2890
2891 }
2892 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2893 png_ptr->zstream.next_in = png_ptr->zbuf;
2894 if (png_ptr->zbuf_size > png_ptr->idat_size)
2895 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2896 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2897 png_ptr->idat_size -= png_ptr->zstream.avail_in;
2898 }
2899 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
2900 if (ret == Z_STREAM_END)
2901 {
2902 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
2903 png_ptr->idat_size)
2904 png_warning(png_ptr, "Extra compressed data");
2905 png_ptr->mode |= PNG_AFTER_IDAT;
2906 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2907 break;
2908 }
2909 if (ret != Z_OK)
2910 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
2911 "Decompression Error");
2912
2913 if (!(png_ptr->zstream.avail_out))
2914 {
2915 png_warning(png_ptr, "Extra compressed data.");
2916 png_ptr->mode |= PNG_AFTER_IDAT;
2917 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2918 break;
2919 }
2920
2921 }
2922 png_ptr->zstream.avail_out = 0;
2923 }
2924
2925 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
2926 png_warning(png_ptr, "Extra compression data");
2927
2928 inflateReset(&png_ptr->zstream);
2929
2930 png_ptr->mode |= PNG_AFTER_IDAT;
2931}
2932
2933void /* PRIVATE */
2934png_read_start_row(png_structp png_ptr)
2935{
2936#ifdef PNG_USE_LOCAL_ARRAYS
2937 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2938
2939 /* start of interlace block */
2940 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2941
2942 /* offset to next interlace block */
2943 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2944
2945 /* start of interlace block in the y direction */
2946 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2947
2948 /* offset to next interlace block in the y direction */
2949 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2950#endif
2951
2952 int max_pixel_depth;
2953 png_uint_32 row_bytes;
2954
2955 png_debug(1, "in png_read_start_row\n");
2956 png_ptr->zstream.avail_in = 0;
2957 png_init_read_transformations(png_ptr);
2958 if (png_ptr->interlaced)
2959 {
2960 if (!(png_ptr->transformations & PNG_INTERLACE))
2961 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2962 png_pass_ystart[0]) / png_pass_yinc[0];
2963 else
2964 png_ptr->num_rows = png_ptr->height;
2965
2966 png_ptr->iwidth = (png_ptr->width +
2967 png_pass_inc[png_ptr->pass] - 1 -
2968 png_pass_start[png_ptr->pass]) /
2969 png_pass_inc[png_ptr->pass];
2970
2971 row_bytes = ((png_ptr->iwidth *
2972 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2973 png_ptr->irowbytes = (png_size_t)row_bytes;
2974 if((png_uint_32)png_ptr->irowbytes != row_bytes)
2975 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
2976 }
2977 else
2978 {
2979 png_ptr->num_rows = png_ptr->height;
2980 png_ptr->iwidth = png_ptr->width;
2981 png_ptr->irowbytes = png_ptr->rowbytes + 1;
2982 }
2983 max_pixel_depth = png_ptr->pixel_depth;
2984
2985#if defined(PNG_READ_PACK_SUPPORTED)
2986 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
2987 max_pixel_depth = 8;
2988#endif
2989
2990#if defined(PNG_READ_EXPAND_SUPPORTED)
2991 if (png_ptr->transformations & PNG_EXPAND)
2992 {
2993 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2994 {
2995 if (png_ptr->num_trans)
2996 max_pixel_depth = 32;
2997 else
2998 max_pixel_depth = 24;
2999 }
3000 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3001 {
3002 if (max_pixel_depth < 8)
3003 max_pixel_depth = 8;
3004 if (png_ptr->num_trans)
3005 max_pixel_depth *= 2;
3006 }
3007 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3008 {
3009 if (png_ptr->num_trans)
3010 {
3011 max_pixel_depth *= 4;
3012 max_pixel_depth /= 3;
3013 }
3014 }
3015 }
3016#endif
3017
3018#if defined(PNG_READ_FILLER_SUPPORTED)
3019 if (png_ptr->transformations & (PNG_FILLER))
3020 {
3021 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3022 max_pixel_depth = 32;
3023 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3024 {
3025 if (max_pixel_depth <= 8)
3026 max_pixel_depth = 16;
3027 else
3028 max_pixel_depth = 32;
3029 }
3030 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3031 {
3032 if (max_pixel_depth <= 32)
3033 max_pixel_depth = 32;
3034 else
3035 max_pixel_depth = 64;
3036 }
3037 }
3038#endif
3039
3040#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
3041 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3042 {
3043 if (
3044#if defined(PNG_READ_EXPAND_SUPPORTED)
3045 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3046#endif
3047#if defined(PNG_READ_FILLER_SUPPORTED)
3048 (png_ptr->transformations & (PNG_FILLER)) ||
3049#endif
3050 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3051 {
3052 if (max_pixel_depth <= 16)
3053 max_pixel_depth = 32;
3054 else
3055 max_pixel_depth = 64;
3056 }
3057 else
3058 {
3059 if (max_pixel_depth <= 8)
3060 {
3061 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3062 max_pixel_depth = 32;
3063 else
3064 max_pixel_depth = 24;
3065 }
3066 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3067 max_pixel_depth = 64;
3068 else
3069 max_pixel_depth = 48;
3070 }
3071 }
3072#endif
3073
3074#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3075defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
3076 if(png_ptr->transformations & PNG_USER_TRANSFORM)
3077 {
3078 int user_pixel_depth=png_ptr->user_transform_depth*
3079 png_ptr->user_transform_channels;
3080 if(user_pixel_depth > max_pixel_depth)
3081 max_pixel_depth=user_pixel_depth;
3082 }
3083#endif
3084
3085 /* align the width on the next larger 8 pixels. Mainly used
3086 for interlacing */
3087 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
3088 /* calculate the maximum bytes needed, adding a byte and a pixel
3089 for safety's sake */
3090 row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
3091 1 + ((max_pixel_depth + 7) >> 3);
3092#ifdef PNG_MAX_MALLOC_64K
3093 if (row_bytes > (png_uint_32)65536L)
3094 png_error(png_ptr, "This image requires a row greater than 64KB");
3095#endif
3096 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
3097 png_ptr->row_buf = png_ptr->big_row_buf+32;
3098#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
3099 png_ptr->row_buf_size = row_bytes;
3100#endif
3101
3102#ifdef PNG_MAX_MALLOC_64K
3103 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
3104 png_error(png_ptr, "This image requires a row greater than 64KB");
3105#endif
3106 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3107 png_ptr->rowbytes + 1));
3108
3109 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
3110
3111 png_debug1(3, "width = %lu,\n", png_ptr->width);
3112 png_debug1(3, "height = %lu,\n", png_ptr->height);
3113 png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
3114 png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
3115 png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
3116 png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
3117
3118 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3119}