Add ICU message format support
[chromium-blink-merge.git] / third_party / libpng / pngrutil.c
blob10588c4e1d0d0b469384cc6e8fef4be05adb18d6
2 /* pngrutil.c - utilities to read a PNG file
4 * Last changed in libpng 1.2.45 [July 7, 2011]
5 * Copyright (c) 1998-2011 Glenn Randers-Pehrson
6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9 * This code is released under the libpng license.
10 * For conditions of distribution and use, see the disclaimer
11 * and license in png.h
13 * This file contains routines that are only called from within
14 * libpng itself during the course of reading an image.
17 #define PNG_INTERNAL
18 #define PNG_NO_PEDANTIC_WARNINGS
19 #include "png.h"
20 #ifdef PNG_READ_SUPPORTED
22 #if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
23 # define WIN32_WCE_OLD
24 #endif
26 #ifdef PNG_FLOATING_POINT_SUPPORTED
27 # ifdef WIN32_WCE_OLD
28 /* The strtod() function is not supported on WindowsCE */
29 __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr,
30 char **endptr)
32 double result = 0;
33 int len;
34 wchar_t *str, *end;
36 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
37 str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
38 if ( NULL != str )
40 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
41 result = wcstod(str, &end);
42 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
43 *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
44 png_free(png_ptr, str);
46 return result;
48 # else
49 # define png_strtod(p,a,b) strtod(a,b)
50 # endif
51 #endif
53 png_uint_32 PNGAPI
54 png_get_uint_31(png_structp png_ptr, png_bytep buf)
56 #ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
57 png_uint_32 i = png_get_uint_32(buf);
58 #else
59 /* Avoid an extra function call by inlining the result. */
60 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
61 ((png_uint_32)(*(buf + 1)) << 16) +
62 ((png_uint_32)(*(buf + 2)) << 8) +
63 (png_uint_32)(*(buf + 3));
64 #endif
65 if (i > PNG_UINT_31_MAX)
66 png_error(png_ptr, "PNG unsigned integer out of range.");
67 return (i);
69 #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
70 /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
71 png_uint_32 PNGAPI
72 png_get_uint_32(png_bytep buf)
74 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
75 ((png_uint_32)(*(buf + 1)) << 16) +
76 ((png_uint_32)(*(buf + 2)) << 8) +
77 (png_uint_32)(*(buf + 3));
79 return (i);
82 /* Grab a signed 32-bit integer from a buffer in big-endian format. The
83 * data is stored in the PNG file in two's complement format, and it is
84 * assumed that the machine format for signed integers is the same.
86 png_int_32 PNGAPI
87 png_get_int_32(png_bytep buf)
89 png_int_32 i = ((png_int_32)(*buf) << 24) +
90 ((png_int_32)(*(buf + 1)) << 16) +
91 ((png_int_32)(*(buf + 2)) << 8) +
92 (png_int_32)(*(buf + 3));
94 return (i);
97 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
98 png_uint_16 PNGAPI
99 png_get_uint_16(png_bytep buf)
101 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
102 (png_uint_16)(*(buf + 1)));
104 return (i);
106 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
108 /* Read the chunk header (length + type name).
109 * Put the type name into png_ptr->chunk_name, and return the length.
111 png_uint_32 /* PRIVATE */
112 png_read_chunk_header(png_structp png_ptr)
114 png_byte buf[8];
115 png_uint_32 length;
117 /* Read the length and the chunk name */
118 png_read_data(png_ptr, buf, 8);
119 length = png_get_uint_31(png_ptr, buf);
121 /* Put the chunk name into png_ptr->chunk_name */
122 png_memcpy(png_ptr->chunk_name, buf + 4, 4);
124 png_debug2(0, "Reading %s chunk, length = %lu",
125 png_ptr->chunk_name, length);
127 /* Reset the crc and run it over the chunk name */
128 png_reset_crc(png_ptr);
129 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
131 /* Check to see if chunk name is valid */
132 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
134 return length;
137 /* Read data, and (optionally) run it through the CRC. */
138 void /* PRIVATE */
139 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
141 if (png_ptr == NULL)
142 return;
143 png_read_data(png_ptr, buf, length);
144 png_calculate_crc(png_ptr, buf, length);
147 /* Optionally skip data and then check the CRC. Depending on whether we
148 * are reading a ancillary or critical chunk, and how the program has set
149 * things up, we may calculate the CRC on the data and print a message.
150 * Returns '1' if there was a CRC error, '0' otherwise.
152 int /* PRIVATE */
153 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
155 png_size_t i;
156 png_size_t istop = png_ptr->zbuf_size;
158 for (i = (png_size_t)skip; i > istop; i -= istop)
160 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
162 if (i)
164 png_crc_read(png_ptr, png_ptr->zbuf, i);
167 if (png_crc_error(png_ptr))
169 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
170 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
171 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
172 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
174 png_chunk_warning(png_ptr, "CRC error");
176 else
178 png_chunk_error(png_ptr, "CRC error");
180 return (1);
183 return (0);
186 /* Compare the CRC stored in the PNG file with that calculated by libpng from
187 * the data it has read thus far.
189 int /* PRIVATE */
190 png_crc_error(png_structp png_ptr)
192 png_byte crc_bytes[4];
193 png_uint_32 crc;
194 int need_crc = 1;
196 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
198 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
199 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
200 need_crc = 0;
202 else /* critical */
204 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
205 need_crc = 0;
208 png_read_data(png_ptr, crc_bytes, 4);
210 if (need_crc)
212 crc = png_get_uint_32(crc_bytes);
213 return ((int)(crc != png_ptr->crc));
215 else
216 return (0);
219 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
220 defined(PNG_READ_iCCP_SUPPORTED)
221 static png_size_t
222 png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
223 png_bytep output, png_size_t output_size)
225 png_size_t count = 0;
227 png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
228 png_ptr->zstream.avail_in = size;
230 while (1)
232 int ret, avail;
234 /* Reset the output buffer each time round - we empty it
235 * after every inflate call.
237 png_ptr->zstream.next_out = png_ptr->zbuf;
238 png_ptr->zstream.avail_out = png_ptr->zbuf_size;
240 ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
241 avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
243 /* First copy/count any new output - but only if we didn't
244 * get an error code.
246 if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
248 if (output != 0 && output_size > count)
250 png_size_t copy = output_size - count;
251 if ((png_size_t) avail < copy) copy = (png_size_t) avail;
252 png_memcpy(output + count, png_ptr->zbuf, copy);
254 count += avail;
257 if (ret == Z_OK)
258 continue;
260 /* Termination conditions - always reset the zstream, it
261 * must be left in inflateInit state.
263 png_ptr->zstream.avail_in = 0;
264 inflateReset(&png_ptr->zstream);
266 if (ret == Z_STREAM_END)
267 return count; /* NOTE: may be zero. */
269 /* Now handle the error codes - the API always returns 0
270 * and the error message is dumped into the uncompressed
271 * buffer if available.
274 PNG_CONST char *msg;
275 if (png_ptr->zstream.msg != 0)
276 msg = png_ptr->zstream.msg;
277 else
279 #if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
280 char umsg[52];
282 switch (ret)
284 case Z_BUF_ERROR:
285 msg = "Buffer error in compressed datastream in %s chunk";
286 break;
287 case Z_DATA_ERROR:
288 msg = "Data error in compressed datastream in %s chunk";
289 break;
290 default:
291 msg = "Incomplete compressed datastream in %s chunk";
292 break;
295 png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
296 msg = umsg;
297 #else
298 msg = "Damaged compressed datastream in chunk other than IDAT";
299 #endif
302 png_warning(png_ptr, msg);
305 /* 0 means an error - notice that this code simple ignores
306 * zero length compressed chunks as a result.
308 return 0;
313 * Decompress trailing data in a chunk. The assumption is that chunkdata
314 * points at an allocated area holding the contents of a chunk with a
315 * trailing compressed part. What we get back is an allocated area
316 * holding the original prefix part and an uncompressed version of the
317 * trailing part (the malloc area passed in is freed).
319 void /* PRIVATE */
320 png_decompress_chunk(png_structp png_ptr, int comp_type,
321 png_size_t chunklength,
322 png_size_t prefix_size, png_size_t *newlength)
324 /* The caller should guarantee this */
325 if (prefix_size > chunklength)
327 /* The recovery is to delete the chunk. */
328 png_warning(png_ptr, "invalid chunklength");
329 prefix_size = 0; /* To delete everything */
332 else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
334 png_size_t expanded_size = png_inflate(png_ptr,
335 (png_bytep)(png_ptr->chunkdata + prefix_size),
336 chunklength - prefix_size,
337 0/*output*/, 0/*output size*/);
339 /* Now check the limits on this chunk - if the limit fails the
340 * compressed data will be removed, the prefix will remain.
342 #ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
343 if (png_ptr->user_chunk_malloc_max &&
344 (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
345 #else
346 # ifdef PNG_USER_CHUNK_MALLOC_MAX
347 if ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
348 prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
349 # endif
350 #endif
351 png_warning(png_ptr, "Exceeded size limit while expanding chunk");
353 /* If the size is zero either there was an error and a message
354 * has already been output (warning) or the size really is zero
355 * and we have nothing to do - the code will exit through the
356 * error case below.
358 #if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \
359 defined(PNG_USER_CHUNK_MALLOC_MAX)
360 else
361 #endif
362 if (expanded_size > 0)
364 /* Success (maybe) - really uncompress the chunk. */
365 png_size_t new_size = 0;
366 png_charp text = NULL;
367 /* Need to check for both truncation (64-bit platforms) and integer
368 * overflow.
370 if (prefix_size + expanded_size > prefix_size &&
371 prefix_size + expanded_size < 0xffffffffU)
373 text = png_malloc_warn(png_ptr, prefix_size + expanded_size + 1);
376 if (text != NULL)
378 png_memcpy(text, png_ptr->chunkdata, prefix_size);
379 new_size = png_inflate(png_ptr,
380 (png_bytep)(png_ptr->chunkdata + prefix_size),
381 chunklength - prefix_size,
382 (png_bytep)(text + prefix_size), expanded_size);
383 text[prefix_size + expanded_size] = 0; /* just in case */
385 if (new_size == expanded_size)
387 png_free(png_ptr, png_ptr->chunkdata);
388 png_ptr->chunkdata = text;
389 *newlength = prefix_size + expanded_size;
390 return; /* The success return! */
393 png_warning(png_ptr, "png_inflate logic error");
394 png_free(png_ptr, text);
396 else
397 png_warning(png_ptr, "Not enough memory to decompress chunk.");
401 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
403 #if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
404 char umsg[50];
406 png_snprintf(umsg, sizeof umsg, "Unknown zTXt compression type %d",
407 comp_type);
408 png_warning(png_ptr, umsg);
409 #else
410 png_warning(png_ptr, "Unknown zTXt compression type");
411 #endif
413 /* The recovery is to simply drop the data. */
416 /* Generic error return - leave the prefix, delete the compressed
417 * data, reallocate the chunkdata to remove the potentially large
418 * amount of compressed data.
421 png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
422 if (text != NULL)
424 if (prefix_size > 0)
425 png_memcpy(text, png_ptr->chunkdata, prefix_size);
426 png_free(png_ptr, png_ptr->chunkdata);
427 png_ptr->chunkdata = text;
429 /* This is an extra zero in the 'uncompressed' part. */
430 *(png_ptr->chunkdata + prefix_size) = 0x00;
432 /* Ignore a malloc error here - it is safe. */
435 *newlength = prefix_size;
437 #endif
439 /* Read and check the IDHR chunk */
440 void /* PRIVATE */
441 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
443 png_byte buf[13];
444 png_uint_32 width, height;
445 int bit_depth, color_type, compression_type, filter_type;
446 int interlace_type;
448 png_debug(1, "in png_handle_IHDR");
450 if (png_ptr->mode & PNG_HAVE_IHDR)
451 png_error(png_ptr, "Out of place IHDR");
453 /* Check the length */
454 if (length != 13)
455 png_error(png_ptr, "Invalid IHDR chunk");
457 png_ptr->mode |= PNG_HAVE_IHDR;
459 png_crc_read(png_ptr, buf, 13);
460 png_crc_finish(png_ptr, 0);
462 width = png_get_uint_31(png_ptr, buf);
463 height = png_get_uint_31(png_ptr, buf + 4);
464 bit_depth = buf[8];
465 color_type = buf[9];
466 compression_type = buf[10];
467 filter_type = buf[11];
468 interlace_type = buf[12];
470 /* Set internal variables */
471 png_ptr->width = width;
472 png_ptr->height = height;
473 png_ptr->bit_depth = (png_byte)bit_depth;
474 png_ptr->interlaced = (png_byte)interlace_type;
475 png_ptr->color_type = (png_byte)color_type;
476 #ifdef PNG_MNG_FEATURES_SUPPORTED
477 png_ptr->filter_type = (png_byte)filter_type;
478 #endif
479 png_ptr->compression_type = (png_byte)compression_type;
481 /* Find number of channels */
482 switch (png_ptr->color_type)
484 case PNG_COLOR_TYPE_GRAY:
485 case PNG_COLOR_TYPE_PALETTE:
486 png_ptr->channels = 1;
487 break;
489 case PNG_COLOR_TYPE_RGB:
490 png_ptr->channels = 3;
491 break;
493 case PNG_COLOR_TYPE_GRAY_ALPHA:
494 png_ptr->channels = 2;
495 break;
497 case PNG_COLOR_TYPE_RGB_ALPHA:
498 png_ptr->channels = 4;
499 break;
502 /* Set up other useful info */
503 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
504 png_ptr->channels);
505 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
506 png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
507 png_debug1(3, "channels = %d", png_ptr->channels);
508 png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
509 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
510 color_type, interlace_type, compression_type, filter_type);
513 /* Read and check the palette */
514 void /* PRIVATE */
515 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
517 png_color palette[PNG_MAX_PALETTE_LENGTH];
518 int num, i;
519 #ifdef PNG_POINTER_INDEXING_SUPPORTED
520 png_colorp pal_ptr;
521 #endif
523 png_debug(1, "in png_handle_PLTE");
525 if (!(png_ptr->mode & PNG_HAVE_IHDR))
526 png_error(png_ptr, "Missing IHDR before PLTE");
528 else if (png_ptr->mode & PNG_HAVE_IDAT)
530 png_warning(png_ptr, "Invalid PLTE after IDAT");
531 png_crc_finish(png_ptr, length);
532 return;
535 else if (png_ptr->mode & PNG_HAVE_PLTE)
536 png_error(png_ptr, "Duplicate PLTE chunk");
538 png_ptr->mode |= PNG_HAVE_PLTE;
540 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
542 png_warning(png_ptr,
543 "Ignoring PLTE chunk in grayscale PNG");
544 png_crc_finish(png_ptr, length);
545 return;
547 #ifndef PNG_READ_OPT_PLTE_SUPPORTED
548 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
550 png_crc_finish(png_ptr, length);
551 return;
553 #endif
555 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
557 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
559 png_warning(png_ptr, "Invalid palette chunk");
560 png_crc_finish(png_ptr, length);
561 return;
564 else
566 png_error(png_ptr, "Invalid palette chunk");
570 num = (int)length / 3;
572 #ifdef PNG_POINTER_INDEXING_SUPPORTED
573 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
575 png_byte buf[3];
577 png_crc_read(png_ptr, buf, 3);
578 pal_ptr->red = buf[0];
579 pal_ptr->green = buf[1];
580 pal_ptr->blue = buf[2];
582 #else
583 for (i = 0; i < num; i++)
585 png_byte buf[3];
587 png_crc_read(png_ptr, buf, 3);
588 /* Don't depend upon png_color being any order */
589 palette[i].red = buf[0];
590 palette[i].green = buf[1];
591 palette[i].blue = buf[2];
593 #endif
595 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
596 * whatever the normal CRC configuration tells us. However, if we
597 * have an RGB image, the PLTE can be considered ancillary, so
598 * we will act as though it is.
600 #ifndef PNG_READ_OPT_PLTE_SUPPORTED
601 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
602 #endif
604 png_crc_finish(png_ptr, 0);
606 #ifndef PNG_READ_OPT_PLTE_SUPPORTED
607 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
609 /* If we don't want to use the data from an ancillary chunk,
610 we have two options: an error abort, or a warning and we
611 ignore the data in this chunk (which should be OK, since
612 it's considered ancillary for a RGB or RGBA image). */
613 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
615 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
617 png_chunk_error(png_ptr, "CRC error");
619 else
621 png_chunk_warning(png_ptr, "CRC error");
622 return;
625 /* Otherwise, we (optionally) emit a warning and use the chunk. */
626 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
628 png_chunk_warning(png_ptr, "CRC error");
631 #endif
633 png_set_PLTE(png_ptr, info_ptr, palette, num);
635 #ifdef PNG_READ_tRNS_SUPPORTED
636 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
638 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
640 if (png_ptr->num_trans > (png_uint_16)num)
642 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
643 png_ptr->num_trans = (png_uint_16)num;
645 if (info_ptr->num_trans > (png_uint_16)num)
647 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
648 info_ptr->num_trans = (png_uint_16)num;
652 #endif
656 void /* PRIVATE */
657 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
659 png_debug(1, "in png_handle_IEND");
661 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
663 png_error(png_ptr, "No image in file");
666 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
668 if (length != 0)
670 png_warning(png_ptr, "Incorrect IEND chunk length");
672 png_crc_finish(png_ptr, length);
674 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
677 #ifdef PNG_READ_gAMA_SUPPORTED
678 void /* PRIVATE */
679 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
681 png_fixed_point igamma;
682 #ifdef PNG_FLOATING_POINT_SUPPORTED
683 float file_gamma;
684 #endif
685 png_byte buf[4];
687 png_debug(1, "in png_handle_gAMA");
689 if (!(png_ptr->mode & PNG_HAVE_IHDR))
690 png_error(png_ptr, "Missing IHDR before gAMA");
691 else if (png_ptr->mode & PNG_HAVE_IDAT)
693 png_warning(png_ptr, "Invalid gAMA after IDAT");
694 png_crc_finish(png_ptr, length);
695 return;
697 else if (png_ptr->mode & PNG_HAVE_PLTE)
698 /* Should be an error, but we can cope with it */
699 png_warning(png_ptr, "Out of place gAMA chunk");
701 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
702 #ifdef PNG_READ_sRGB_SUPPORTED
703 && !(info_ptr->valid & PNG_INFO_sRGB)
704 #endif
707 png_warning(png_ptr, "Duplicate gAMA chunk");
708 png_crc_finish(png_ptr, length);
709 return;
712 if (length != 4)
714 png_warning(png_ptr, "Incorrect gAMA chunk length");
715 png_crc_finish(png_ptr, length);
716 return;
719 png_crc_read(png_ptr, buf, 4);
720 if (png_crc_finish(png_ptr, 0))
721 return;
723 igamma = (png_fixed_point)png_get_uint_32(buf);
724 /* Check for zero gamma */
725 if (igamma == 0)
727 png_warning(png_ptr,
728 "Ignoring gAMA chunk with gamma=0");
729 return;
732 #ifdef PNG_READ_sRGB_SUPPORTED
733 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
734 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
736 png_warning(png_ptr,
737 "Ignoring incorrect gAMA value when sRGB is also present");
738 #ifdef PNG_CONSOLE_IO_SUPPORTED
739 fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
740 #endif
741 return;
743 #endif /* PNG_READ_sRGB_SUPPORTED */
745 #ifdef PNG_FLOATING_POINT_SUPPORTED
746 file_gamma = (float)igamma / (float)100000.0;
747 # ifdef PNG_READ_GAMMA_SUPPORTED
748 png_ptr->gamma = file_gamma;
749 # endif
750 png_set_gAMA(png_ptr, info_ptr, file_gamma);
751 #endif
752 #ifdef PNG_FIXED_POINT_SUPPORTED
753 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
754 #endif
756 #endif
758 #ifdef PNG_READ_sBIT_SUPPORTED
759 void /* PRIVATE */
760 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
762 png_size_t truelen;
763 png_byte buf[4];
765 png_debug(1, "in png_handle_sBIT");
767 buf[0] = buf[1] = buf[2] = buf[3] = 0;
769 if (!(png_ptr->mode & PNG_HAVE_IHDR))
770 png_error(png_ptr, "Missing IHDR before sBIT");
771 else if (png_ptr->mode & PNG_HAVE_IDAT)
773 png_warning(png_ptr, "Invalid sBIT after IDAT");
774 png_crc_finish(png_ptr, length);
775 return;
777 else if (png_ptr->mode & PNG_HAVE_PLTE)
779 /* Should be an error, but we can cope with it */
780 png_warning(png_ptr, "Out of place sBIT chunk");
782 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
784 png_warning(png_ptr, "Duplicate sBIT chunk");
785 png_crc_finish(png_ptr, length);
786 return;
789 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
790 truelen = 3;
791 else
792 truelen = (png_size_t)png_ptr->channels;
794 if (length != truelen || length > 4)
796 png_warning(png_ptr, "Incorrect sBIT chunk length");
797 png_crc_finish(png_ptr, length);
798 return;
801 png_crc_read(png_ptr, buf, truelen);
802 if (png_crc_finish(png_ptr, 0))
803 return;
805 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
807 png_ptr->sig_bit.red = buf[0];
808 png_ptr->sig_bit.green = buf[1];
809 png_ptr->sig_bit.blue = buf[2];
810 png_ptr->sig_bit.alpha = buf[3];
812 else
814 png_ptr->sig_bit.gray = buf[0];
815 png_ptr->sig_bit.red = buf[0];
816 png_ptr->sig_bit.green = buf[0];
817 png_ptr->sig_bit.blue = buf[0];
818 png_ptr->sig_bit.alpha = buf[1];
820 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
822 #endif
824 #ifdef PNG_READ_cHRM_SUPPORTED
825 void /* PRIVATE */
826 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
828 png_byte buf[32];
829 #ifdef PNG_FLOATING_POINT_SUPPORTED
830 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
831 #endif
832 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
833 int_y_green, int_x_blue, int_y_blue;
835 png_uint_32 uint_x, uint_y;
837 png_debug(1, "in png_handle_cHRM");
839 if (!(png_ptr->mode & PNG_HAVE_IHDR))
840 png_error(png_ptr, "Missing IHDR before cHRM");
841 else if (png_ptr->mode & PNG_HAVE_IDAT)
843 png_warning(png_ptr, "Invalid cHRM after IDAT");
844 png_crc_finish(png_ptr, length);
845 return;
847 else if (png_ptr->mode & PNG_HAVE_PLTE)
848 /* Should be an error, but we can cope with it */
849 png_warning(png_ptr, "Missing PLTE before cHRM");
851 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
852 #ifdef PNG_READ_sRGB_SUPPORTED
853 && !(info_ptr->valid & PNG_INFO_sRGB)
854 #endif
857 png_warning(png_ptr, "Duplicate cHRM chunk");
858 png_crc_finish(png_ptr, length);
859 return;
862 if (length != 32)
864 png_warning(png_ptr, "Incorrect cHRM chunk length");
865 png_crc_finish(png_ptr, length);
866 return;
869 png_crc_read(png_ptr, buf, 32);
870 if (png_crc_finish(png_ptr, 0))
871 return;
873 uint_x = png_get_uint_32(buf);
874 uint_y = png_get_uint_32(buf + 4);
875 int_x_white = (png_fixed_point)uint_x;
876 int_y_white = (png_fixed_point)uint_y;
878 uint_x = png_get_uint_32(buf + 8);
879 uint_y = png_get_uint_32(buf + 12);
880 int_x_red = (png_fixed_point)uint_x;
881 int_y_red = (png_fixed_point)uint_y;
883 uint_x = png_get_uint_32(buf + 16);
884 uint_y = png_get_uint_32(buf + 20);
885 int_x_green = (png_fixed_point)uint_x;
886 int_y_green = (png_fixed_point)uint_y;
888 uint_x = png_get_uint_32(buf + 24);
889 uint_y = png_get_uint_32(buf + 28);
890 int_x_blue = (png_fixed_point)uint_x;
891 int_y_blue = (png_fixed_point)uint_y;
893 #ifdef PNG_FLOATING_POINT_SUPPORTED
894 white_x = (float)int_x_white / (float)100000.0;
895 white_y = (float)int_y_white / (float)100000.0;
896 red_x = (float)int_x_red / (float)100000.0;
897 red_y = (float)int_y_red / (float)100000.0;
898 green_x = (float)int_x_green / (float)100000.0;
899 green_y = (float)int_y_green / (float)100000.0;
900 blue_x = (float)int_x_blue / (float)100000.0;
901 blue_y = (float)int_y_blue / (float)100000.0;
902 #endif
904 #ifdef PNG_READ_sRGB_SUPPORTED
905 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
907 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
908 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
909 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
910 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
911 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
912 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
913 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
914 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
916 png_warning(png_ptr,
917 "Ignoring incorrect cHRM value when sRGB is also present");
918 #ifdef PNG_CONSOLE_IO_SUPPORTED
919 #ifdef PNG_FLOATING_POINT_SUPPORTED
920 fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
921 white_x, white_y, red_x, red_y);
922 fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
923 green_x, green_y, blue_x, blue_y);
924 #else
925 fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
926 (long)int_x_white, (long)int_y_white,
927 (long)int_x_red, (long)int_y_red);
928 fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
929 (long)int_x_green, (long)int_y_green,
930 (long)int_x_blue, (long)int_y_blue);
931 #endif
932 #endif /* PNG_CONSOLE_IO_SUPPORTED */
934 return;
936 #endif /* PNG_READ_sRGB_SUPPORTED */
938 #ifdef PNG_FLOATING_POINT_SUPPORTED
939 png_set_cHRM(png_ptr, info_ptr,
940 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
941 #endif
942 #ifdef PNG_FIXED_POINT_SUPPORTED
943 png_set_cHRM_fixed(png_ptr, info_ptr,
944 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
945 int_y_green, int_x_blue, int_y_blue);
946 #endif
948 #endif
950 #ifdef PNG_READ_sRGB_SUPPORTED
951 void /* PRIVATE */
952 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
954 int intent;
955 png_byte buf[1];
957 png_debug(1, "in png_handle_sRGB");
959 if (!(png_ptr->mode & PNG_HAVE_IHDR))
960 png_error(png_ptr, "Missing IHDR before sRGB");
961 else if (png_ptr->mode & PNG_HAVE_IDAT)
963 png_warning(png_ptr, "Invalid sRGB after IDAT");
964 png_crc_finish(png_ptr, length);
965 return;
967 else if (png_ptr->mode & PNG_HAVE_PLTE)
968 /* Should be an error, but we can cope with it */
969 png_warning(png_ptr, "Out of place sRGB chunk");
971 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
973 png_warning(png_ptr, "Duplicate sRGB chunk");
974 png_crc_finish(png_ptr, length);
975 return;
978 if (length != 1)
980 png_warning(png_ptr, "Incorrect sRGB chunk length");
981 png_crc_finish(png_ptr, length);
982 return;
985 png_crc_read(png_ptr, buf, 1);
986 if (png_crc_finish(png_ptr, 0))
987 return;
989 intent = buf[0];
990 /* Check for bad intent */
991 if (intent >= PNG_sRGB_INTENT_LAST)
993 png_warning(png_ptr, "Unknown sRGB intent");
994 return;
997 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
998 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
1000 png_fixed_point igamma;
1001 #ifdef PNG_FIXED_POINT_SUPPORTED
1002 igamma=info_ptr->int_gamma;
1003 #else
1004 # ifdef PNG_FLOATING_POINT_SUPPORTED
1005 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
1006 # endif
1007 #endif
1008 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
1010 png_warning(png_ptr,
1011 "Ignoring incorrect gAMA value when sRGB is also present");
1012 #ifdef PNG_CONSOLE_IO_SUPPORTED
1013 # ifdef PNG_FIXED_POINT_SUPPORTED
1014 fprintf(stderr, "incorrect gamma=(%d/100000)\n",
1015 (int)png_ptr->int_gamma);
1016 # else
1017 # ifdef PNG_FLOATING_POINT_SUPPORTED
1018 fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
1019 # endif
1020 # endif
1021 #endif
1024 #endif /* PNG_READ_gAMA_SUPPORTED */
1026 #ifdef PNG_READ_cHRM_SUPPORTED
1027 #ifdef PNG_FIXED_POINT_SUPPORTED
1028 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
1029 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
1030 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
1031 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
1032 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
1033 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
1034 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
1035 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
1036 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
1038 png_warning(png_ptr,
1039 "Ignoring incorrect cHRM value when sRGB is also present");
1041 #endif /* PNG_FIXED_POINT_SUPPORTED */
1042 #endif /* PNG_READ_cHRM_SUPPORTED */
1044 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
1046 #endif /* PNG_READ_sRGB_SUPPORTED */
1048 #ifdef PNG_READ_iCCP_SUPPORTED
1049 void /* PRIVATE */
1050 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1051 /* Note: this does not properly handle chunks that are > 64K under DOS */
1053 png_byte compression_type;
1054 png_bytep pC;
1055 png_charp profile;
1056 png_uint_32 skip = 0;
1057 png_uint_32 profile_size, profile_length;
1058 png_size_t slength, prefix_length, data_length;
1060 png_debug(1, "in png_handle_iCCP");
1062 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1063 png_error(png_ptr, "Missing IHDR before iCCP");
1064 else if (png_ptr->mode & PNG_HAVE_IDAT)
1066 png_warning(png_ptr, "Invalid iCCP after IDAT");
1067 png_crc_finish(png_ptr, length);
1068 return;
1070 else if (png_ptr->mode & PNG_HAVE_PLTE)
1071 /* Should be an error, but we can cope with it */
1072 png_warning(png_ptr, "Out of place iCCP chunk");
1074 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1076 png_warning(png_ptr, "Duplicate iCCP chunk");
1077 png_crc_finish(png_ptr, length);
1078 return;
1081 #ifdef PNG_MAX_MALLOC_64K
1082 if (length > (png_uint_32)65535L)
1084 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1085 skip = length - (png_uint_32)65535L;
1086 length = (png_uint_32)65535L;
1088 #endif
1090 png_free(png_ptr, png_ptr->chunkdata);
1091 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1092 slength = (png_size_t)length;
1093 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1095 if (png_crc_finish(png_ptr, skip))
1097 png_free(png_ptr, png_ptr->chunkdata);
1098 png_ptr->chunkdata = NULL;
1099 return;
1102 png_ptr->chunkdata[slength] = 0x00;
1104 for (profile = png_ptr->chunkdata; *profile; profile++)
1105 /* Empty loop to find end of name */ ;
1107 ++profile;
1109 /* There should be at least one zero (the compression type byte)
1110 * following the separator, and we should be on it
1112 if ( profile >= png_ptr->chunkdata + slength - 1)
1114 png_free(png_ptr, png_ptr->chunkdata);
1115 png_ptr->chunkdata = NULL;
1116 png_warning(png_ptr, "Malformed iCCP chunk");
1117 return;
1120 /* Compression_type should always be zero */
1121 compression_type = *profile++;
1122 if (compression_type)
1124 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1125 compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1126 wrote nonzero) */
1129 prefix_length = profile - png_ptr->chunkdata;
1130 png_decompress_chunk(png_ptr, compression_type,
1131 slength, prefix_length, &data_length);
1133 profile_length = data_length - prefix_length;
1135 if ( prefix_length > data_length || profile_length < 4)
1137 png_free(png_ptr, png_ptr->chunkdata);
1138 png_ptr->chunkdata = NULL;
1139 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1140 return;
1143 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1144 pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
1145 profile_size = ((*(pC ))<<24) |
1146 ((*(pC + 1))<<16) |
1147 ((*(pC + 2))<< 8) |
1148 ((*(pC + 3)) );
1150 if (profile_size < profile_length)
1151 profile_length = profile_size;
1153 if (profile_size > profile_length)
1155 png_free(png_ptr, png_ptr->chunkdata);
1156 png_ptr->chunkdata = NULL;
1157 png_warning(png_ptr, "Ignoring truncated iCCP profile.");
1158 return;
1161 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
1162 compression_type, png_ptr->chunkdata + prefix_length, profile_length);
1163 png_free(png_ptr, png_ptr->chunkdata);
1164 png_ptr->chunkdata = NULL;
1166 #endif /* PNG_READ_iCCP_SUPPORTED */
1168 #ifdef PNG_READ_sPLT_SUPPORTED
1169 void /* PRIVATE */
1170 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1171 /* Note: this does not properly handle chunks that are > 64K under DOS */
1173 png_bytep entry_start;
1174 png_sPLT_t new_palette;
1175 #ifdef PNG_POINTER_INDEXING_SUPPORTED
1176 png_sPLT_entryp pp;
1177 #endif
1178 int data_length, entry_size, i;
1179 png_uint_32 skip = 0;
1180 png_size_t slength;
1182 png_debug(1, "in png_handle_sPLT");
1184 #ifdef PNG_USER_LIMITS_SUPPORTED
1186 if (png_ptr->user_chunk_cache_max != 0)
1188 if (png_ptr->user_chunk_cache_max == 1)
1190 png_crc_finish(png_ptr, length);
1191 return;
1193 if (--png_ptr->user_chunk_cache_max == 1)
1195 png_warning(png_ptr, "No space in chunk cache for sPLT");
1196 png_crc_finish(png_ptr, length);
1197 return;
1200 #endif
1202 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1203 png_error(png_ptr, "Missing IHDR before sPLT");
1204 else if (png_ptr->mode & PNG_HAVE_IDAT)
1206 png_warning(png_ptr, "Invalid sPLT after IDAT");
1207 png_crc_finish(png_ptr, length);
1208 return;
1211 #ifdef PNG_MAX_MALLOC_64K
1212 if (length > (png_uint_32)65535L)
1214 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1215 skip = length - (png_uint_32)65535L;
1216 length = (png_uint_32)65535L;
1218 #endif
1220 png_free(png_ptr, png_ptr->chunkdata);
1221 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1222 slength = (png_size_t)length;
1223 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1225 if (png_crc_finish(png_ptr, skip))
1227 png_free(png_ptr, png_ptr->chunkdata);
1228 png_ptr->chunkdata = NULL;
1229 return;
1232 png_ptr->chunkdata[slength] = 0x00;
1234 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
1235 entry_start++)
1236 /* Empty loop to find end of name */ ;
1237 ++entry_start;
1239 /* A sample depth should follow the separator, and we should be on it */
1240 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
1242 png_free(png_ptr, png_ptr->chunkdata);
1243 png_ptr->chunkdata = NULL;
1244 png_warning(png_ptr, "malformed sPLT chunk");
1245 return;
1248 new_palette.depth = *entry_start++;
1249 entry_size = (new_palette.depth == 8 ? 6 : 10);
1250 data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
1252 /* Integrity-check the data length */
1253 if (data_length % entry_size)
1255 png_free(png_ptr, png_ptr->chunkdata);
1256 png_ptr->chunkdata = NULL;
1257 png_warning(png_ptr, "sPLT chunk has bad length");
1258 return;
1261 new_palette.nentries = (png_int_32) ( data_length / entry_size);
1262 if ((png_uint_32) new_palette.nentries >
1263 (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
1265 png_warning(png_ptr, "sPLT chunk too long");
1266 return;
1268 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1269 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1270 if (new_palette.entries == NULL)
1272 png_warning(png_ptr, "sPLT chunk requires too much memory");
1273 return;
1276 #ifdef PNG_POINTER_INDEXING_SUPPORTED
1277 for (i = 0; i < new_palette.nentries; i++)
1279 pp = new_palette.entries + i;
1281 if (new_palette.depth == 8)
1283 pp->red = *entry_start++;
1284 pp->green = *entry_start++;
1285 pp->blue = *entry_start++;
1286 pp->alpha = *entry_start++;
1288 else
1290 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1291 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1292 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1293 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1295 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1297 #else
1298 pp = new_palette.entries;
1299 for (i = 0; i < new_palette.nentries; i++)
1302 if (new_palette.depth == 8)
1304 pp[i].red = *entry_start++;
1305 pp[i].green = *entry_start++;
1306 pp[i].blue = *entry_start++;
1307 pp[i].alpha = *entry_start++;
1309 else
1311 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1312 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1313 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1314 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1316 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1318 #endif
1320 /* Discard all chunk data except the name and stash that */
1321 new_palette.name = png_ptr->chunkdata;
1323 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1325 png_free(png_ptr, png_ptr->chunkdata);
1326 png_ptr->chunkdata = NULL;
1327 png_free(png_ptr, new_palette.entries);
1329 #endif /* PNG_READ_sPLT_SUPPORTED */
1331 #ifdef PNG_READ_tRNS_SUPPORTED
1332 void /* PRIVATE */
1333 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1335 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1337 png_debug(1, "in png_handle_tRNS");
1339 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1340 png_error(png_ptr, "Missing IHDR before tRNS");
1341 else if (png_ptr->mode & PNG_HAVE_IDAT)
1343 png_warning(png_ptr, "Invalid tRNS after IDAT");
1344 png_crc_finish(png_ptr, length);
1345 return;
1347 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1349 png_warning(png_ptr, "Duplicate tRNS chunk");
1350 png_crc_finish(png_ptr, length);
1351 return;
1354 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1356 png_byte buf[2];
1358 if (length != 2)
1360 png_warning(png_ptr, "Incorrect tRNS chunk length");
1361 png_crc_finish(png_ptr, length);
1362 return;
1365 png_crc_read(png_ptr, buf, 2);
1366 png_ptr->num_trans = 1;
1367 png_ptr->trans_values.gray = png_get_uint_16(buf);
1369 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1371 png_byte buf[6];
1373 if (length != 6)
1375 png_warning(png_ptr, "Incorrect tRNS chunk length");
1376 png_crc_finish(png_ptr, length);
1377 return;
1379 png_crc_read(png_ptr, buf, (png_size_t)length);
1380 png_ptr->num_trans = 1;
1381 png_ptr->trans_values.red = png_get_uint_16(buf);
1382 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1383 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1385 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1387 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1389 /* Should be an error, but we can cope with it. */
1390 png_warning(png_ptr, "Missing PLTE before tRNS");
1392 if (length > (png_uint_32)png_ptr->num_palette ||
1393 length > PNG_MAX_PALETTE_LENGTH)
1395 png_warning(png_ptr, "Incorrect tRNS chunk length");
1396 png_crc_finish(png_ptr, length);
1397 return;
1399 if (length == 0)
1401 png_warning(png_ptr, "Zero length tRNS chunk");
1402 png_crc_finish(png_ptr, length);
1403 return;
1405 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1406 png_ptr->num_trans = (png_uint_16)length;
1408 else
1410 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1411 png_crc_finish(png_ptr, length);
1412 return;
1415 if (png_crc_finish(png_ptr, 0))
1417 png_ptr->num_trans = 0;
1418 return;
1421 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1422 &(png_ptr->trans_values));
1424 #endif
1426 #ifdef PNG_READ_bKGD_SUPPORTED
1427 void /* PRIVATE */
1428 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1430 png_size_t truelen;
1431 png_byte buf[6];
1433 png_debug(1, "in png_handle_bKGD");
1435 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1436 png_error(png_ptr, "Missing IHDR before bKGD");
1437 else if (png_ptr->mode & PNG_HAVE_IDAT)
1439 png_warning(png_ptr, "Invalid bKGD after IDAT");
1440 png_crc_finish(png_ptr, length);
1441 return;
1443 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1444 !(png_ptr->mode & PNG_HAVE_PLTE))
1446 png_warning(png_ptr, "Missing PLTE before bKGD");
1447 png_crc_finish(png_ptr, length);
1448 return;
1450 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1452 png_warning(png_ptr, "Duplicate bKGD chunk");
1453 png_crc_finish(png_ptr, length);
1454 return;
1457 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1458 truelen = 1;
1459 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1460 truelen = 6;
1461 else
1462 truelen = 2;
1464 if (length != truelen)
1466 png_warning(png_ptr, "Incorrect bKGD chunk length");
1467 png_crc_finish(png_ptr, length);
1468 return;
1471 png_crc_read(png_ptr, buf, truelen);
1472 if (png_crc_finish(png_ptr, 0))
1473 return;
1475 /* We convert the index value into RGB components so that we can allow
1476 * arbitrary RGB values for background when we have transparency, and
1477 * so it is easy to determine the RGB values of the background color
1478 * from the info_ptr struct. */
1479 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1481 png_ptr->background.index = buf[0];
1482 if (info_ptr && info_ptr->num_palette)
1484 if (buf[0] >= info_ptr->num_palette)
1486 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1487 return;
1489 png_ptr->background.red =
1490 (png_uint_16)png_ptr->palette[buf[0]].red;
1491 png_ptr->background.green =
1492 (png_uint_16)png_ptr->palette[buf[0]].green;
1493 png_ptr->background.blue =
1494 (png_uint_16)png_ptr->palette[buf[0]].blue;
1497 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1499 png_ptr->background.red =
1500 png_ptr->background.green =
1501 png_ptr->background.blue =
1502 png_ptr->background.gray = png_get_uint_16(buf);
1504 else
1506 png_ptr->background.red = png_get_uint_16(buf);
1507 png_ptr->background.green = png_get_uint_16(buf + 2);
1508 png_ptr->background.blue = png_get_uint_16(buf + 4);
1511 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1513 #endif
1515 #ifdef PNG_READ_hIST_SUPPORTED
1516 void /* PRIVATE */
1517 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1519 unsigned int num, i;
1520 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1522 png_debug(1, "in png_handle_hIST");
1524 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1525 png_error(png_ptr, "Missing IHDR before hIST");
1526 else if (png_ptr->mode & PNG_HAVE_IDAT)
1528 png_warning(png_ptr, "Invalid hIST after IDAT");
1529 png_crc_finish(png_ptr, length);
1530 return;
1532 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1534 png_warning(png_ptr, "Missing PLTE before hIST");
1535 png_crc_finish(png_ptr, length);
1536 return;
1538 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1540 png_warning(png_ptr, "Duplicate hIST chunk");
1541 png_crc_finish(png_ptr, length);
1542 return;
1545 num = length / 2 ;
1546 if (num != (unsigned int) png_ptr->num_palette || num >
1547 (unsigned int) PNG_MAX_PALETTE_LENGTH)
1549 png_warning(png_ptr, "Incorrect hIST chunk length");
1550 png_crc_finish(png_ptr, length);
1551 return;
1554 for (i = 0; i < num; i++)
1556 png_byte buf[2];
1558 png_crc_read(png_ptr, buf, 2);
1559 readbuf[i] = png_get_uint_16(buf);
1562 if (png_crc_finish(png_ptr, 0))
1563 return;
1565 png_set_hIST(png_ptr, info_ptr, readbuf);
1567 #endif
1569 #ifdef PNG_READ_pHYs_SUPPORTED
1570 void /* PRIVATE */
1571 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1573 png_byte buf[9];
1574 png_uint_32 res_x, res_y;
1575 int unit_type;
1577 png_debug(1, "in png_handle_pHYs");
1579 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1580 png_error(png_ptr, "Missing IHDR before pHYs");
1581 else if (png_ptr->mode & PNG_HAVE_IDAT)
1583 png_warning(png_ptr, "Invalid pHYs after IDAT");
1584 png_crc_finish(png_ptr, length);
1585 return;
1587 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1589 png_warning(png_ptr, "Duplicate pHYs chunk");
1590 png_crc_finish(png_ptr, length);
1591 return;
1594 if (length != 9)
1596 png_warning(png_ptr, "Incorrect pHYs chunk length");
1597 png_crc_finish(png_ptr, length);
1598 return;
1601 png_crc_read(png_ptr, buf, 9);
1602 if (png_crc_finish(png_ptr, 0))
1603 return;
1605 res_x = png_get_uint_32(buf);
1606 res_y = png_get_uint_32(buf + 4);
1607 unit_type = buf[8];
1608 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1610 #endif
1612 #ifdef PNG_READ_oFFs_SUPPORTED
1613 void /* PRIVATE */
1614 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1616 png_byte buf[9];
1617 png_int_32 offset_x, offset_y;
1618 int unit_type;
1620 png_debug(1, "in png_handle_oFFs");
1622 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1623 png_error(png_ptr, "Missing IHDR before oFFs");
1624 else if (png_ptr->mode & PNG_HAVE_IDAT)
1626 png_warning(png_ptr, "Invalid oFFs after IDAT");
1627 png_crc_finish(png_ptr, length);
1628 return;
1630 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1632 png_warning(png_ptr, "Duplicate oFFs chunk");
1633 png_crc_finish(png_ptr, length);
1634 return;
1637 if (length != 9)
1639 png_warning(png_ptr, "Incorrect oFFs chunk length");
1640 png_crc_finish(png_ptr, length);
1641 return;
1644 png_crc_read(png_ptr, buf, 9);
1645 if (png_crc_finish(png_ptr, 0))
1646 return;
1648 offset_x = png_get_int_32(buf);
1649 offset_y = png_get_int_32(buf + 4);
1650 unit_type = buf[8];
1651 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1653 #endif
1655 #ifdef PNG_READ_pCAL_SUPPORTED
1656 /* Read the pCAL chunk (described in the PNG Extensions document) */
1657 void /* PRIVATE */
1658 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1660 png_int_32 X0, X1;
1661 png_byte type, nparams;
1662 png_charp buf, units, endptr;
1663 png_charpp params;
1664 png_size_t slength;
1665 int i;
1667 png_debug(1, "in png_handle_pCAL");
1669 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1670 png_error(png_ptr, "Missing IHDR before pCAL");
1671 else if (png_ptr->mode & PNG_HAVE_IDAT)
1673 png_warning(png_ptr, "Invalid pCAL after IDAT");
1674 png_crc_finish(png_ptr, length);
1675 return;
1677 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1679 png_warning(png_ptr, "Duplicate pCAL chunk");
1680 png_crc_finish(png_ptr, length);
1681 return;
1684 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
1685 length + 1);
1686 png_free(png_ptr, png_ptr->chunkdata);
1687 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1688 if (png_ptr->chunkdata == NULL)
1690 png_warning(png_ptr, "No memory for pCAL purpose.");
1691 return;
1693 slength = (png_size_t)length;
1694 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1696 if (png_crc_finish(png_ptr, 0))
1698 png_free(png_ptr, png_ptr->chunkdata);
1699 png_ptr->chunkdata = NULL;
1700 return;
1703 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
1705 png_debug(3, "Finding end of pCAL purpose string");
1706 for (buf = png_ptr->chunkdata; *buf; buf++)
1707 /* Empty loop */ ;
1709 endptr = png_ptr->chunkdata + slength;
1711 /* We need to have at least 12 bytes after the purpose string
1712 in order to get the parameter information. */
1713 if (endptr <= buf + 12)
1715 png_warning(png_ptr, "Invalid pCAL data");
1716 png_free(png_ptr, png_ptr->chunkdata);
1717 png_ptr->chunkdata = NULL;
1718 return;
1721 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
1722 X0 = png_get_int_32((png_bytep)buf+1);
1723 X1 = png_get_int_32((png_bytep)buf+5);
1724 type = buf[9];
1725 nparams = buf[10];
1726 units = buf + 11;
1728 png_debug(3, "Checking pCAL equation type and number of parameters");
1729 /* Check that we have the right number of parameters for known
1730 equation types. */
1731 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1732 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1733 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1734 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1736 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1737 png_free(png_ptr, png_ptr->chunkdata);
1738 png_ptr->chunkdata = NULL;
1739 return;
1741 else if (type >= PNG_EQUATION_LAST)
1743 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1746 for (buf = units; *buf; buf++)
1747 /* Empty loop to move past the units string. */ ;
1749 png_debug(3, "Allocating pCAL parameters array");
1750 params = (png_charpp)png_malloc_warn(png_ptr,
1751 (png_uint_32)(nparams * png_sizeof(png_charp))) ;
1752 if (params == NULL)
1754 png_free(png_ptr, png_ptr->chunkdata);
1755 png_ptr->chunkdata = NULL;
1756 png_warning(png_ptr, "No memory for pCAL params.");
1757 return;
1760 /* Get pointers to the start of each parameter string. */
1761 for (i = 0; i < (int)nparams; i++)
1763 buf++; /* Skip the null string terminator from previous parameter. */
1765 png_debug1(3, "Reading pCAL parameter %d", i);
1766 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
1767 /* Empty loop to move past each parameter string */ ;
1769 /* Make sure we haven't run out of data yet */
1770 if (buf > endptr)
1772 png_warning(png_ptr, "Invalid pCAL data");
1773 png_free(png_ptr, png_ptr->chunkdata);
1774 png_ptr->chunkdata = NULL;
1775 png_free(png_ptr, params);
1776 return;
1780 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
1781 units, params);
1783 png_free(png_ptr, png_ptr->chunkdata);
1784 png_ptr->chunkdata = NULL;
1785 png_free(png_ptr, params);
1787 #endif
1789 #ifdef PNG_READ_sCAL_SUPPORTED
1790 /* Read the sCAL chunk */
1791 void /* PRIVATE */
1792 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1794 png_charp ep;
1795 #ifdef PNG_FLOATING_POINT_SUPPORTED
1796 double width, height;
1797 png_charp vp;
1798 #else
1799 #ifdef PNG_FIXED_POINT_SUPPORTED
1800 png_charp swidth, sheight;
1801 #endif
1802 #endif
1803 png_size_t slength;
1805 png_debug(1, "in png_handle_sCAL");
1807 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1808 png_error(png_ptr, "Missing IHDR before sCAL");
1809 else if (png_ptr->mode & PNG_HAVE_IDAT)
1811 png_warning(png_ptr, "Invalid sCAL after IDAT");
1812 png_crc_finish(png_ptr, length);
1813 return;
1815 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1817 png_warning(png_ptr, "Duplicate sCAL chunk");
1818 png_crc_finish(png_ptr, length);
1819 return;
1822 /* Need unit type, width, \0, height: minimum 4 bytes */
1823 else if (length < 4)
1825 png_warning(png_ptr, "sCAL chunk too short");
1826 png_crc_finish(png_ptr, length);
1827 return;
1830 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
1831 length + 1);
1832 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1833 if (png_ptr->chunkdata == NULL)
1835 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
1836 png_crc_finish(png_ptr, length);
1837 return;
1839 slength = (png_size_t)length;
1840 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1842 if (png_crc_finish(png_ptr, 0))
1844 png_free(png_ptr, png_ptr->chunkdata);
1845 png_ptr->chunkdata = NULL;
1846 return;
1849 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
1851 ep = png_ptr->chunkdata + 1; /* Skip unit byte */
1853 #ifdef PNG_FLOATING_POINT_SUPPORTED
1854 width = png_strtod(png_ptr, ep, &vp);
1855 if (*vp)
1857 png_warning(png_ptr, "malformed width string in sCAL chunk");
1858 png_free(png_ptr, png_ptr->chunkdata);
1859 png_ptr->chunkdata = NULL;
1860 return;
1862 #else
1863 #ifdef PNG_FIXED_POINT_SUPPORTED
1864 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1865 if (swidth == NULL)
1867 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
1868 png_free(png_ptr, png_ptr->chunkdata);
1869 png_ptr->chunkdata = NULL;
1870 return;
1872 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1873 #endif
1874 #endif
1876 for (ep = png_ptr->chunkdata; *ep; ep++)
1877 /* Empty loop */ ;
1878 ep++;
1880 if (png_ptr->chunkdata + slength < ep)
1882 png_warning(png_ptr, "Truncated sCAL chunk");
1883 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1884 png_free(png_ptr, swidth);
1885 #endif
1886 png_free(png_ptr, png_ptr->chunkdata);
1887 png_ptr->chunkdata = NULL;
1888 return;
1891 #ifdef PNG_FLOATING_POINT_SUPPORTED
1892 height = png_strtod(png_ptr, ep, &vp);
1893 if (*vp)
1895 png_warning(png_ptr, "malformed height string in sCAL chunk");
1896 png_free(png_ptr, png_ptr->chunkdata);
1897 png_ptr->chunkdata = NULL;
1898 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1899 png_free(png_ptr, swidth);
1900 #endif
1901 return;
1903 #else
1904 #ifdef PNG_FIXED_POINT_SUPPORTED
1905 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1906 if (sheight == NULL)
1908 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
1909 png_free(png_ptr, png_ptr->chunkdata);
1910 png_ptr->chunkdata = NULL;
1911 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1912 png_free(png_ptr, swidth);
1913 #endif
1914 return;
1916 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1917 #endif
1918 #endif
1920 if (png_ptr->chunkdata + slength < ep
1921 #ifdef PNG_FLOATING_POINT_SUPPORTED
1922 || width <= 0. || height <= 0.
1923 #endif
1926 png_warning(png_ptr, "Invalid sCAL data");
1927 png_free(png_ptr, png_ptr->chunkdata);
1928 png_ptr->chunkdata = NULL;
1929 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1930 png_free(png_ptr, swidth);
1931 png_free(png_ptr, sheight);
1932 #endif
1933 return;
1937 #ifdef PNG_FLOATING_POINT_SUPPORTED
1938 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
1939 #else
1940 #ifdef PNG_FIXED_POINT_SUPPORTED
1941 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
1942 #endif
1943 #endif
1945 png_free(png_ptr, png_ptr->chunkdata);
1946 png_ptr->chunkdata = NULL;
1947 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1948 png_free(png_ptr, swidth);
1949 png_free(png_ptr, sheight);
1950 #endif
1952 #endif
1954 #ifdef PNG_READ_tIME_SUPPORTED
1955 void /* PRIVATE */
1956 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1958 png_byte buf[7];
1959 png_time mod_time;
1961 png_debug(1, "in png_handle_tIME");
1963 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1964 png_error(png_ptr, "Out of place tIME chunk");
1965 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1967 png_warning(png_ptr, "Duplicate tIME chunk");
1968 png_crc_finish(png_ptr, length);
1969 return;
1972 if (png_ptr->mode & PNG_HAVE_IDAT)
1973 png_ptr->mode |= PNG_AFTER_IDAT;
1975 if (length != 7)
1977 png_warning(png_ptr, "Incorrect tIME chunk length");
1978 png_crc_finish(png_ptr, length);
1979 return;
1982 png_crc_read(png_ptr, buf, 7);
1983 if (png_crc_finish(png_ptr, 0))
1984 return;
1986 mod_time.second = buf[6];
1987 mod_time.minute = buf[5];
1988 mod_time.hour = buf[4];
1989 mod_time.day = buf[3];
1990 mod_time.month = buf[2];
1991 mod_time.year = png_get_uint_16(buf);
1993 png_set_tIME(png_ptr, info_ptr, &mod_time);
1995 #endif
1997 #ifdef PNG_READ_tEXt_SUPPORTED
1998 /* Note: this does not properly handle chunks that are > 64K under DOS */
1999 void /* PRIVATE */
2000 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2002 png_textp text_ptr;
2003 png_charp key;
2004 png_charp text;
2005 png_uint_32 skip = 0;
2006 png_size_t slength;
2007 int ret;
2009 png_debug(1, "in png_handle_tEXt");
2011 #ifdef PNG_USER_LIMITS_SUPPORTED
2012 if (png_ptr->user_chunk_cache_max != 0)
2014 if (png_ptr->user_chunk_cache_max == 1)
2016 png_crc_finish(png_ptr, length);
2017 return;
2019 if (--png_ptr->user_chunk_cache_max == 1)
2021 png_warning(png_ptr, "No space in chunk cache for tEXt");
2022 png_crc_finish(png_ptr, length);
2023 return;
2026 #endif
2028 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2029 png_error(png_ptr, "Missing IHDR before tEXt");
2031 if (png_ptr->mode & PNG_HAVE_IDAT)
2032 png_ptr->mode |= PNG_AFTER_IDAT;
2034 #ifdef PNG_MAX_MALLOC_64K
2035 if (length > (png_uint_32)65535L)
2037 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
2038 skip = length - (png_uint_32)65535L;
2039 length = (png_uint_32)65535L;
2041 #endif
2043 png_free(png_ptr, png_ptr->chunkdata);
2045 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2046 if (png_ptr->chunkdata == NULL)
2048 png_warning(png_ptr, "No memory to process text chunk.");
2049 return;
2051 slength = (png_size_t)length;
2052 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
2054 if (png_crc_finish(png_ptr, skip))
2056 png_free(png_ptr, png_ptr->chunkdata);
2057 png_ptr->chunkdata = NULL;
2058 return;
2061 key = png_ptr->chunkdata;
2063 key[slength] = 0x00;
2065 for (text = key; *text; text++)
2066 /* Empty loop to find end of key */ ;
2068 if (text != key + slength)
2069 text++;
2071 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2072 (png_uint_32)png_sizeof(png_text));
2073 if (text_ptr == NULL)
2075 png_warning(png_ptr, "Not enough memory to process text chunk.");
2076 png_free(png_ptr, png_ptr->chunkdata);
2077 png_ptr->chunkdata = NULL;
2078 return;
2080 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
2081 text_ptr->key = key;
2082 #ifdef PNG_iTXt_SUPPORTED
2083 text_ptr->lang = NULL;
2084 text_ptr->lang_key = NULL;
2085 text_ptr->itxt_length = 0;
2086 #endif
2087 text_ptr->text = text;
2088 text_ptr->text_length = png_strlen(text);
2090 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2092 png_free(png_ptr, png_ptr->chunkdata);
2093 png_ptr->chunkdata = NULL;
2094 png_free(png_ptr, text_ptr);
2095 if (ret)
2096 png_warning(png_ptr, "Insufficient memory to process text chunk.");
2098 #endif
2100 #ifdef PNG_READ_zTXt_SUPPORTED
2101 /* Note: this does not correctly handle chunks that are > 64K under DOS */
2102 void /* PRIVATE */
2103 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2105 png_textp text_ptr;
2106 png_charp text;
2107 int comp_type;
2108 int ret;
2109 png_size_t slength, prefix_len, data_len;
2111 png_debug(1, "in png_handle_zTXt");
2113 #ifdef PNG_USER_LIMITS_SUPPORTED
2114 if (png_ptr->user_chunk_cache_max != 0)
2116 if (png_ptr->user_chunk_cache_max == 1)
2118 png_crc_finish(png_ptr, length);
2119 return;
2121 if (--png_ptr->user_chunk_cache_max == 1)
2123 png_warning(png_ptr, "No space in chunk cache for zTXt");
2124 png_crc_finish(png_ptr, length);
2125 return;
2128 #endif
2130 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2131 png_error(png_ptr, "Missing IHDR before zTXt");
2133 if (png_ptr->mode & PNG_HAVE_IDAT)
2134 png_ptr->mode |= PNG_AFTER_IDAT;
2136 #ifdef PNG_MAX_MALLOC_64K
2137 /* We will no doubt have problems with chunks even half this size, but
2138 there is no hard and fast rule to tell us where to stop. */
2139 if (length > (png_uint_32)65535L)
2141 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
2142 png_crc_finish(png_ptr, length);
2143 return;
2145 #endif
2147 png_free(png_ptr, png_ptr->chunkdata);
2148 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2149 if (png_ptr->chunkdata == NULL)
2151 png_warning(png_ptr, "Out of memory processing zTXt chunk.");
2152 return;
2154 slength = (png_size_t)length;
2155 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
2156 if (png_crc_finish(png_ptr, 0))
2158 png_free(png_ptr, png_ptr->chunkdata);
2159 png_ptr->chunkdata = NULL;
2160 return;
2163 png_ptr->chunkdata[slength] = 0x00;
2165 for (text = png_ptr->chunkdata; *text; text++)
2166 /* Empty loop */ ;
2168 /* zTXt must have some text after the chunkdataword */
2169 if (text >= png_ptr->chunkdata + slength - 2)
2171 png_warning(png_ptr, "Truncated zTXt chunk");
2172 png_free(png_ptr, png_ptr->chunkdata);
2173 png_ptr->chunkdata = NULL;
2174 return;
2176 else
2178 comp_type = *(++text);
2179 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2181 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2182 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2184 text++; /* Skip the compression_method byte */
2186 prefix_len = text - png_ptr->chunkdata;
2188 png_decompress_chunk(png_ptr, comp_type,
2189 (png_size_t)length, prefix_len, &data_len);
2191 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2192 (png_uint_32)png_sizeof(png_text));
2193 if (text_ptr == NULL)
2195 png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
2196 png_free(png_ptr, png_ptr->chunkdata);
2197 png_ptr->chunkdata = NULL;
2198 return;
2200 text_ptr->compression = comp_type;
2201 text_ptr->key = png_ptr->chunkdata;
2202 #ifdef PNG_iTXt_SUPPORTED
2203 text_ptr->lang = NULL;
2204 text_ptr->lang_key = NULL;
2205 text_ptr->itxt_length = 0;
2206 #endif
2207 text_ptr->text = png_ptr->chunkdata + prefix_len;
2208 text_ptr->text_length = data_len;
2210 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2212 png_free(png_ptr, text_ptr);
2213 png_free(png_ptr, png_ptr->chunkdata);
2214 png_ptr->chunkdata = NULL;
2215 if (ret)
2216 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2218 #endif
2220 #ifdef PNG_READ_iTXt_SUPPORTED
2221 /* Note: this does not correctly handle chunks that are > 64K under DOS */
2222 void /* PRIVATE */
2223 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2225 png_textp text_ptr;
2226 png_charp key, lang, text, lang_key;
2227 int comp_flag;
2228 int comp_type = 0;
2229 int ret;
2230 png_size_t slength, prefix_len, data_len;
2232 png_debug(1, "in png_handle_iTXt");
2234 #ifdef PNG_USER_LIMITS_SUPPORTED
2235 if (png_ptr->user_chunk_cache_max != 0)
2237 if (png_ptr->user_chunk_cache_max == 1)
2239 png_crc_finish(png_ptr, length);
2240 return;
2242 if (--png_ptr->user_chunk_cache_max == 1)
2244 png_warning(png_ptr, "No space in chunk cache for iTXt");
2245 png_crc_finish(png_ptr, length);
2246 return;
2249 #endif
2251 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2252 png_error(png_ptr, "Missing IHDR before iTXt");
2254 if (png_ptr->mode & PNG_HAVE_IDAT)
2255 png_ptr->mode |= PNG_AFTER_IDAT;
2257 #ifdef PNG_MAX_MALLOC_64K
2258 /* We will no doubt have problems with chunks even half this size, but
2259 there is no hard and fast rule to tell us where to stop. */
2260 if (length > (png_uint_32)65535L)
2262 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
2263 png_crc_finish(png_ptr, length);
2264 return;
2266 #endif
2268 png_free(png_ptr, png_ptr->chunkdata);
2269 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2270 if (png_ptr->chunkdata == NULL)
2272 png_warning(png_ptr, "No memory to process iTXt chunk.");
2273 return;
2275 slength = (png_size_t)length;
2276 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
2277 if (png_crc_finish(png_ptr, 0))
2279 png_free(png_ptr, png_ptr->chunkdata);
2280 png_ptr->chunkdata = NULL;
2281 return;
2284 png_ptr->chunkdata[slength] = 0x00;
2286 for (lang = png_ptr->chunkdata; *lang; lang++)
2287 /* Empty loop */ ;
2288 lang++; /* Skip NUL separator */
2290 /* iTXt must have a language tag (possibly empty), two compression bytes,
2291 * translated keyword (possibly empty), and possibly some text after the
2292 * keyword
2295 if (lang >= png_ptr->chunkdata + slength - 3)
2297 png_warning(png_ptr, "Truncated iTXt chunk");
2298 png_free(png_ptr, png_ptr->chunkdata);
2299 png_ptr->chunkdata = NULL;
2300 return;
2302 else
2304 comp_flag = *lang++;
2305 comp_type = *lang++;
2308 for (lang_key = lang; *lang_key; lang_key++)
2309 /* Empty loop */ ;
2310 lang_key++; /* Skip NUL separator */
2312 if (lang_key >= png_ptr->chunkdata + slength)
2314 png_warning(png_ptr, "Truncated iTXt chunk");
2315 png_free(png_ptr, png_ptr->chunkdata);
2316 png_ptr->chunkdata = NULL;
2317 return;
2320 for (text = lang_key; *text; text++)
2321 /* Empty loop */ ;
2322 text++; /* Skip NUL separator */
2323 if (text >= png_ptr->chunkdata + slength)
2325 png_warning(png_ptr, "Malformed iTXt chunk");
2326 png_free(png_ptr, png_ptr->chunkdata);
2327 png_ptr->chunkdata = NULL;
2328 return;
2331 prefix_len = text - png_ptr->chunkdata;
2333 key=png_ptr->chunkdata;
2334 if (comp_flag)
2335 png_decompress_chunk(png_ptr, comp_type,
2336 (size_t)length, prefix_len, &data_len);
2337 else
2338 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
2339 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2340 (png_uint_32)png_sizeof(png_text));
2341 if (text_ptr == NULL)
2343 png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
2344 png_free(png_ptr, png_ptr->chunkdata);
2345 png_ptr->chunkdata = NULL;
2346 return;
2348 text_ptr->compression = (int)comp_flag + 1;
2349 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
2350 text_ptr->lang = png_ptr->chunkdata + (lang - key);
2351 text_ptr->itxt_length = data_len;
2352 text_ptr->text_length = 0;
2353 text_ptr->key = png_ptr->chunkdata;
2354 text_ptr->text = png_ptr->chunkdata + prefix_len;
2356 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2358 png_free(png_ptr, text_ptr);
2359 png_free(png_ptr, png_ptr->chunkdata);
2360 png_ptr->chunkdata = NULL;
2361 if (ret)
2362 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
2364 #endif
2366 /* This function is called when we haven't found a handler for a
2367 chunk. If there isn't a problem with the chunk itself (ie bad
2368 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2369 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2370 case it will be saved away to be written out later. */
2371 void /* PRIVATE */
2372 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2374 png_uint_32 skip = 0;
2376 png_debug(1, "in png_handle_unknown");
2378 #ifdef PNG_USER_LIMITS_SUPPORTED
2379 if (png_ptr->user_chunk_cache_max != 0)
2381 if (png_ptr->user_chunk_cache_max == 1)
2383 png_crc_finish(png_ptr, length);
2384 return;
2386 if (--png_ptr->user_chunk_cache_max == 1)
2388 png_warning(png_ptr, "No space in chunk cache for unknown chunk");
2389 png_crc_finish(png_ptr, length);
2390 return;
2393 #endif
2395 if (png_ptr->mode & PNG_HAVE_IDAT)
2397 #ifdef PNG_USE_LOCAL_ARRAYS
2398 PNG_CONST PNG_IDAT;
2399 #endif
2400 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */
2401 png_ptr->mode |= PNG_AFTER_IDAT;
2404 if (!(png_ptr->chunk_name[0] & 0x20))
2406 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
2407 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2408 PNG_HANDLE_CHUNK_ALWAYS
2409 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
2410 && png_ptr->read_user_chunk_fn == NULL
2411 #endif
2413 #endif
2414 png_chunk_error(png_ptr, "unknown critical chunk");
2417 #ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
2418 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
2419 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
2420 || (png_ptr->read_user_chunk_fn != NULL)
2421 #endif
2424 #ifdef PNG_MAX_MALLOC_64K
2425 if (length > (png_uint_32)65535L)
2427 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2428 skip = length - (png_uint_32)65535L;
2429 length = (png_uint_32)65535L;
2431 #endif
2432 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
2433 (png_charp)png_ptr->chunk_name,
2434 png_sizeof(png_ptr->unknown_chunk.name));
2435 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
2436 = '\0';
2437 png_ptr->unknown_chunk.size = (png_size_t)length;
2438 if (length == 0)
2439 png_ptr->unknown_chunk.data = NULL;
2440 else
2442 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2443 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2445 #ifdef PNG_READ_USER_CHUNKS_SUPPORTED
2446 if (png_ptr->read_user_chunk_fn != NULL)
2448 /* Callback to user unknown chunk handler */
2449 int ret;
2450 ret = (*(png_ptr->read_user_chunk_fn))
2451 (png_ptr, &png_ptr->unknown_chunk);
2452 if (ret < 0)
2453 png_chunk_error(png_ptr, "error in user chunk");
2454 if (ret == 0)
2456 if (!(png_ptr->chunk_name[0] & 0x20))
2457 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
2458 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2459 PNG_HANDLE_CHUNK_ALWAYS)
2460 #endif
2461 png_chunk_error(png_ptr, "unknown critical chunk");
2462 png_set_unknown_chunks(png_ptr, info_ptr,
2463 &png_ptr->unknown_chunk, 1);
2466 else
2467 #endif
2468 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
2469 png_free(png_ptr, png_ptr->unknown_chunk.data);
2470 png_ptr->unknown_chunk.data = NULL;
2472 else
2473 #endif
2474 skip = length;
2476 png_crc_finish(png_ptr, skip);
2478 #ifndef PNG_READ_USER_CHUNKS_SUPPORTED
2479 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
2480 #endif
2483 /* This function is called to verify that a chunk name is valid.
2484 This function can't have the "critical chunk check" incorporated
2485 into it, since in the future we will need to be able to call user
2486 functions to handle unknown critical chunks after we check that
2487 the chunk name itself is valid. */
2489 #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
2491 void /* PRIVATE */
2492 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2494 png_debug(1, "in png_check_chunk_name");
2495 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2496 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2498 png_chunk_error(png_ptr, "invalid chunk type");
2502 /* Combines the row recently read in with the existing pixels in the
2503 row. This routine takes care of alpha and transparency if requested.
2504 This routine also handles the two methods of progressive display
2505 of interlaced images, depending on the mask value.
2506 The mask value describes which pixels are to be combined with
2507 the row. The pattern always repeats every 8 pixels, so just 8
2508 bits are needed. A one indicates the pixel is to be combined,
2509 a zero indicates the pixel is to be skipped. This is in addition
2510 to any alpha or transparency value associated with the pixel. If
2511 you want all pixels to be combined, pass 0xff (255) in mask. */
2513 void /* PRIVATE */
2514 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2516 png_debug(1, "in png_combine_row");
2517 if (mask == 0xff)
2519 png_memcpy(row, png_ptr->row_buf + 1,
2520 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
2522 else
2524 switch (png_ptr->row_info.pixel_depth)
2526 case 1:
2528 png_bytep sp = png_ptr->row_buf + 1;
2529 png_bytep dp = row;
2530 int s_inc, s_start, s_end;
2531 int m = 0x80;
2532 int shift;
2533 png_uint_32 i;
2534 png_uint_32 row_width = png_ptr->width;
2536 #ifdef PNG_READ_PACKSWAP_SUPPORTED
2537 if (png_ptr->transformations & PNG_PACKSWAP)
2539 s_start = 0;
2540 s_end = 7;
2541 s_inc = 1;
2543 else
2544 #endif
2546 s_start = 7;
2547 s_end = 0;
2548 s_inc = -1;
2551 shift = s_start;
2553 for (i = 0; i < row_width; i++)
2555 if (m & mask)
2557 int value;
2559 value = (*sp >> shift) & 0x01;
2560 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2561 *dp |= (png_byte)(value << shift);
2564 if (shift == s_end)
2566 shift = s_start;
2567 sp++;
2568 dp++;
2570 else
2571 shift += s_inc;
2573 if (m == 1)
2574 m = 0x80;
2575 else
2576 m >>= 1;
2578 break;
2580 case 2:
2582 png_bytep sp = png_ptr->row_buf + 1;
2583 png_bytep dp = row;
2584 int s_start, s_end, s_inc;
2585 int m = 0x80;
2586 int shift;
2587 png_uint_32 i;
2588 png_uint_32 row_width = png_ptr->width;
2589 int value;
2591 #ifdef PNG_READ_PACKSWAP_SUPPORTED
2592 if (png_ptr->transformations & PNG_PACKSWAP)
2594 s_start = 0;
2595 s_end = 6;
2596 s_inc = 2;
2598 else
2599 #endif
2601 s_start = 6;
2602 s_end = 0;
2603 s_inc = -2;
2606 shift = s_start;
2608 for (i = 0; i < row_width; i++)
2610 if (m & mask)
2612 value = (*sp >> shift) & 0x03;
2613 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2614 *dp |= (png_byte)(value << shift);
2617 if (shift == s_end)
2619 shift = s_start;
2620 sp++;
2621 dp++;
2623 else
2624 shift += s_inc;
2625 if (m == 1)
2626 m = 0x80;
2627 else
2628 m >>= 1;
2630 break;
2632 case 4:
2634 png_bytep sp = png_ptr->row_buf + 1;
2635 png_bytep dp = row;
2636 int s_start, s_end, s_inc;
2637 int m = 0x80;
2638 int shift;
2639 png_uint_32 i;
2640 png_uint_32 row_width = png_ptr->width;
2641 int value;
2643 #ifdef PNG_READ_PACKSWAP_SUPPORTED
2644 if (png_ptr->transformations & PNG_PACKSWAP)
2646 s_start = 0;
2647 s_end = 4;
2648 s_inc = 4;
2650 else
2651 #endif
2653 s_start = 4;
2654 s_end = 0;
2655 s_inc = -4;
2657 shift = s_start;
2659 for (i = 0; i < row_width; i++)
2661 if (m & mask)
2663 value = (*sp >> shift) & 0xf;
2664 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2665 *dp |= (png_byte)(value << shift);
2668 if (shift == s_end)
2670 shift = s_start;
2671 sp++;
2672 dp++;
2674 else
2675 shift += s_inc;
2676 if (m == 1)
2677 m = 0x80;
2678 else
2679 m >>= 1;
2681 break;
2683 default:
2685 png_bytep sp = png_ptr->row_buf + 1;
2686 png_bytep dp = row;
2687 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2688 png_uint_32 i;
2689 png_uint_32 row_width = png_ptr->width;
2690 png_byte m = 0x80;
2693 for (i = 0; i < row_width; i++)
2695 if (m & mask)
2697 png_memcpy(dp, sp, pixel_bytes);
2700 sp += pixel_bytes;
2701 dp += pixel_bytes;
2703 if (m == 1)
2704 m = 0x80;
2705 else
2706 m >>= 1;
2708 break;
2714 #ifdef PNG_READ_INTERLACING_SUPPORTED
2715 /* OLD pre-1.0.9 interface:
2716 void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2717 png_uint_32 transformations)
2719 void /* PRIVATE */
2720 png_do_read_interlace(png_structp png_ptr)
2722 png_row_infop row_info = &(png_ptr->row_info);
2723 png_bytep row = png_ptr->row_buf + 1;
2724 int pass = png_ptr->pass;
2725 png_uint_32 transformations = png_ptr->transformations;
2726 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2727 /* Offset to next interlace block */
2728 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2730 png_debug(1, "in png_do_read_interlace");
2731 if (row != NULL && row_info != NULL)
2733 png_uint_32 final_width;
2735 final_width = row_info->width * png_pass_inc[pass];
2737 switch (row_info->pixel_depth)
2739 case 1:
2741 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2742 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2743 int sshift, dshift;
2744 int s_start, s_end, s_inc;
2745 int jstop = png_pass_inc[pass];
2746 png_byte v;
2747 png_uint_32 i;
2748 int j;
2750 #ifdef PNG_READ_PACKSWAP_SUPPORTED
2751 if (transformations & PNG_PACKSWAP)
2753 sshift = (int)((row_info->width + 7) & 0x07);
2754 dshift = (int)((final_width + 7) & 0x07);
2755 s_start = 7;
2756 s_end = 0;
2757 s_inc = -1;
2759 else
2760 #endif
2762 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2763 dshift = 7 - (int)((final_width + 7) & 0x07);
2764 s_start = 0;
2765 s_end = 7;
2766 s_inc = 1;
2769 for (i = 0; i < row_info->width; i++)
2771 v = (png_byte)((*sp >> sshift) & 0x01);
2772 for (j = 0; j < jstop; j++)
2774 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2775 *dp |= (png_byte)(v << dshift);
2776 if (dshift == s_end)
2778 dshift = s_start;
2779 dp--;
2781 else
2782 dshift += s_inc;
2784 if (sshift == s_end)
2786 sshift = s_start;
2787 sp--;
2789 else
2790 sshift += s_inc;
2792 break;
2794 case 2:
2796 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2797 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2798 int sshift, dshift;
2799 int s_start, s_end, s_inc;
2800 int jstop = png_pass_inc[pass];
2801 png_uint_32 i;
2803 #ifdef PNG_READ_PACKSWAP_SUPPORTED
2804 if (transformations & PNG_PACKSWAP)
2806 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2807 dshift = (int)(((final_width + 3) & 0x03) << 1);
2808 s_start = 6;
2809 s_end = 0;
2810 s_inc = -2;
2812 else
2813 #endif
2815 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2816 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2817 s_start = 0;
2818 s_end = 6;
2819 s_inc = 2;
2822 for (i = 0; i < row_info->width; i++)
2824 png_byte v;
2825 int j;
2827 v = (png_byte)((*sp >> sshift) & 0x03);
2828 for (j = 0; j < jstop; j++)
2830 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2831 *dp |= (png_byte)(v << dshift);
2832 if (dshift == s_end)
2834 dshift = s_start;
2835 dp--;
2837 else
2838 dshift += s_inc;
2840 if (sshift == s_end)
2842 sshift = s_start;
2843 sp--;
2845 else
2846 sshift += s_inc;
2848 break;
2850 case 4:
2852 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2853 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2854 int sshift, dshift;
2855 int s_start, s_end, s_inc;
2856 png_uint_32 i;
2857 int jstop = png_pass_inc[pass];
2859 #ifdef PNG_READ_PACKSWAP_SUPPORTED
2860 if (transformations & PNG_PACKSWAP)
2862 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2863 dshift = (int)(((final_width + 1) & 0x01) << 2);
2864 s_start = 4;
2865 s_end = 0;
2866 s_inc = -4;
2868 else
2869 #endif
2871 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2872 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2873 s_start = 0;
2874 s_end = 4;
2875 s_inc = 4;
2878 for (i = 0; i < row_info->width; i++)
2880 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2881 int j;
2883 for (j = 0; j < jstop; j++)
2885 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2886 *dp |= (png_byte)(v << dshift);
2887 if (dshift == s_end)
2889 dshift = s_start;
2890 dp--;
2892 else
2893 dshift += s_inc;
2895 if (sshift == s_end)
2897 sshift = s_start;
2898 sp--;
2900 else
2901 sshift += s_inc;
2903 break;
2905 default:
2907 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2908 png_bytep sp = row + (png_size_t)(row_info->width - 1)
2909 * pixel_bytes;
2910 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2912 int jstop = png_pass_inc[pass];
2913 png_uint_32 i;
2915 for (i = 0; i < row_info->width; i++)
2917 png_byte v[8];
2918 int j;
2920 png_memcpy(v, sp, pixel_bytes);
2921 for (j = 0; j < jstop; j++)
2923 png_memcpy(dp, v, pixel_bytes);
2924 dp -= pixel_bytes;
2926 sp -= pixel_bytes;
2928 break;
2931 row_info->width = final_width;
2932 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
2934 #ifndef PNG_READ_PACKSWAP_SUPPORTED
2935 transformations = transformations; /* Silence compiler warning */
2936 #endif
2938 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2940 void /* PRIVATE */
2941 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2942 png_bytep prev_row, int filter)
2944 png_debug(1, "in png_read_filter_row");
2945 png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
2946 switch (filter)
2948 case PNG_FILTER_VALUE_NONE:
2949 break;
2950 case PNG_FILTER_VALUE_SUB:
2952 png_uint_32 i;
2953 png_uint_32 istop = row_info->rowbytes;
2954 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2955 png_bytep rp = row + bpp;
2956 png_bytep lp = row;
2958 for (i = bpp; i < istop; i++)
2960 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2961 rp++;
2963 break;
2965 case PNG_FILTER_VALUE_UP:
2967 png_uint_32 i;
2968 png_uint_32 istop = row_info->rowbytes;
2969 png_bytep rp = row;
2970 png_bytep pp = prev_row;
2972 for (i = 0; i < istop; i++)
2974 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2975 rp++;
2977 break;
2979 case PNG_FILTER_VALUE_AVG:
2981 png_uint_32 i;
2982 png_bytep rp = row;
2983 png_bytep pp = prev_row;
2984 png_bytep lp = row;
2985 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2986 png_uint_32 istop = row_info->rowbytes - bpp;
2988 for (i = 0; i < bpp; i++)
2990 *rp = (png_byte)(((int)(*rp) +
2991 ((int)(*pp++) / 2 )) & 0xff);
2992 rp++;
2995 for (i = 0; i < istop; i++)
2997 *rp = (png_byte)(((int)(*rp) +
2998 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2999 rp++;
3001 break;
3003 case PNG_FILTER_VALUE_PAETH:
3005 png_uint_32 i;
3006 png_bytep rp = row;
3007 png_bytep pp = prev_row;
3008 png_bytep lp = row;
3009 png_bytep cp = prev_row;
3010 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3011 png_uint_32 istop=row_info->rowbytes - bpp;
3013 for (i = 0; i < bpp; i++)
3015 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3016 rp++;
3019 for (i = 0; i < istop; i++) /* Use leftover rp,pp */
3021 int a, b, c, pa, pb, pc, p;
3023 a = *lp++;
3024 b = *pp++;
3025 c = *cp++;
3027 p = b - c;
3028 pc = a - c;
3030 #ifdef PNG_USE_ABS
3031 pa = abs(p);
3032 pb = abs(pc);
3033 pc = abs(p + pc);
3034 #else
3035 pa = p < 0 ? -p : p;
3036 pb = pc < 0 ? -pc : pc;
3037 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3038 #endif
3041 if (pa <= pb && pa <= pc)
3042 p = a;
3043 else if (pb <= pc)
3044 p = b;
3045 else
3046 p = c;
3049 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
3051 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
3052 rp++;
3054 break;
3056 default:
3057 png_warning(png_ptr, "Ignoring bad adaptive filter type");
3058 *row = 0;
3059 break;
3063 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED
3064 void /* PRIVATE */
3065 png_read_finish_row(png_structp png_ptr)
3067 #ifdef PNG_READ_INTERLACING_SUPPORTED
3068 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3070 /* Start of interlace block */
3071 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3073 /* Offset to next interlace block */
3074 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3076 /* Start of interlace block in the y direction */
3077 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3079 /* Offset to next interlace block in the y direction */
3080 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3081 #endif /* PNG_READ_INTERLACING_SUPPORTED */
3083 png_debug(1, "in png_read_finish_row");
3084 png_ptr->row_number++;
3085 if (png_ptr->row_number < png_ptr->num_rows)
3086 return;
3088 #ifdef PNG_READ_INTERLACING_SUPPORTED
3089 if (png_ptr->interlaced)
3091 png_ptr->row_number = 0;
3092 png_memset_check(png_ptr, png_ptr->prev_row, 0,
3093 png_ptr->rowbytes + 1);
3096 png_ptr->pass++;
3097 if (png_ptr->pass >= 7)
3098 break;
3099 png_ptr->iwidth = (png_ptr->width +
3100 png_pass_inc[png_ptr->pass] - 1 -
3101 png_pass_start[png_ptr->pass]) /
3102 png_pass_inc[png_ptr->pass];
3104 if (!(png_ptr->transformations & PNG_INTERLACE))
3106 png_ptr->num_rows = (png_ptr->height +
3107 png_pass_yinc[png_ptr->pass] - 1 -
3108 png_pass_ystart[png_ptr->pass]) /
3109 png_pass_yinc[png_ptr->pass];
3110 if (!(png_ptr->num_rows))
3111 continue;
3113 else /* if (png_ptr->transformations & PNG_INTERLACE) */
3114 break;
3115 } while (png_ptr->iwidth == 0);
3117 if (png_ptr->pass < 7)
3118 return;
3120 #endif /* PNG_READ_INTERLACING_SUPPORTED */
3122 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
3124 #ifdef PNG_USE_LOCAL_ARRAYS
3125 PNG_CONST PNG_IDAT;
3126 #endif
3127 char extra;
3128 int ret;
3130 png_ptr->zstream.next_out = (Byte *)&extra;
3131 png_ptr->zstream.avail_out = (uInt)1;
3132 for (;;)
3134 if (!(png_ptr->zstream.avail_in))
3136 while (!png_ptr->idat_size)
3138 png_byte chunk_length[4];
3140 png_crc_finish(png_ptr, 0);
3142 png_read_data(png_ptr, chunk_length, 4);
3143 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
3144 png_reset_crc(png_ptr);
3145 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
3146 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
3147 png_error(png_ptr, "Not enough image data");
3150 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
3151 png_ptr->zstream.next_in = png_ptr->zbuf;
3152 if (png_ptr->zbuf_size > png_ptr->idat_size)
3153 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
3154 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
3155 png_ptr->idat_size -= png_ptr->zstream.avail_in;
3157 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
3158 if (ret == Z_STREAM_END)
3160 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
3161 png_ptr->idat_size)
3162 png_warning(png_ptr, "Extra compressed data.");
3163 png_ptr->mode |= PNG_AFTER_IDAT;
3164 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3165 break;
3167 if (ret != Z_OK)
3168 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
3169 "Decompression Error");
3171 if (!(png_ptr->zstream.avail_out))
3173 png_warning(png_ptr, "Extra compressed data.");
3174 png_ptr->mode |= PNG_AFTER_IDAT;
3175 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3176 break;
3180 png_ptr->zstream.avail_out = 0;
3183 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
3184 png_warning(png_ptr, "Extra compression data.");
3186 inflateReset(&png_ptr->zstream);
3188 png_ptr->mode |= PNG_AFTER_IDAT;
3190 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
3192 void /* PRIVATE */
3193 png_read_start_row(png_structp png_ptr)
3195 #ifdef PNG_READ_INTERLACING_SUPPORTED
3196 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3198 /* Start of interlace block */
3199 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3201 /* Offset to next interlace block */
3202 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3204 /* Start of interlace block in the y direction */
3205 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3207 /* Offset to next interlace block in the y direction */
3208 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3209 #endif
3211 int max_pixel_depth;
3212 png_size_t row_bytes;
3214 png_debug(1, "in png_read_start_row");
3215 png_ptr->zstream.avail_in = 0;
3216 png_init_read_transformations(png_ptr);
3217 #ifdef PNG_READ_INTERLACING_SUPPORTED
3218 if (png_ptr->interlaced)
3220 if (!(png_ptr->transformations & PNG_INTERLACE))
3221 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
3222 png_pass_ystart[0]) / png_pass_yinc[0];
3223 else
3224 png_ptr->num_rows = png_ptr->height;
3226 png_ptr->iwidth = (png_ptr->width +
3227 png_pass_inc[png_ptr->pass] - 1 -
3228 png_pass_start[png_ptr->pass]) /
3229 png_pass_inc[png_ptr->pass];
3231 else
3232 #endif /* PNG_READ_INTERLACING_SUPPORTED */
3234 png_ptr->num_rows = png_ptr->height;
3235 png_ptr->iwidth = png_ptr->width;
3237 max_pixel_depth = png_ptr->pixel_depth;
3239 #ifdef PNG_READ_PACK_SUPPORTED
3240 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
3241 max_pixel_depth = 8;
3242 #endif
3244 #ifdef PNG_READ_EXPAND_SUPPORTED
3245 if (png_ptr->transformations & PNG_EXPAND)
3247 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3249 if (png_ptr->num_trans)
3250 max_pixel_depth = 32;
3251 else
3252 max_pixel_depth = 24;
3254 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3256 if (max_pixel_depth < 8)
3257 max_pixel_depth = 8;
3258 if (png_ptr->num_trans)
3259 max_pixel_depth *= 2;
3261 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3263 if (png_ptr->num_trans)
3265 max_pixel_depth *= 4;
3266 max_pixel_depth /= 3;
3270 #endif
3272 #ifdef PNG_READ_FILLER_SUPPORTED
3273 if (png_ptr->transformations & (PNG_FILLER))
3275 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3276 max_pixel_depth = 32;
3277 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3279 if (max_pixel_depth <= 8)
3280 max_pixel_depth = 16;
3281 else
3282 max_pixel_depth = 32;
3284 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3286 if (max_pixel_depth <= 32)
3287 max_pixel_depth = 32;
3288 else
3289 max_pixel_depth = 64;
3292 #endif
3294 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
3295 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3297 if (
3298 #ifdef PNG_READ_EXPAND_SUPPORTED
3299 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3300 #endif
3301 #ifdef PNG_READ_FILLER_SUPPORTED
3302 (png_ptr->transformations & (PNG_FILLER)) ||
3303 #endif
3304 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3306 if (max_pixel_depth <= 16)
3307 max_pixel_depth = 32;
3308 else
3309 max_pixel_depth = 64;
3311 else
3313 if (max_pixel_depth <= 8)
3315 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3316 max_pixel_depth = 32;
3317 else
3318 max_pixel_depth = 24;
3320 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3321 max_pixel_depth = 64;
3322 else
3323 max_pixel_depth = 48;
3326 #endif
3328 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3329 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
3330 if (png_ptr->transformations & PNG_USER_TRANSFORM)
3332 int user_pixel_depth = png_ptr->user_transform_depth*
3333 png_ptr->user_transform_channels;
3334 if (user_pixel_depth > max_pixel_depth)
3335 max_pixel_depth=user_pixel_depth;
3337 #endif
3339 /* Align the width on the next larger 8 pixels. Mainly used
3340 * for interlacing
3342 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
3343 /* Calculate the maximum bytes needed, adding a byte and a pixel
3344 * for safety's sake
3346 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
3347 1 + ((max_pixel_depth + 7) >> 3);
3348 #ifdef PNG_MAX_MALLOC_64K
3349 if (row_bytes > (png_uint_32)65536L)
3350 png_error(png_ptr, "This image requires a row greater than 64KB");
3351 #endif
3353 if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
3355 png_free(png_ptr, png_ptr->big_row_buf);
3356 if (png_ptr->interlaced)
3357 png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
3358 row_bytes + 64);
3359 else
3360 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
3361 row_bytes + 64);
3362 png_ptr->old_big_row_buf_size = row_bytes + 64;
3364 /* Use 32 bytes of padding before and after row_buf. */
3365 png_ptr->row_buf = png_ptr->big_row_buf + 32;
3366 png_ptr->old_big_row_buf_size = row_bytes + 64;
3369 #ifdef PNG_MAX_MALLOC_64K
3370 if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L)
3371 png_error(png_ptr, "This image requires a row greater than 64KB");
3372 #endif
3373 if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1))
3374 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
3376 if (row_bytes + 1 > png_ptr->old_prev_row_size)
3378 png_free(png_ptr, png_ptr->prev_row);
3379 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3380 row_bytes + 1));
3381 png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1);
3382 png_ptr->old_prev_row_size = row_bytes + 1;
3385 png_ptr->rowbytes = row_bytes;
3387 png_debug1(3, "width = %lu,", png_ptr->width);
3388 png_debug1(3, "height = %lu,", png_ptr->height);
3389 png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
3390 png_debug1(3, "num_rows = %lu,", png_ptr->num_rows);
3391 png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
3392 png_debug1(3, "irowbytes = %lu",
3393 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
3395 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3397 #endif /* PNG_READ_SUPPORTED */