Fix incorrect 10-bit color issue.
[xy_vsfilter.git] / src / libpng / pngrutil.c
bloba5f9ccf3c3c41e98a12e2f631a4d4af8db91c6ca
2 /* pngrutil.c - utilities to read a PNG file
4 * Last changed in libpng 1.2.37 [June 4, 2009]
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2009 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.)
10 * This file contains routines that are only called from within
11 * libpng itself during the course of reading an image.
14 #define PNG_INTERNAL
15 #include "png.h"
16 #if defined(PNG_READ_SUPPORTED)
18 #if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
19 # define WIN32_WCE_OLD
20 #endif
22 #ifdef PNG_FLOATING_POINT_SUPPORTED
23 # if defined(WIN32_WCE_OLD)
24 /* The strtod() function is not supported on WindowsCE */
25 __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr)
27 double result = 0;
28 int len;
29 wchar_t *str, *end;
31 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
32 str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
33 if ( NULL != str )
35 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
36 result = wcstod(str, &end);
37 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
38 *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
39 png_free(png_ptr, str);
41 return result;
43 # else
44 # define png_strtod(p,a,b) strtod(a,b)
45 # endif
46 #endif
48 png_uint_32 PNGAPI
49 png_get_uint_31(png_structp png_ptr, png_bytep buf)
51 #ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
52 png_uint_32 i = png_get_uint_32(buf);
53 #else
54 /* Avoid an extra function call by inlining the result. */
55 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
56 ((png_uint_32)(*(buf + 1)) << 16) +
57 ((png_uint_32)(*(buf + 2)) << 8) +
58 (png_uint_32)(*(buf + 3));
59 #endif
60 if (i > PNG_UINT_31_MAX)
61 png_error(png_ptr, "PNG unsigned integer out of range.");
62 return (i);
64 #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
65 /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
66 png_uint_32 PNGAPI
67 png_get_uint_32(png_bytep buf)
69 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
70 ((png_uint_32)(*(buf + 1)) << 16) +
71 ((png_uint_32)(*(buf + 2)) << 8) +
72 (png_uint_32)(*(buf + 3));
74 return (i);
77 /* Grab a signed 32-bit integer from a buffer in big-endian format. The
78 * data is stored in the PNG file in two's complement format, and it is
79 * assumed that the machine format for signed integers is the same.
81 png_int_32 PNGAPI
82 png_get_int_32(png_bytep buf)
84 png_int_32 i = ((png_int_32)(*buf) << 24) +
85 ((png_int_32)(*(buf + 1)) << 16) +
86 ((png_int_32)(*(buf + 2)) << 8) +
87 (png_int_32)(*(buf + 3));
89 return (i);
92 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
93 png_uint_16 PNGAPI
94 png_get_uint_16(png_bytep buf)
96 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
97 (png_uint_16)(*(buf + 1)));
99 return (i);
101 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
103 /* Read the chunk header (length + type name).
104 * Put the type name into png_ptr->chunk_name, and return the length.
106 png_uint_32 /* PRIVATE */
107 png_read_chunk_header(png_structp png_ptr)
109 png_byte buf[8];
110 png_uint_32 length;
112 /* Read the length and the chunk name */
113 png_read_data(png_ptr, buf, 8);
114 length = png_get_uint_31(png_ptr, buf);
116 /* Put the chunk name into png_ptr->chunk_name */
117 png_memcpy(png_ptr->chunk_name, buf + 4, 4);
119 png_debug2(0, "Reading %s chunk, length = %lu",
120 png_ptr->chunk_name, length);
122 /* Reset the crc and run it over the chunk name */
123 png_reset_crc(png_ptr);
124 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
126 /* Check to see if chunk name is valid */
127 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
129 return length;
132 /* Read data, and (optionally) run it through the CRC. */
133 void /* PRIVATE */
134 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
136 if (png_ptr == NULL)
137 return;
138 png_read_data(png_ptr, buf, length);
139 png_calculate_crc(png_ptr, buf, length);
142 /* Optionally skip data and then check the CRC. Depending on whether we
143 * are reading a ancillary or critical chunk, and how the program has set
144 * things up, we may calculate the CRC on the data and print a message.
145 * Returns '1' if there was a CRC error, '0' otherwise.
147 int /* PRIVATE */
148 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
150 png_size_t i;
151 png_size_t istop = png_ptr->zbuf_size;
153 for (i = (png_size_t)skip; i > istop; i -= istop)
155 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
157 if (i)
159 png_crc_read(png_ptr, png_ptr->zbuf, i);
162 if (png_crc_error(png_ptr))
164 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
165 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
166 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
167 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
169 png_chunk_warning(png_ptr, "CRC error");
171 else
173 png_chunk_error(png_ptr, "CRC error");
175 return (1);
178 return (0);
181 /* Compare the CRC stored in the PNG file with that calculated by libpng from
182 * the data it has read thus far.
184 int /* PRIVATE */
185 png_crc_error(png_structp png_ptr)
187 png_byte crc_bytes[4];
188 png_uint_32 crc;
189 int need_crc = 1;
191 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
193 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
194 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
195 need_crc = 0;
197 else /* critical */
199 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
200 need_crc = 0;
203 png_read_data(png_ptr, crc_bytes, 4);
205 if (need_crc)
207 crc = png_get_uint_32(crc_bytes);
208 return ((int)(crc != png_ptr->crc));
210 else
211 return (0);
214 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
215 defined(PNG_READ_iCCP_SUPPORTED)
217 * Decompress trailing data in a chunk. The assumption is that chunkdata
218 * points at an allocated area holding the contents of a chunk with a
219 * trailing compressed part. What we get back is an allocated area
220 * holding the original prefix part and an uncompressed version of the
221 * trailing part (the malloc area passed in is freed).
223 void /* PRIVATE */
224 png_decompress_chunk(png_structp png_ptr, int comp_type,
225 png_size_t chunklength,
226 png_size_t prefix_size, png_size_t *newlength)
228 static PNG_CONST char msg[] = "Error decoding compressed text";
229 png_charp text;
230 png_size_t text_size;
232 if (comp_type == PNG_COMPRESSION_TYPE_BASE)
234 int ret = Z_OK;
235 png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size);
236 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
237 png_ptr->zstream.next_out = png_ptr->zbuf;
238 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
240 text_size = 0;
241 text = NULL;
243 while (png_ptr->zstream.avail_in)
245 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
246 if (ret != Z_OK && ret != Z_STREAM_END)
248 if (png_ptr->zstream.msg != NULL)
249 png_warning(png_ptr, png_ptr->zstream.msg);
250 else
251 png_warning(png_ptr, msg);
252 inflateReset(&png_ptr->zstream);
253 png_ptr->zstream.avail_in = 0;
255 if (text == NULL)
257 text_size = prefix_size + png_sizeof(msg) + 1;
258 text = (png_charp)png_malloc_warn(png_ptr, text_size);
259 if (text == NULL)
261 png_free(png_ptr, png_ptr->chunkdata);
262 png_ptr->chunkdata = NULL;
263 png_error(png_ptr, "Not enough memory to decompress chunk");
265 png_memcpy(text, png_ptr->chunkdata, prefix_size);
268 text[text_size - 1] = 0x00;
270 /* Copy what we can of the error message into the text chunk */
271 text_size = (png_size_t)(chunklength -
272 (text - png_ptr->chunkdata) - 1);
273 if (text_size > png_sizeof(msg))
274 text_size = png_sizeof(msg);
275 png_memcpy(text + prefix_size, msg, text_size);
276 break;
278 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
280 if (text == NULL)
282 text_size = prefix_size +
283 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
284 text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
285 if (text == NULL)
287 png_free(png_ptr, png_ptr->chunkdata);
288 png_ptr->chunkdata = NULL;
289 png_error(png_ptr,
290 "Not enough memory to decompress chunk.");
292 png_memcpy(text + prefix_size, png_ptr->zbuf,
293 text_size - prefix_size);
294 png_memcpy(text, png_ptr->chunkdata, prefix_size);
295 *(text + text_size) = 0x00;
297 else
299 png_charp tmp;
301 tmp = text;
302 text = (png_charp)png_malloc_warn(png_ptr,
303 (png_uint_32)(text_size +
304 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
305 if (text == NULL)
307 png_free(png_ptr, tmp);
308 png_free(png_ptr, png_ptr->chunkdata);
309 png_ptr->chunkdata = NULL;
310 png_error(png_ptr,
311 "Not enough memory to decompress chunk..");
313 png_memcpy(text, tmp, text_size);
314 png_free(png_ptr, tmp);
315 png_memcpy(text + text_size, png_ptr->zbuf,
316 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
317 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
318 *(text + text_size) = 0x00;
320 if (ret == Z_STREAM_END)
321 break;
322 else
324 png_ptr->zstream.next_out = png_ptr->zbuf;
325 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
329 if (ret != Z_STREAM_END)
331 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
332 char umsg[52];
334 if (ret == Z_BUF_ERROR)
335 png_snprintf(umsg, 52,
336 "Buffer error in compressed datastream in %s chunk",
337 png_ptr->chunk_name);
339 else if (ret == Z_DATA_ERROR)
340 png_snprintf(umsg, 52,
341 "Data error in compressed datastream in %s chunk",
342 png_ptr->chunk_name);
344 else
345 png_snprintf(umsg, 52,
346 "Incomplete compressed datastream in %s chunk",
347 png_ptr->chunk_name);
349 png_warning(png_ptr, umsg);
350 #else
351 png_warning(png_ptr,
352 "Incomplete compressed datastream in chunk other than IDAT");
353 #endif
354 text_size = prefix_size;
355 if (text == NULL)
357 text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
358 if (text == NULL)
360 png_free(png_ptr, png_ptr->chunkdata);
361 png_ptr->chunkdata = NULL;
362 png_error(png_ptr, "Not enough memory for text.");
364 png_memcpy(text, png_ptr->chunkdata, prefix_size);
366 *(text + text_size) = 0x00;
369 inflateReset(&png_ptr->zstream);
370 png_ptr->zstream.avail_in = 0;
372 png_free(png_ptr, png_ptr->chunkdata);
373 png_ptr->chunkdata = text;
374 *newlength=text_size;
376 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
378 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
379 char umsg[50];
381 png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type);
382 png_warning(png_ptr, umsg);
383 #else
384 png_warning(png_ptr, "Unknown zTXt compression type");
385 #endif
387 *(png_ptr->chunkdata + prefix_size) = 0x00;
388 *newlength = prefix_size;
391 #endif
393 /* Read and check the IDHR chunk */
394 void /* PRIVATE */
395 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
397 png_byte buf[13];
398 png_uint_32 width, height;
399 int bit_depth, color_type, compression_type, filter_type;
400 int interlace_type;
402 png_debug(1, "in png_handle_IHDR");
404 if (png_ptr->mode & PNG_HAVE_IHDR)
405 png_error(png_ptr, "Out of place IHDR");
407 /* Check the length */
408 if (length != 13)
409 png_error(png_ptr, "Invalid IHDR chunk");
411 png_ptr->mode |= PNG_HAVE_IHDR;
413 png_crc_read(png_ptr, buf, 13);
414 png_crc_finish(png_ptr, 0);
416 width = png_get_uint_31(png_ptr, buf);
417 height = png_get_uint_31(png_ptr, buf + 4);
418 bit_depth = buf[8];
419 color_type = buf[9];
420 compression_type = buf[10];
421 filter_type = buf[11];
422 interlace_type = buf[12];
424 /* Set internal variables */
425 png_ptr->width = width;
426 png_ptr->height = height;
427 png_ptr->bit_depth = (png_byte)bit_depth;
428 png_ptr->interlaced = (png_byte)interlace_type;
429 png_ptr->color_type = (png_byte)color_type;
430 #if defined(PNG_MNG_FEATURES_SUPPORTED)
431 png_ptr->filter_type = (png_byte)filter_type;
432 #endif
433 png_ptr->compression_type = (png_byte)compression_type;
435 /* Find number of channels */
436 switch (png_ptr->color_type)
438 case PNG_COLOR_TYPE_GRAY:
439 case PNG_COLOR_TYPE_PALETTE:
440 png_ptr->channels = 1;
441 break;
443 case PNG_COLOR_TYPE_RGB:
444 png_ptr->channels = 3;
445 break;
447 case PNG_COLOR_TYPE_GRAY_ALPHA:
448 png_ptr->channels = 2;
449 break;
451 case PNG_COLOR_TYPE_RGB_ALPHA:
452 png_ptr->channels = 4;
453 break;
456 /* Set up other useful info */
457 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
458 png_ptr->channels);
459 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
460 png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
461 png_debug1(3, "channels = %d", png_ptr->channels);
462 png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
463 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
464 color_type, interlace_type, compression_type, filter_type);
467 /* Read and check the palette */
468 void /* PRIVATE */
469 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
471 png_color palette[PNG_MAX_PALETTE_LENGTH];
472 int num, i;
473 #ifndef PNG_NO_POINTER_INDEXING
474 png_colorp pal_ptr;
475 #endif
477 png_debug(1, "in png_handle_PLTE");
479 if (!(png_ptr->mode & PNG_HAVE_IHDR))
480 png_error(png_ptr, "Missing IHDR before PLTE");
482 else if (png_ptr->mode & PNG_HAVE_IDAT)
484 png_warning(png_ptr, "Invalid PLTE after IDAT");
485 png_crc_finish(png_ptr, length);
486 return;
489 else if (png_ptr->mode & PNG_HAVE_PLTE)
490 png_error(png_ptr, "Duplicate PLTE chunk");
492 png_ptr->mode |= PNG_HAVE_PLTE;
494 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
496 png_warning(png_ptr,
497 "Ignoring PLTE chunk in grayscale PNG");
498 png_crc_finish(png_ptr, length);
499 return;
501 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
502 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
504 png_crc_finish(png_ptr, length);
505 return;
507 #endif
509 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
511 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
513 png_warning(png_ptr, "Invalid palette chunk");
514 png_crc_finish(png_ptr, length);
515 return;
518 else
520 png_error(png_ptr, "Invalid palette chunk");
524 num = (int)length / 3;
526 #ifndef PNG_NO_POINTER_INDEXING
527 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
529 png_byte buf[3];
531 png_crc_read(png_ptr, buf, 3);
532 pal_ptr->red = buf[0];
533 pal_ptr->green = buf[1];
534 pal_ptr->blue = buf[2];
536 #else
537 for (i = 0; i < num; i++)
539 png_byte buf[3];
541 png_crc_read(png_ptr, buf, 3);
542 /* Don't depend upon png_color being any order */
543 palette[i].red = buf[0];
544 palette[i].green = buf[1];
545 palette[i].blue = buf[2];
547 #endif
549 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
550 * whatever the normal CRC configuration tells us. However, if we
551 * have an RGB image, the PLTE can be considered ancillary, so
552 * we will act as though it is.
554 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
555 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
556 #endif
558 png_crc_finish(png_ptr, 0);
560 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
561 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
563 /* If we don't want to use the data from an ancillary chunk,
564 we have two options: an error abort, or a warning and we
565 ignore the data in this chunk (which should be OK, since
566 it's considered ancillary for a RGB or RGBA image). */
567 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
569 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
571 png_chunk_error(png_ptr, "CRC error");
573 else
575 png_chunk_warning(png_ptr, "CRC error");
576 return;
579 /* Otherwise, we (optionally) emit a warning and use the chunk. */
580 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
582 png_chunk_warning(png_ptr, "CRC error");
585 #endif
587 png_set_PLTE(png_ptr, info_ptr, palette, num);
589 #if defined(PNG_READ_tRNS_SUPPORTED)
590 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
592 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
594 if (png_ptr->num_trans > (png_uint_16)num)
596 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
597 png_ptr->num_trans = (png_uint_16)num;
599 if (info_ptr->num_trans > (png_uint_16)num)
601 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
602 info_ptr->num_trans = (png_uint_16)num;
606 #endif
610 void /* PRIVATE */
611 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
613 png_debug(1, "in png_handle_IEND");
615 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
617 png_error(png_ptr, "No image in file");
620 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
622 if (length != 0)
624 png_warning(png_ptr, "Incorrect IEND chunk length");
626 png_crc_finish(png_ptr, length);
628 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
631 #if defined(PNG_READ_gAMA_SUPPORTED)
632 void /* PRIVATE */
633 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
635 png_fixed_point igamma;
636 #ifdef PNG_FLOATING_POINT_SUPPORTED
637 float file_gamma;
638 #endif
639 png_byte buf[4];
641 png_debug(1, "in png_handle_gAMA");
643 if (!(png_ptr->mode & PNG_HAVE_IHDR))
644 png_error(png_ptr, "Missing IHDR before gAMA");
645 else if (png_ptr->mode & PNG_HAVE_IDAT)
647 png_warning(png_ptr, "Invalid gAMA after IDAT");
648 png_crc_finish(png_ptr, length);
649 return;
651 else if (png_ptr->mode & PNG_HAVE_PLTE)
652 /* Should be an error, but we can cope with it */
653 png_warning(png_ptr, "Out of place gAMA chunk");
655 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
656 #if defined(PNG_READ_sRGB_SUPPORTED)
657 && !(info_ptr->valid & PNG_INFO_sRGB)
658 #endif
661 png_warning(png_ptr, "Duplicate gAMA chunk");
662 png_crc_finish(png_ptr, length);
663 return;
666 if (length != 4)
668 png_warning(png_ptr, "Incorrect gAMA chunk length");
669 png_crc_finish(png_ptr, length);
670 return;
673 png_crc_read(png_ptr, buf, 4);
674 if (png_crc_finish(png_ptr, 0))
675 return;
677 igamma = (png_fixed_point)png_get_uint_32(buf);
678 /* Check for zero gamma */
679 if (igamma == 0)
681 png_warning(png_ptr,
682 "Ignoring gAMA chunk with gamma=0");
683 return;
686 #if defined(PNG_READ_sRGB_SUPPORTED)
687 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
688 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
690 png_warning(png_ptr,
691 "Ignoring incorrect gAMA value when sRGB is also present");
692 #ifndef PNG_NO_CONSOLE_IO
693 fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
694 #endif
695 return;
697 #endif /* PNG_READ_sRGB_SUPPORTED */
699 #ifdef PNG_FLOATING_POINT_SUPPORTED
700 file_gamma = (float)igamma / (float)100000.0;
701 # ifdef PNG_READ_GAMMA_SUPPORTED
702 png_ptr->gamma = file_gamma;
703 # endif
704 png_set_gAMA(png_ptr, info_ptr, file_gamma);
705 #endif
706 #ifdef PNG_FIXED_POINT_SUPPORTED
707 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
708 #endif
710 #endif
712 #if defined(PNG_READ_sBIT_SUPPORTED)
713 void /* PRIVATE */
714 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
716 png_size_t truelen;
717 png_byte buf[4];
719 png_debug(1, "in png_handle_sBIT");
721 buf[0] = buf[1] = buf[2] = buf[3] = 0;
723 if (!(png_ptr->mode & PNG_HAVE_IHDR))
724 png_error(png_ptr, "Missing IHDR before sBIT");
725 else if (png_ptr->mode & PNG_HAVE_IDAT)
727 png_warning(png_ptr, "Invalid sBIT after IDAT");
728 png_crc_finish(png_ptr, length);
729 return;
731 else if (png_ptr->mode & PNG_HAVE_PLTE)
733 /* Should be an error, but we can cope with it */
734 png_warning(png_ptr, "Out of place sBIT chunk");
736 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
738 png_warning(png_ptr, "Duplicate sBIT chunk");
739 png_crc_finish(png_ptr, length);
740 return;
743 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
744 truelen = 3;
745 else
746 truelen = (png_size_t)png_ptr->channels;
748 if (length != truelen || length > 4)
750 png_warning(png_ptr, "Incorrect sBIT chunk length");
751 png_crc_finish(png_ptr, length);
752 return;
755 png_crc_read(png_ptr, buf, truelen);
756 if (png_crc_finish(png_ptr, 0))
757 return;
759 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
761 png_ptr->sig_bit.red = buf[0];
762 png_ptr->sig_bit.green = buf[1];
763 png_ptr->sig_bit.blue = buf[2];
764 png_ptr->sig_bit.alpha = buf[3];
766 else
768 png_ptr->sig_bit.gray = buf[0];
769 png_ptr->sig_bit.red = buf[0];
770 png_ptr->sig_bit.green = buf[0];
771 png_ptr->sig_bit.blue = buf[0];
772 png_ptr->sig_bit.alpha = buf[1];
774 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
776 #endif
778 #if defined(PNG_READ_cHRM_SUPPORTED)
779 void /* PRIVATE */
780 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
782 png_byte buf[32];
783 #ifdef PNG_FLOATING_POINT_SUPPORTED
784 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
785 #endif
786 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
787 int_y_green, int_x_blue, int_y_blue;
789 png_uint_32 uint_x, uint_y;
791 png_debug(1, "in png_handle_cHRM");
793 if (!(png_ptr->mode & PNG_HAVE_IHDR))
794 png_error(png_ptr, "Missing IHDR before cHRM");
795 else if (png_ptr->mode & PNG_HAVE_IDAT)
797 png_warning(png_ptr, "Invalid cHRM after IDAT");
798 png_crc_finish(png_ptr, length);
799 return;
801 else if (png_ptr->mode & PNG_HAVE_PLTE)
802 /* Should be an error, but we can cope with it */
803 png_warning(png_ptr, "Missing PLTE before cHRM");
805 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
806 #if defined(PNG_READ_sRGB_SUPPORTED)
807 && !(info_ptr->valid & PNG_INFO_sRGB)
808 #endif
811 png_warning(png_ptr, "Duplicate cHRM chunk");
812 png_crc_finish(png_ptr, length);
813 return;
816 if (length != 32)
818 png_warning(png_ptr, "Incorrect cHRM chunk length");
819 png_crc_finish(png_ptr, length);
820 return;
823 png_crc_read(png_ptr, buf, 32);
824 if (png_crc_finish(png_ptr, 0))
825 return;
827 uint_x = png_get_uint_32(buf);
828 uint_y = png_get_uint_32(buf + 4);
829 int_x_white = (png_fixed_point)uint_x;
830 int_y_white = (png_fixed_point)uint_y;
832 uint_x = png_get_uint_32(buf + 8);
833 uint_y = png_get_uint_32(buf + 12);
834 int_x_red = (png_fixed_point)uint_x;
835 int_y_red = (png_fixed_point)uint_y;
837 uint_x = png_get_uint_32(buf + 16);
838 uint_y = png_get_uint_32(buf + 20);
839 int_x_green = (png_fixed_point)uint_x;
840 int_y_green = (png_fixed_point)uint_y;
842 uint_x = png_get_uint_32(buf + 24);
843 uint_y = png_get_uint_32(buf + 28);
844 int_x_blue = (png_fixed_point)uint_x;
845 int_y_blue = (png_fixed_point)uint_y;
847 #ifdef PNG_FLOATING_POINT_SUPPORTED
848 white_x = (float)int_x_white / (float)100000.0;
849 white_y = (float)int_y_white / (float)100000.0;
850 red_x = (float)int_x_red / (float)100000.0;
851 red_y = (float)int_y_red / (float)100000.0;
852 green_x = (float)int_x_green / (float)100000.0;
853 green_y = (float)int_y_green / (float)100000.0;
854 blue_x = (float)int_x_blue / (float)100000.0;
855 blue_y = (float)int_y_blue / (float)100000.0;
856 #endif
858 #if defined(PNG_READ_sRGB_SUPPORTED)
859 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
861 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
862 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
863 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
864 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
865 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
866 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
867 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
868 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
870 png_warning(png_ptr,
871 "Ignoring incorrect cHRM value when sRGB is also present");
872 #ifndef PNG_NO_CONSOLE_IO
873 #ifdef PNG_FLOATING_POINT_SUPPORTED
874 fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
875 white_x, white_y, red_x, red_y);
876 fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
877 green_x, green_y, blue_x, blue_y);
878 #else
879 fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
880 int_x_white, int_y_white, int_x_red, int_y_red);
881 fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
882 int_x_green, int_y_green, int_x_blue, int_y_blue);
883 #endif
884 #endif /* PNG_NO_CONSOLE_IO */
886 return;
888 #endif /* PNG_READ_sRGB_SUPPORTED */
890 #ifdef PNG_FLOATING_POINT_SUPPORTED
891 png_set_cHRM(png_ptr, info_ptr,
892 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
893 #endif
894 #ifdef PNG_FIXED_POINT_SUPPORTED
895 png_set_cHRM_fixed(png_ptr, info_ptr,
896 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
897 int_y_green, int_x_blue, int_y_blue);
898 #endif
900 #endif
902 #if defined(PNG_READ_sRGB_SUPPORTED)
903 void /* PRIVATE */
904 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
906 int intent;
907 png_byte buf[1];
909 png_debug(1, "in png_handle_sRGB");
911 if (!(png_ptr->mode & PNG_HAVE_IHDR))
912 png_error(png_ptr, "Missing IHDR before sRGB");
913 else if (png_ptr->mode & PNG_HAVE_IDAT)
915 png_warning(png_ptr, "Invalid sRGB after IDAT");
916 png_crc_finish(png_ptr, length);
917 return;
919 else if (png_ptr->mode & PNG_HAVE_PLTE)
920 /* Should be an error, but we can cope with it */
921 png_warning(png_ptr, "Out of place sRGB chunk");
923 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
925 png_warning(png_ptr, "Duplicate sRGB chunk");
926 png_crc_finish(png_ptr, length);
927 return;
930 if (length != 1)
932 png_warning(png_ptr, "Incorrect sRGB chunk length");
933 png_crc_finish(png_ptr, length);
934 return;
937 png_crc_read(png_ptr, buf, 1);
938 if (png_crc_finish(png_ptr, 0))
939 return;
941 intent = buf[0];
942 /* Check for bad intent */
943 if (intent >= PNG_sRGB_INTENT_LAST)
945 png_warning(png_ptr, "Unknown sRGB intent");
946 return;
949 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
950 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
952 png_fixed_point igamma;
953 #ifdef PNG_FIXED_POINT_SUPPORTED
954 igamma=info_ptr->int_gamma;
955 #else
956 # ifdef PNG_FLOATING_POINT_SUPPORTED
957 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
958 # endif
959 #endif
960 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
962 png_warning(png_ptr,
963 "Ignoring incorrect gAMA value when sRGB is also present");
964 #ifndef PNG_NO_CONSOLE_IO
965 # ifdef PNG_FIXED_POINT_SUPPORTED
966 fprintf(stderr, "incorrect gamma=(%d/100000)\n",
967 (int)png_ptr->int_gamma);
968 # else
969 # ifdef PNG_FLOATING_POINT_SUPPORTED
970 fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
971 # endif
972 # endif
973 #endif
976 #endif /* PNG_READ_gAMA_SUPPORTED */
978 #ifdef PNG_READ_cHRM_SUPPORTED
979 #ifdef PNG_FIXED_POINT_SUPPORTED
980 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
981 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
982 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
983 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
984 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
985 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
986 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
987 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
988 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
990 png_warning(png_ptr,
991 "Ignoring incorrect cHRM value when sRGB is also present");
993 #endif /* PNG_FIXED_POINT_SUPPORTED */
994 #endif /* PNG_READ_cHRM_SUPPORTED */
996 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
998 #endif /* PNG_READ_sRGB_SUPPORTED */
1000 #if defined(PNG_READ_iCCP_SUPPORTED)
1001 void /* PRIVATE */
1002 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1003 /* Note: this does not properly handle chunks that are > 64K under DOS */
1005 png_byte compression_type;
1006 png_bytep pC;
1007 png_charp profile;
1008 png_uint_32 skip = 0;
1009 png_uint_32 profile_size, profile_length;
1010 png_size_t slength, prefix_length, data_length;
1012 png_debug(1, "in png_handle_iCCP");
1014 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1015 png_error(png_ptr, "Missing IHDR before iCCP");
1016 else if (png_ptr->mode & PNG_HAVE_IDAT)
1018 png_warning(png_ptr, "Invalid iCCP after IDAT");
1019 png_crc_finish(png_ptr, length);
1020 return;
1022 else if (png_ptr->mode & PNG_HAVE_PLTE)
1023 /* Should be an error, but we can cope with it */
1024 png_warning(png_ptr, "Out of place iCCP chunk");
1026 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1028 png_warning(png_ptr, "Duplicate iCCP chunk");
1029 png_crc_finish(png_ptr, length);
1030 return;
1033 #ifdef PNG_MAX_MALLOC_64K
1034 if (length > (png_uint_32)65535L)
1036 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1037 skip = length - (png_uint_32)65535L;
1038 length = (png_uint_32)65535L;
1040 #endif
1042 png_free(png_ptr, png_ptr->chunkdata);
1043 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1044 slength = (png_size_t)length;
1045 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1047 if (png_crc_finish(png_ptr, skip))
1049 png_free(png_ptr, png_ptr->chunkdata);
1050 png_ptr->chunkdata = NULL;
1051 return;
1054 png_ptr->chunkdata[slength] = 0x00;
1056 for (profile = png_ptr->chunkdata; *profile; profile++)
1057 /* Empty loop to find end of name */ ;
1059 ++profile;
1061 /* There should be at least one zero (the compression type byte)
1062 * following the separator, and we should be on it
1064 if ( profile >= png_ptr->chunkdata + slength - 1)
1066 png_free(png_ptr, png_ptr->chunkdata);
1067 png_ptr->chunkdata = NULL;
1068 png_warning(png_ptr, "Malformed iCCP chunk");
1069 return;
1072 /* Compression_type should always be zero */
1073 compression_type = *profile++;
1074 if (compression_type)
1076 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1077 compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1078 wrote nonzero) */
1081 prefix_length = profile - png_ptr->chunkdata;
1082 png_decompress_chunk(png_ptr, compression_type,
1083 slength, prefix_length, &data_length);
1085 profile_length = data_length - prefix_length;
1087 if ( prefix_length > data_length || profile_length < 4)
1089 png_free(png_ptr, png_ptr->chunkdata);
1090 png_ptr->chunkdata = NULL;
1091 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1092 return;
1095 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1096 pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
1097 profile_size = ((*(pC ))<<24) |
1098 ((*(pC + 1))<<16) |
1099 ((*(pC + 2))<< 8) |
1100 ((*(pC + 3)) );
1102 if (profile_size < profile_length)
1103 profile_length = profile_size;
1105 if (profile_size > profile_length)
1107 png_free(png_ptr, png_ptr->chunkdata);
1108 png_ptr->chunkdata = NULL;
1109 png_warning(png_ptr, "Ignoring truncated iCCP profile.");
1110 return;
1113 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
1114 compression_type, png_ptr->chunkdata + prefix_length, profile_length);
1115 png_free(png_ptr, png_ptr->chunkdata);
1116 png_ptr->chunkdata = NULL;
1118 #endif /* PNG_READ_iCCP_SUPPORTED */
1120 #if defined(PNG_READ_sPLT_SUPPORTED)
1121 void /* PRIVATE */
1122 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1123 /* Note: this does not properly handle chunks that are > 64K under DOS */
1125 png_bytep entry_start;
1126 png_sPLT_t new_palette;
1127 #ifdef PNG_NO_POINTER_INDEXING
1128 png_sPLT_entryp pp;
1129 #endif
1130 int data_length, entry_size, i;
1131 png_uint_32 skip = 0;
1132 png_size_t slength;
1134 png_debug(1, "in png_handle_sPLT");
1137 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1138 png_error(png_ptr, "Missing IHDR before sPLT");
1139 else if (png_ptr->mode & PNG_HAVE_IDAT)
1141 png_warning(png_ptr, "Invalid sPLT after IDAT");
1142 png_crc_finish(png_ptr, length);
1143 return;
1146 #ifdef PNG_MAX_MALLOC_64K
1147 if (length > (png_uint_32)65535L)
1149 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1150 skip = length - (png_uint_32)65535L;
1151 length = (png_uint_32)65535L;
1153 #endif
1155 png_free(png_ptr, png_ptr->chunkdata);
1156 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1157 slength = (png_size_t)length;
1158 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1160 if (png_crc_finish(png_ptr, skip))
1162 png_free(png_ptr, png_ptr->chunkdata);
1163 png_ptr->chunkdata = NULL;
1164 return;
1167 png_ptr->chunkdata[slength] = 0x00;
1169 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; entry_start++)
1170 /* Empty loop to find end of name */ ;
1171 ++entry_start;
1173 /* A sample depth should follow the separator, and we should be on it */
1174 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
1176 png_free(png_ptr, png_ptr->chunkdata);
1177 png_ptr->chunkdata = NULL;
1178 png_warning(png_ptr, "malformed sPLT chunk");
1179 return;
1182 new_palette.depth = *entry_start++;
1183 entry_size = (new_palette.depth == 8 ? 6 : 10);
1184 data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
1186 /* Integrity-check the data length */
1187 if (data_length % entry_size)
1189 png_free(png_ptr, png_ptr->chunkdata);
1190 png_ptr->chunkdata = NULL;
1191 png_warning(png_ptr, "sPLT chunk has bad length");
1192 return;
1195 new_palette.nentries = (png_int_32) ( data_length / entry_size);
1196 if ((png_uint_32) new_palette.nentries >
1197 (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
1199 png_warning(png_ptr, "sPLT chunk too long");
1200 return;
1202 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1203 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1204 if (new_palette.entries == NULL)
1206 png_warning(png_ptr, "sPLT chunk requires too much memory");
1207 return;
1210 #ifndef PNG_NO_POINTER_INDEXING
1211 for (i = 0; i < new_palette.nentries; i++)
1213 png_sPLT_entryp pp = new_palette.entries + i;
1215 if (new_palette.depth == 8)
1217 pp->red = *entry_start++;
1218 pp->green = *entry_start++;
1219 pp->blue = *entry_start++;
1220 pp->alpha = *entry_start++;
1222 else
1224 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1225 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1226 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1227 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1229 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1231 #else
1232 pp = new_palette.entries;
1233 for (i = 0; i < new_palette.nentries; i++)
1236 if (new_palette.depth == 8)
1238 pp[i].red = *entry_start++;
1239 pp[i].green = *entry_start++;
1240 pp[i].blue = *entry_start++;
1241 pp[i].alpha = *entry_start++;
1243 else
1245 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1246 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1247 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1248 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1250 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1252 #endif
1254 /* Discard all chunk data except the name and stash that */
1255 new_palette.name = png_ptr->chunkdata;
1257 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1259 png_free(png_ptr, png_ptr->chunkdata);
1260 png_ptr->chunkdata = NULL;
1261 png_free(png_ptr, new_palette.entries);
1263 #endif /* PNG_READ_sPLT_SUPPORTED */
1265 #if defined(PNG_READ_tRNS_SUPPORTED)
1266 void /* PRIVATE */
1267 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1269 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1271 png_debug(1, "in png_handle_tRNS");
1273 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1274 png_error(png_ptr, "Missing IHDR before tRNS");
1275 else if (png_ptr->mode & PNG_HAVE_IDAT)
1277 png_warning(png_ptr, "Invalid tRNS after IDAT");
1278 png_crc_finish(png_ptr, length);
1279 return;
1281 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1283 png_warning(png_ptr, "Duplicate tRNS chunk");
1284 png_crc_finish(png_ptr, length);
1285 return;
1288 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1290 png_byte buf[2];
1292 if (length != 2)
1294 png_warning(png_ptr, "Incorrect tRNS chunk length");
1295 png_crc_finish(png_ptr, length);
1296 return;
1299 png_crc_read(png_ptr, buf, 2);
1300 png_ptr->num_trans = 1;
1301 png_ptr->trans_values.gray = png_get_uint_16(buf);
1303 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1305 png_byte buf[6];
1307 if (length != 6)
1309 png_warning(png_ptr, "Incorrect tRNS chunk length");
1310 png_crc_finish(png_ptr, length);
1311 return;
1313 png_crc_read(png_ptr, buf, (png_size_t)length);
1314 png_ptr->num_trans = 1;
1315 png_ptr->trans_values.red = png_get_uint_16(buf);
1316 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1317 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1319 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1321 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1323 /* Should be an error, but we can cope with it. */
1324 png_warning(png_ptr, "Missing PLTE before tRNS");
1326 if (length > (png_uint_32)png_ptr->num_palette ||
1327 length > PNG_MAX_PALETTE_LENGTH)
1329 png_warning(png_ptr, "Incorrect tRNS chunk length");
1330 png_crc_finish(png_ptr, length);
1331 return;
1333 if (length == 0)
1335 png_warning(png_ptr, "Zero length tRNS chunk");
1336 png_crc_finish(png_ptr, length);
1337 return;
1339 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1340 png_ptr->num_trans = (png_uint_16)length;
1342 else
1344 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1345 png_crc_finish(png_ptr, length);
1346 return;
1349 if (png_crc_finish(png_ptr, 0))
1351 png_ptr->num_trans = 0;
1352 return;
1355 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1356 &(png_ptr->trans_values));
1358 #endif
1360 #if defined(PNG_READ_bKGD_SUPPORTED)
1361 void /* PRIVATE */
1362 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1364 png_size_t truelen;
1365 png_byte buf[6];
1367 png_debug(1, "in png_handle_bKGD");
1369 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1370 png_error(png_ptr, "Missing IHDR before bKGD");
1371 else if (png_ptr->mode & PNG_HAVE_IDAT)
1373 png_warning(png_ptr, "Invalid bKGD after IDAT");
1374 png_crc_finish(png_ptr, length);
1375 return;
1377 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1378 !(png_ptr->mode & PNG_HAVE_PLTE))
1380 png_warning(png_ptr, "Missing PLTE before bKGD");
1381 png_crc_finish(png_ptr, length);
1382 return;
1384 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1386 png_warning(png_ptr, "Duplicate bKGD chunk");
1387 png_crc_finish(png_ptr, length);
1388 return;
1391 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1392 truelen = 1;
1393 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1394 truelen = 6;
1395 else
1396 truelen = 2;
1398 if (length != truelen)
1400 png_warning(png_ptr, "Incorrect bKGD chunk length");
1401 png_crc_finish(png_ptr, length);
1402 return;
1405 png_crc_read(png_ptr, buf, truelen);
1406 if (png_crc_finish(png_ptr, 0))
1407 return;
1409 /* We convert the index value into RGB components so that we can allow
1410 * arbitrary RGB values for background when we have transparency, and
1411 * so it is easy to determine the RGB values of the background color
1412 * from the info_ptr struct. */
1413 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1415 png_ptr->background.index = buf[0];
1416 if (info_ptr && info_ptr->num_palette)
1418 if (buf[0] >= info_ptr->num_palette)
1420 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1421 return;
1423 png_ptr->background.red =
1424 (png_uint_16)png_ptr->palette[buf[0]].red;
1425 png_ptr->background.green =
1426 (png_uint_16)png_ptr->palette[buf[0]].green;
1427 png_ptr->background.blue =
1428 (png_uint_16)png_ptr->palette[buf[0]].blue;
1431 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1433 png_ptr->background.red =
1434 png_ptr->background.green =
1435 png_ptr->background.blue =
1436 png_ptr->background.gray = png_get_uint_16(buf);
1438 else
1440 png_ptr->background.red = png_get_uint_16(buf);
1441 png_ptr->background.green = png_get_uint_16(buf + 2);
1442 png_ptr->background.blue = png_get_uint_16(buf + 4);
1445 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1447 #endif
1449 #if defined(PNG_READ_hIST_SUPPORTED)
1450 void /* PRIVATE */
1451 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1453 unsigned int num, i;
1454 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1456 png_debug(1, "in png_handle_hIST");
1458 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1459 png_error(png_ptr, "Missing IHDR before hIST");
1460 else if (png_ptr->mode & PNG_HAVE_IDAT)
1462 png_warning(png_ptr, "Invalid hIST after IDAT");
1463 png_crc_finish(png_ptr, length);
1464 return;
1466 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1468 png_warning(png_ptr, "Missing PLTE before hIST");
1469 png_crc_finish(png_ptr, length);
1470 return;
1472 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1474 png_warning(png_ptr, "Duplicate hIST chunk");
1475 png_crc_finish(png_ptr, length);
1476 return;
1479 num = length / 2 ;
1480 if (num != (unsigned int) png_ptr->num_palette || num >
1481 (unsigned int) PNG_MAX_PALETTE_LENGTH)
1483 png_warning(png_ptr, "Incorrect hIST chunk length");
1484 png_crc_finish(png_ptr, length);
1485 return;
1488 for (i = 0; i < num; i++)
1490 png_byte buf[2];
1492 png_crc_read(png_ptr, buf, 2);
1493 readbuf[i] = png_get_uint_16(buf);
1496 if (png_crc_finish(png_ptr, 0))
1497 return;
1499 png_set_hIST(png_ptr, info_ptr, readbuf);
1501 #endif
1503 #if defined(PNG_READ_pHYs_SUPPORTED)
1504 void /* PRIVATE */
1505 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1507 png_byte buf[9];
1508 png_uint_32 res_x, res_y;
1509 int unit_type;
1511 png_debug(1, "in png_handle_pHYs");
1513 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1514 png_error(png_ptr, "Missing IHDR before pHYs");
1515 else if (png_ptr->mode & PNG_HAVE_IDAT)
1517 png_warning(png_ptr, "Invalid pHYs after IDAT");
1518 png_crc_finish(png_ptr, length);
1519 return;
1521 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1523 png_warning(png_ptr, "Duplicate pHYs chunk");
1524 png_crc_finish(png_ptr, length);
1525 return;
1528 if (length != 9)
1530 png_warning(png_ptr, "Incorrect pHYs chunk length");
1531 png_crc_finish(png_ptr, length);
1532 return;
1535 png_crc_read(png_ptr, buf, 9);
1536 if (png_crc_finish(png_ptr, 0))
1537 return;
1539 res_x = png_get_uint_32(buf);
1540 res_y = png_get_uint_32(buf + 4);
1541 unit_type = buf[8];
1542 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1544 #endif
1546 #if defined(PNG_READ_oFFs_SUPPORTED)
1547 void /* PRIVATE */
1548 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1550 png_byte buf[9];
1551 png_int_32 offset_x, offset_y;
1552 int unit_type;
1554 png_debug(1, "in png_handle_oFFs");
1556 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1557 png_error(png_ptr, "Missing IHDR before oFFs");
1558 else if (png_ptr->mode & PNG_HAVE_IDAT)
1560 png_warning(png_ptr, "Invalid oFFs after IDAT");
1561 png_crc_finish(png_ptr, length);
1562 return;
1564 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1566 png_warning(png_ptr, "Duplicate oFFs chunk");
1567 png_crc_finish(png_ptr, length);
1568 return;
1571 if (length != 9)
1573 png_warning(png_ptr, "Incorrect oFFs chunk length");
1574 png_crc_finish(png_ptr, length);
1575 return;
1578 png_crc_read(png_ptr, buf, 9);
1579 if (png_crc_finish(png_ptr, 0))
1580 return;
1582 offset_x = png_get_int_32(buf);
1583 offset_y = png_get_int_32(buf + 4);
1584 unit_type = buf[8];
1585 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1587 #endif
1589 #if defined(PNG_READ_pCAL_SUPPORTED)
1590 /* Read the pCAL chunk (described in the PNG Extensions document) */
1591 void /* PRIVATE */
1592 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1594 png_int_32 X0, X1;
1595 png_byte type, nparams;
1596 png_charp buf, units, endptr;
1597 png_charpp params;
1598 png_size_t slength;
1599 int i;
1601 png_debug(1, "in png_handle_pCAL");
1603 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1604 png_error(png_ptr, "Missing IHDR before pCAL");
1605 else if (png_ptr->mode & PNG_HAVE_IDAT)
1607 png_warning(png_ptr, "Invalid pCAL after IDAT");
1608 png_crc_finish(png_ptr, length);
1609 return;
1611 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1613 png_warning(png_ptr, "Duplicate pCAL chunk");
1614 png_crc_finish(png_ptr, length);
1615 return;
1618 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
1619 length + 1);
1620 png_free(png_ptr, png_ptr->chunkdata);
1621 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1622 if (png_ptr->chunkdata == NULL)
1624 png_warning(png_ptr, "No memory for pCAL purpose.");
1625 return;
1627 slength = (png_size_t)length;
1628 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1630 if (png_crc_finish(png_ptr, 0))
1632 png_free(png_ptr, png_ptr->chunkdata);
1633 png_ptr->chunkdata = NULL;
1634 return;
1637 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
1639 png_debug(3, "Finding end of pCAL purpose string");
1640 for (buf = png_ptr->chunkdata; *buf; buf++)
1641 /* Empty loop */ ;
1643 endptr = png_ptr->chunkdata + slength;
1645 /* We need to have at least 12 bytes after the purpose string
1646 in order to get the parameter information. */
1647 if (endptr <= buf + 12)
1649 png_warning(png_ptr, "Invalid pCAL data");
1650 png_free(png_ptr, png_ptr->chunkdata);
1651 png_ptr->chunkdata = NULL;
1652 return;
1655 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
1656 X0 = png_get_int_32((png_bytep)buf+1);
1657 X1 = png_get_int_32((png_bytep)buf+5);
1658 type = buf[9];
1659 nparams = buf[10];
1660 units = buf + 11;
1662 png_debug(3, "Checking pCAL equation type and number of parameters");
1663 /* Check that we have the right number of parameters for known
1664 equation types. */
1665 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1666 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1667 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1668 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1670 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1671 png_free(png_ptr, png_ptr->chunkdata);
1672 png_ptr->chunkdata = NULL;
1673 return;
1675 else if (type >= PNG_EQUATION_LAST)
1677 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1680 for (buf = units; *buf; buf++)
1681 /* Empty loop to move past the units string. */ ;
1683 png_debug(3, "Allocating pCAL parameters array");
1684 params = (png_charpp)png_malloc_warn(png_ptr,
1685 (png_uint_32)(nparams * png_sizeof(png_charp))) ;
1686 if (params == NULL)
1688 png_free(png_ptr, png_ptr->chunkdata);
1689 png_ptr->chunkdata = NULL;
1690 png_warning(png_ptr, "No memory for pCAL params.");
1691 return;
1694 /* Get pointers to the start of each parameter string. */
1695 for (i = 0; i < (int)nparams; i++)
1697 buf++; /* Skip the null string terminator from previous parameter. */
1699 png_debug1(3, "Reading pCAL parameter %d", i);
1700 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
1701 /* Empty loop to move past each parameter string */ ;
1703 /* Make sure we haven't run out of data yet */
1704 if (buf > endptr)
1706 png_warning(png_ptr, "Invalid pCAL data");
1707 png_free(png_ptr, png_ptr->chunkdata);
1708 png_ptr->chunkdata = NULL;
1709 png_free(png_ptr, params);
1710 return;
1714 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
1715 units, params);
1717 png_free(png_ptr, png_ptr->chunkdata);
1718 png_ptr->chunkdata = NULL;
1719 png_free(png_ptr, params);
1721 #endif
1723 #if defined(PNG_READ_sCAL_SUPPORTED)
1724 /* Read the sCAL chunk */
1725 void /* PRIVATE */
1726 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1728 png_charp ep;
1729 #ifdef PNG_FLOATING_POINT_SUPPORTED
1730 double width, height;
1731 png_charp vp;
1732 #else
1733 #ifdef PNG_FIXED_POINT_SUPPORTED
1734 png_charp swidth, sheight;
1735 #endif
1736 #endif
1737 png_size_t slength;
1739 png_debug(1, "in png_handle_sCAL");
1741 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1742 png_error(png_ptr, "Missing IHDR before sCAL");
1743 else if (png_ptr->mode & PNG_HAVE_IDAT)
1745 png_warning(png_ptr, "Invalid sCAL after IDAT");
1746 png_crc_finish(png_ptr, length);
1747 return;
1749 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1751 png_warning(png_ptr, "Duplicate sCAL chunk");
1752 png_crc_finish(png_ptr, length);
1753 return;
1756 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
1757 length + 1);
1758 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1759 if (png_ptr->chunkdata == NULL)
1761 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
1762 return;
1764 slength = (png_size_t)length;
1765 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1767 if (png_crc_finish(png_ptr, 0))
1769 png_free(png_ptr, png_ptr->chunkdata);
1770 png_ptr->chunkdata = NULL;
1771 return;
1774 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
1776 ep = png_ptr->chunkdata + 1; /* Skip unit byte */
1778 #ifdef PNG_FLOATING_POINT_SUPPORTED
1779 width = png_strtod(png_ptr, ep, &vp);
1780 if (*vp)
1782 png_warning(png_ptr, "malformed width string in sCAL chunk");
1783 return;
1785 #else
1786 #ifdef PNG_FIXED_POINT_SUPPORTED
1787 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1788 if (swidth == NULL)
1790 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
1791 return;
1793 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1794 #endif
1795 #endif
1797 for (ep = png_ptr->chunkdata; *ep; ep++)
1798 /* Empty loop */ ;
1799 ep++;
1801 if (png_ptr->chunkdata + slength < ep)
1803 png_warning(png_ptr, "Truncated sCAL chunk");
1804 #if defined(PNG_FIXED_POINT_SUPPORTED) && \
1805 !defined(PNG_FLOATING_POINT_SUPPORTED)
1806 png_free(png_ptr, swidth);
1807 #endif
1808 png_free(png_ptr, png_ptr->chunkdata);
1809 png_ptr->chunkdata = NULL;
1810 return;
1813 #ifdef PNG_FLOATING_POINT_SUPPORTED
1814 height = png_strtod(png_ptr, ep, &vp);
1815 if (*vp)
1817 png_warning(png_ptr, "malformed height string in sCAL chunk");
1818 return;
1820 #else
1821 #ifdef PNG_FIXED_POINT_SUPPORTED
1822 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1823 if (sheight == NULL)
1825 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
1826 return;
1828 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1829 #endif
1830 #endif
1832 if (png_ptr->chunkdata + slength < ep
1833 #ifdef PNG_FLOATING_POINT_SUPPORTED
1834 || width <= 0. || height <= 0.
1835 #endif
1838 png_warning(png_ptr, "Invalid sCAL data");
1839 png_free(png_ptr, png_ptr->chunkdata);
1840 png_ptr->chunkdata = NULL;
1841 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1842 png_free(png_ptr, swidth);
1843 png_free(png_ptr, sheight);
1844 #endif
1845 return;
1849 #ifdef PNG_FLOATING_POINT_SUPPORTED
1850 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
1851 #else
1852 #ifdef PNG_FIXED_POINT_SUPPORTED
1853 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
1854 #endif
1855 #endif
1857 png_free(png_ptr, png_ptr->chunkdata);
1858 png_ptr->chunkdata = NULL;
1859 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1860 png_free(png_ptr, swidth);
1861 png_free(png_ptr, sheight);
1862 #endif
1864 #endif
1866 #if defined(PNG_READ_tIME_SUPPORTED)
1867 void /* PRIVATE */
1868 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1870 png_byte buf[7];
1871 png_time mod_time;
1873 png_debug(1, "in png_handle_tIME");
1875 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1876 png_error(png_ptr, "Out of place tIME chunk");
1877 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1879 png_warning(png_ptr, "Duplicate tIME chunk");
1880 png_crc_finish(png_ptr, length);
1881 return;
1884 if (png_ptr->mode & PNG_HAVE_IDAT)
1885 png_ptr->mode |= PNG_AFTER_IDAT;
1887 if (length != 7)
1889 png_warning(png_ptr, "Incorrect tIME chunk length");
1890 png_crc_finish(png_ptr, length);
1891 return;
1894 png_crc_read(png_ptr, buf, 7);
1895 if (png_crc_finish(png_ptr, 0))
1896 return;
1898 mod_time.second = buf[6];
1899 mod_time.minute = buf[5];
1900 mod_time.hour = buf[4];
1901 mod_time.day = buf[3];
1902 mod_time.month = buf[2];
1903 mod_time.year = png_get_uint_16(buf);
1905 png_set_tIME(png_ptr, info_ptr, &mod_time);
1907 #endif
1909 #if defined(PNG_READ_tEXt_SUPPORTED)
1910 /* Note: this does not properly handle chunks that are > 64K under DOS */
1911 void /* PRIVATE */
1912 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1914 png_textp text_ptr;
1915 png_charp key;
1916 png_charp text;
1917 png_uint_32 skip = 0;
1918 png_size_t slength;
1919 int ret;
1921 png_debug(1, "in png_handle_tEXt");
1924 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1925 png_error(png_ptr, "Missing IHDR before tEXt");
1927 if (png_ptr->mode & PNG_HAVE_IDAT)
1928 png_ptr->mode |= PNG_AFTER_IDAT;
1930 #ifdef PNG_MAX_MALLOC_64K
1931 if (length > (png_uint_32)65535L)
1933 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1934 skip = length - (png_uint_32)65535L;
1935 length = (png_uint_32)65535L;
1937 #endif
1939 png_free(png_ptr, png_ptr->chunkdata);
1941 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1942 if (png_ptr->chunkdata == NULL)
1944 png_warning(png_ptr, "No memory to process text chunk.");
1945 return;
1947 slength = (png_size_t)length;
1948 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1950 if (png_crc_finish(png_ptr, skip))
1952 png_free(png_ptr, png_ptr->chunkdata);
1953 png_ptr->chunkdata = NULL;
1954 return;
1957 key = png_ptr->chunkdata;
1959 key[slength] = 0x00;
1961 for (text = key; *text; text++)
1962 /* Empty loop to find end of key */ ;
1964 if (text != key + slength)
1965 text++;
1967 text_ptr = (png_textp)png_malloc_warn(png_ptr,
1968 (png_uint_32)png_sizeof(png_text));
1969 if (text_ptr == NULL)
1971 png_warning(png_ptr, "Not enough memory to process text chunk.");
1972 png_free(png_ptr, png_ptr->chunkdata);
1973 png_ptr->chunkdata = NULL;
1974 return;
1976 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1977 text_ptr->key = key;
1978 #ifdef PNG_iTXt_SUPPORTED
1979 text_ptr->lang = NULL;
1980 text_ptr->lang_key = NULL;
1981 text_ptr->itxt_length = 0;
1982 #endif
1983 text_ptr->text = text;
1984 text_ptr->text_length = png_strlen(text);
1986 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
1988 png_free(png_ptr, png_ptr->chunkdata);
1989 png_ptr->chunkdata = NULL;
1990 png_free(png_ptr, text_ptr);
1991 if (ret)
1992 png_warning(png_ptr, "Insufficient memory to process text chunk.");
1994 #endif
1996 #if defined(PNG_READ_zTXt_SUPPORTED)
1997 /* Note: this does not correctly handle chunks that are > 64K under DOS */
1998 void /* PRIVATE */
1999 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2001 png_textp text_ptr;
2002 png_charp text;
2003 int comp_type;
2004 int ret;
2005 png_size_t slength, prefix_len, data_len;
2007 png_debug(1, "in png_handle_zTXt");
2010 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2011 png_error(png_ptr, "Missing IHDR before zTXt");
2013 if (png_ptr->mode & PNG_HAVE_IDAT)
2014 png_ptr->mode |= PNG_AFTER_IDAT;
2016 #ifdef PNG_MAX_MALLOC_64K
2017 /* We will no doubt have problems with chunks even half this size, but
2018 there is no hard and fast rule to tell us where to stop. */
2019 if (length > (png_uint_32)65535L)
2021 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
2022 png_crc_finish(png_ptr, length);
2023 return;
2025 #endif
2027 png_free(png_ptr, png_ptr->chunkdata);
2028 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2029 if (png_ptr->chunkdata == NULL)
2031 png_warning(png_ptr, "Out of memory processing zTXt chunk.");
2032 return;
2034 slength = (png_size_t)length;
2035 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
2036 if (png_crc_finish(png_ptr, 0))
2038 png_free(png_ptr, png_ptr->chunkdata);
2039 png_ptr->chunkdata = NULL;
2040 return;
2043 png_ptr->chunkdata[slength] = 0x00;
2045 for (text = png_ptr->chunkdata; *text; text++)
2046 /* Empty loop */ ;
2048 /* zTXt must have some text after the chunkdataword */
2049 if (text >= png_ptr->chunkdata + slength - 2)
2051 png_warning(png_ptr, "Truncated zTXt chunk");
2052 png_free(png_ptr, png_ptr->chunkdata);
2053 png_ptr->chunkdata = NULL;
2054 return;
2056 else
2058 comp_type = *(++text);
2059 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2061 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2062 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2064 text++; /* Skip the compression_method byte */
2066 prefix_len = text - png_ptr->chunkdata;
2068 png_decompress_chunk(png_ptr, comp_type,
2069 (png_size_t)length, prefix_len, &data_len);
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 zTXt chunk.");
2076 png_free(png_ptr, png_ptr->chunkdata);
2077 png_ptr->chunkdata = NULL;
2078 return;
2080 text_ptr->compression = comp_type;
2081 text_ptr->key = png_ptr->chunkdata;
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 = png_ptr->chunkdata + prefix_len;
2088 text_ptr->text_length = data_len;
2090 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2092 png_free(png_ptr, text_ptr);
2093 png_free(png_ptr, png_ptr->chunkdata);
2094 png_ptr->chunkdata = NULL;
2095 if (ret)
2096 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2098 #endif
2100 #if defined(PNG_READ_iTXt_SUPPORTED)
2101 /* Note: this does not correctly handle chunks that are > 64K under DOS */
2102 void /* PRIVATE */
2103 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2105 png_textp text_ptr;
2106 png_charp key, lang, text, lang_key;
2107 int comp_flag;
2108 int comp_type = 0;
2109 int ret;
2110 png_size_t slength, prefix_len, data_len;
2112 png_debug(1, "in png_handle_iTXt");
2115 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2116 png_error(png_ptr, "Missing IHDR before iTXt");
2118 if (png_ptr->mode & PNG_HAVE_IDAT)
2119 png_ptr->mode |= PNG_AFTER_IDAT;
2121 #ifdef PNG_MAX_MALLOC_64K
2122 /* We will no doubt have problems with chunks even half this size, but
2123 there is no hard and fast rule to tell us where to stop. */
2124 if (length > (png_uint_32)65535L)
2126 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
2127 png_crc_finish(png_ptr, length);
2128 return;
2130 #endif
2132 png_free(png_ptr, png_ptr->chunkdata);
2133 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2134 if (png_ptr->chunkdata == NULL)
2136 png_warning(png_ptr, "No memory to process iTXt chunk.");
2137 return;
2139 slength = (png_size_t)length;
2140 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
2141 if (png_crc_finish(png_ptr, 0))
2143 png_free(png_ptr, png_ptr->chunkdata);
2144 png_ptr->chunkdata = NULL;
2145 return;
2148 png_ptr->chunkdata[slength] = 0x00;
2150 for (lang = png_ptr->chunkdata; *lang; lang++)
2151 /* Empty loop */ ;
2152 lang++; /* Skip NUL separator */
2154 /* iTXt must have a language tag (possibly empty), two compression bytes,
2155 * translated keyword (possibly empty), and possibly some text after the
2156 * keyword
2159 if (lang >= png_ptr->chunkdata + slength - 3)
2161 png_warning(png_ptr, "Truncated iTXt chunk");
2162 png_free(png_ptr, png_ptr->chunkdata);
2163 png_ptr->chunkdata = NULL;
2164 return;
2166 else
2168 comp_flag = *lang++;
2169 comp_type = *lang++;
2172 for (lang_key = lang; *lang_key; lang_key++)
2173 /* Empty loop */ ;
2174 lang_key++; /* Skip NUL separator */
2176 if (lang_key >= png_ptr->chunkdata + slength)
2178 png_warning(png_ptr, "Truncated iTXt chunk");
2179 png_free(png_ptr, png_ptr->chunkdata);
2180 png_ptr->chunkdata = NULL;
2181 return;
2184 for (text = lang_key; *text; text++)
2185 /* Empty loop */ ;
2186 text++; /* Skip NUL separator */
2187 if (text >= png_ptr->chunkdata + slength)
2189 png_warning(png_ptr, "Malformed iTXt chunk");
2190 png_free(png_ptr, png_ptr->chunkdata);
2191 png_ptr->chunkdata = NULL;
2192 return;
2195 prefix_len = text - png_ptr->chunkdata;
2197 key=png_ptr->chunkdata;
2198 if (comp_flag)
2199 png_decompress_chunk(png_ptr, comp_type,
2200 (size_t)length, prefix_len, &data_len);
2201 else
2202 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
2203 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2204 (png_uint_32)png_sizeof(png_text));
2205 if (text_ptr == NULL)
2207 png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
2208 png_free(png_ptr, png_ptr->chunkdata);
2209 png_ptr->chunkdata = NULL;
2210 return;
2212 text_ptr->compression = (int)comp_flag + 1;
2213 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
2214 text_ptr->lang = png_ptr->chunkdata + (lang - key);
2215 text_ptr->itxt_length = data_len;
2216 text_ptr->text_length = 0;
2217 text_ptr->key = png_ptr->chunkdata;
2218 text_ptr->text = png_ptr->chunkdata + prefix_len;
2220 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2222 png_free(png_ptr, text_ptr);
2223 png_free(png_ptr, png_ptr->chunkdata);
2224 png_ptr->chunkdata = NULL;
2225 if (ret)
2226 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
2228 #endif
2230 /* This function is called when we haven't found a handler for a
2231 chunk. If there isn't a problem with the chunk itself (ie bad
2232 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2233 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2234 case it will be saved away to be written out later. */
2235 void /* PRIVATE */
2236 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2238 png_uint_32 skip = 0;
2240 png_debug(1, "in png_handle_unknown");
2243 if (png_ptr->mode & PNG_HAVE_IDAT)
2245 #ifdef PNG_USE_LOCAL_ARRAYS
2246 PNG_CONST PNG_IDAT;
2247 #endif
2248 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */
2249 png_ptr->mode |= PNG_AFTER_IDAT;
2252 if (!(png_ptr->chunk_name[0] & 0x20))
2254 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2255 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2256 PNG_HANDLE_CHUNK_ALWAYS
2257 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2258 && png_ptr->read_user_chunk_fn == NULL
2259 #endif
2261 #endif
2262 png_chunk_error(png_ptr, "unknown critical chunk");
2265 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2266 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
2267 (png_ptr->read_user_chunk_fn != NULL))
2269 #ifdef PNG_MAX_MALLOC_64K
2270 if (length > (png_uint_32)65535L)
2272 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2273 skip = length - (png_uint_32)65535L;
2274 length = (png_uint_32)65535L;
2276 #endif
2277 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
2278 (png_charp)png_ptr->chunk_name,
2279 png_sizeof(png_ptr->unknown_chunk.name));
2280 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0';
2281 png_ptr->unknown_chunk.size = (png_size_t)length;
2282 if (length == 0)
2283 png_ptr->unknown_chunk.data = NULL;
2284 else
2286 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2287 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2289 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2290 if (png_ptr->read_user_chunk_fn != NULL)
2292 /* Callback to user unknown chunk handler */
2293 int ret;
2294 ret = (*(png_ptr->read_user_chunk_fn))
2295 (png_ptr, &png_ptr->unknown_chunk);
2296 if (ret < 0)
2297 png_chunk_error(png_ptr, "error in user chunk");
2298 if (ret == 0)
2300 if (!(png_ptr->chunk_name[0] & 0x20))
2301 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2302 PNG_HANDLE_CHUNK_ALWAYS)
2303 png_chunk_error(png_ptr, "unknown critical chunk");
2304 png_set_unknown_chunks(png_ptr, info_ptr,
2305 &png_ptr->unknown_chunk, 1);
2308 else
2309 #endif
2310 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
2311 png_free(png_ptr, png_ptr->unknown_chunk.data);
2312 png_ptr->unknown_chunk.data = NULL;
2314 else
2315 #endif
2316 skip = length;
2318 png_crc_finish(png_ptr, skip);
2320 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2321 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
2322 #endif
2325 /* This function is called to verify that a chunk name is valid.
2326 This function can't have the "critical chunk check" incorporated
2327 into it, since in the future we will need to be able to call user
2328 functions to handle unknown critical chunks after we check that
2329 the chunk name itself is valid. */
2331 #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
2333 void /* PRIVATE */
2334 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2336 png_debug(1, "in png_check_chunk_name");
2337 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2338 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2340 png_chunk_error(png_ptr, "invalid chunk type");
2344 /* Combines the row recently read in with the existing pixels in the
2345 row. This routine takes care of alpha and transparency if requested.
2346 This routine also handles the two methods of progressive display
2347 of interlaced images, depending on the mask value.
2348 The mask value describes which pixels are to be combined with
2349 the row. The pattern always repeats every 8 pixels, so just 8
2350 bits are needed. A one indicates the pixel is to be combined,
2351 a zero indicates the pixel is to be skipped. This is in addition
2352 to any alpha or transparency value associated with the pixel. If
2353 you want all pixels to be combined, pass 0xff (255) in mask. */
2355 void /* PRIVATE */
2356 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2358 png_debug(1, "in png_combine_row");
2359 if (mask == 0xff)
2361 png_memcpy(row, png_ptr->row_buf + 1,
2362 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
2364 else
2366 switch (png_ptr->row_info.pixel_depth)
2368 case 1:
2370 png_bytep sp = png_ptr->row_buf + 1;
2371 png_bytep dp = row;
2372 int s_inc, s_start, s_end;
2373 int m = 0x80;
2374 int shift;
2375 png_uint_32 i;
2376 png_uint_32 row_width = png_ptr->width;
2378 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2379 if (png_ptr->transformations & PNG_PACKSWAP)
2381 s_start = 0;
2382 s_end = 7;
2383 s_inc = 1;
2385 else
2386 #endif
2388 s_start = 7;
2389 s_end = 0;
2390 s_inc = -1;
2393 shift = s_start;
2395 for (i = 0; i < row_width; i++)
2397 if (m & mask)
2399 int value;
2401 value = (*sp >> shift) & 0x01;
2402 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2403 *dp |= (png_byte)(value << shift);
2406 if (shift == s_end)
2408 shift = s_start;
2409 sp++;
2410 dp++;
2412 else
2413 shift += s_inc;
2415 if (m == 1)
2416 m = 0x80;
2417 else
2418 m >>= 1;
2420 break;
2422 case 2:
2424 png_bytep sp = png_ptr->row_buf + 1;
2425 png_bytep dp = row;
2426 int s_start, s_end, s_inc;
2427 int m = 0x80;
2428 int shift;
2429 png_uint_32 i;
2430 png_uint_32 row_width = png_ptr->width;
2431 int value;
2433 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2434 if (png_ptr->transformations & PNG_PACKSWAP)
2436 s_start = 0;
2437 s_end = 6;
2438 s_inc = 2;
2440 else
2441 #endif
2443 s_start = 6;
2444 s_end = 0;
2445 s_inc = -2;
2448 shift = s_start;
2450 for (i = 0; i < row_width; i++)
2452 if (m & mask)
2454 value = (*sp >> shift) & 0x03;
2455 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2456 *dp |= (png_byte)(value << shift);
2459 if (shift == s_end)
2461 shift = s_start;
2462 sp++;
2463 dp++;
2465 else
2466 shift += s_inc;
2467 if (m == 1)
2468 m = 0x80;
2469 else
2470 m >>= 1;
2472 break;
2474 case 4:
2476 png_bytep sp = png_ptr->row_buf + 1;
2477 png_bytep dp = row;
2478 int s_start, s_end, s_inc;
2479 int m = 0x80;
2480 int shift;
2481 png_uint_32 i;
2482 png_uint_32 row_width = png_ptr->width;
2483 int value;
2485 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2486 if (png_ptr->transformations & PNG_PACKSWAP)
2488 s_start = 0;
2489 s_end = 4;
2490 s_inc = 4;
2492 else
2493 #endif
2495 s_start = 4;
2496 s_end = 0;
2497 s_inc = -4;
2499 shift = s_start;
2501 for (i = 0; i < row_width; i++)
2503 if (m & mask)
2505 value = (*sp >> shift) & 0xf;
2506 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2507 *dp |= (png_byte)(value << shift);
2510 if (shift == s_end)
2512 shift = s_start;
2513 sp++;
2514 dp++;
2516 else
2517 shift += s_inc;
2518 if (m == 1)
2519 m = 0x80;
2520 else
2521 m >>= 1;
2523 break;
2525 default:
2527 png_bytep sp = png_ptr->row_buf + 1;
2528 png_bytep dp = row;
2529 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2530 png_uint_32 i;
2531 png_uint_32 row_width = png_ptr->width;
2532 png_byte m = 0x80;
2535 for (i = 0; i < row_width; i++)
2537 if (m & mask)
2539 png_memcpy(dp, sp, pixel_bytes);
2542 sp += pixel_bytes;
2543 dp += pixel_bytes;
2545 if (m == 1)
2546 m = 0x80;
2547 else
2548 m >>= 1;
2550 break;
2556 #ifdef PNG_READ_INTERLACING_SUPPORTED
2557 /* OLD pre-1.0.9 interface:
2558 void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2559 png_uint_32 transformations)
2561 void /* PRIVATE */
2562 png_do_read_interlace(png_structp png_ptr)
2564 png_row_infop row_info = &(png_ptr->row_info);
2565 png_bytep row = png_ptr->row_buf + 1;
2566 int pass = png_ptr->pass;
2567 png_uint_32 transformations = png_ptr->transformations;
2568 #ifdef PNG_USE_LOCAL_ARRAYS
2569 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2570 /* Offset to next interlace block */
2571 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2572 #endif
2574 png_debug(1, "in png_do_read_interlace");
2575 if (row != NULL && row_info != NULL)
2577 png_uint_32 final_width;
2579 final_width = row_info->width * png_pass_inc[pass];
2581 switch (row_info->pixel_depth)
2583 case 1:
2585 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2586 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2587 int sshift, dshift;
2588 int s_start, s_end, s_inc;
2589 int jstop = png_pass_inc[pass];
2590 png_byte v;
2591 png_uint_32 i;
2592 int j;
2594 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2595 if (transformations & PNG_PACKSWAP)
2597 sshift = (int)((row_info->width + 7) & 0x07);
2598 dshift = (int)((final_width + 7) & 0x07);
2599 s_start = 7;
2600 s_end = 0;
2601 s_inc = -1;
2603 else
2604 #endif
2606 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2607 dshift = 7 - (int)((final_width + 7) & 0x07);
2608 s_start = 0;
2609 s_end = 7;
2610 s_inc = 1;
2613 for (i = 0; i < row_info->width; i++)
2615 v = (png_byte)((*sp >> sshift) & 0x01);
2616 for (j = 0; j < jstop; j++)
2618 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2619 *dp |= (png_byte)(v << dshift);
2620 if (dshift == s_end)
2622 dshift = s_start;
2623 dp--;
2625 else
2626 dshift += s_inc;
2628 if (sshift == s_end)
2630 sshift = s_start;
2631 sp--;
2633 else
2634 sshift += s_inc;
2636 break;
2638 case 2:
2640 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2641 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2642 int sshift, dshift;
2643 int s_start, s_end, s_inc;
2644 int jstop = png_pass_inc[pass];
2645 png_uint_32 i;
2647 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2648 if (transformations & PNG_PACKSWAP)
2650 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2651 dshift = (int)(((final_width + 3) & 0x03) << 1);
2652 s_start = 6;
2653 s_end = 0;
2654 s_inc = -2;
2656 else
2657 #endif
2659 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2660 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2661 s_start = 0;
2662 s_end = 6;
2663 s_inc = 2;
2666 for (i = 0; i < row_info->width; i++)
2668 png_byte v;
2669 int j;
2671 v = (png_byte)((*sp >> sshift) & 0x03);
2672 for (j = 0; j < jstop; j++)
2674 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2675 *dp |= (png_byte)(v << dshift);
2676 if (dshift == s_end)
2678 dshift = s_start;
2679 dp--;
2681 else
2682 dshift += s_inc;
2684 if (sshift == s_end)
2686 sshift = s_start;
2687 sp--;
2689 else
2690 sshift += s_inc;
2692 break;
2694 case 4:
2696 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2697 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2698 int sshift, dshift;
2699 int s_start, s_end, s_inc;
2700 png_uint_32 i;
2701 int jstop = png_pass_inc[pass];
2703 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2704 if (transformations & PNG_PACKSWAP)
2706 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2707 dshift = (int)(((final_width + 1) & 0x01) << 2);
2708 s_start = 4;
2709 s_end = 0;
2710 s_inc = -4;
2712 else
2713 #endif
2715 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2716 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2717 s_start = 0;
2718 s_end = 4;
2719 s_inc = 4;
2722 for (i = 0; i < row_info->width; i++)
2724 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2725 int j;
2727 for (j = 0; j < jstop; j++)
2729 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2730 *dp |= (png_byte)(v << dshift);
2731 if (dshift == s_end)
2733 dshift = s_start;
2734 dp--;
2736 else
2737 dshift += s_inc;
2739 if (sshift == s_end)
2741 sshift = s_start;
2742 sp--;
2744 else
2745 sshift += s_inc;
2747 break;
2749 default:
2751 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2752 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2753 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2755 int jstop = png_pass_inc[pass];
2756 png_uint_32 i;
2758 for (i = 0; i < row_info->width; i++)
2760 png_byte v[8];
2761 int j;
2763 png_memcpy(v, sp, pixel_bytes);
2764 for (j = 0; j < jstop; j++)
2766 png_memcpy(dp, v, pixel_bytes);
2767 dp -= pixel_bytes;
2769 sp -= pixel_bytes;
2771 break;
2774 row_info->width = final_width;
2775 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
2777 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2778 transformations = transformations; /* Silence compiler warning */
2779 #endif
2781 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2783 void /* PRIVATE */
2784 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2785 png_bytep prev_row, int filter)
2787 png_debug(1, "in png_read_filter_row");
2788 png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
2789 switch (filter)
2791 case PNG_FILTER_VALUE_NONE:
2792 break;
2793 case PNG_FILTER_VALUE_SUB:
2795 png_uint_32 i;
2796 png_uint_32 istop = row_info->rowbytes;
2797 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2798 png_bytep rp = row + bpp;
2799 png_bytep lp = row;
2801 for (i = bpp; i < istop; i++)
2803 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2804 rp++;
2806 break;
2808 case PNG_FILTER_VALUE_UP:
2810 png_uint_32 i;
2811 png_uint_32 istop = row_info->rowbytes;
2812 png_bytep rp = row;
2813 png_bytep pp = prev_row;
2815 for (i = 0; i < istop; i++)
2817 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2818 rp++;
2820 break;
2822 case PNG_FILTER_VALUE_AVG:
2824 png_uint_32 i;
2825 png_bytep rp = row;
2826 png_bytep pp = prev_row;
2827 png_bytep lp = row;
2828 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2829 png_uint_32 istop = row_info->rowbytes - bpp;
2831 for (i = 0; i < bpp; i++)
2833 *rp = (png_byte)(((int)(*rp) +
2834 ((int)(*pp++) / 2 )) & 0xff);
2835 rp++;
2838 for (i = 0; i < istop; i++)
2840 *rp = (png_byte)(((int)(*rp) +
2841 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2842 rp++;
2844 break;
2846 case PNG_FILTER_VALUE_PAETH:
2848 png_uint_32 i;
2849 png_bytep rp = row;
2850 png_bytep pp = prev_row;
2851 png_bytep lp = row;
2852 png_bytep cp = prev_row;
2853 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2854 png_uint_32 istop=row_info->rowbytes - bpp;
2856 for (i = 0; i < bpp; i++)
2858 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2859 rp++;
2862 for (i = 0; i < istop; i++) /* Use leftover rp,pp */
2864 int a, b, c, pa, pb, pc, p;
2866 a = *lp++;
2867 b = *pp++;
2868 c = *cp++;
2870 p = b - c;
2871 pc = a - c;
2873 #ifdef PNG_USE_ABS
2874 pa = abs(p);
2875 pb = abs(pc);
2876 pc = abs(p + pc);
2877 #else
2878 pa = p < 0 ? -p : p;
2879 pb = pc < 0 ? -pc : pc;
2880 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2881 #endif
2884 if (pa <= pb && pa <= pc)
2885 p = a;
2886 else if (pb <= pc)
2887 p = b;
2888 else
2889 p = c;
2892 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
2894 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2895 rp++;
2897 break;
2899 default:
2900 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2901 *row = 0;
2902 break;
2906 #ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
2907 void /* PRIVATE */
2908 png_read_finish_row(png_structp png_ptr)
2910 #ifdef PNG_USE_LOCAL_ARRAYS
2911 #ifdef PNG_READ_INTERLACING_SUPPORTED
2912 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2914 /* Start of interlace block */
2915 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2917 /* Offset to next interlace block */
2918 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2920 /* Start of interlace block in the y direction */
2921 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2923 /* Offset to next interlace block in the y direction */
2924 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2925 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2926 #endif
2928 png_debug(1, "in png_read_finish_row");
2929 png_ptr->row_number++;
2930 if (png_ptr->row_number < png_ptr->num_rows)
2931 return;
2933 #ifdef PNG_READ_INTERLACING_SUPPORTED
2934 if (png_ptr->interlaced)
2936 png_ptr->row_number = 0;
2937 png_memset_check(png_ptr, png_ptr->prev_row, 0,
2938 png_ptr->rowbytes + 1);
2941 png_ptr->pass++;
2942 if (png_ptr->pass >= 7)
2943 break;
2944 png_ptr->iwidth = (png_ptr->width +
2945 png_pass_inc[png_ptr->pass] - 1 -
2946 png_pass_start[png_ptr->pass]) /
2947 png_pass_inc[png_ptr->pass];
2949 png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
2950 png_ptr->iwidth) + 1;
2952 if (!(png_ptr->transformations & PNG_INTERLACE))
2954 png_ptr->num_rows = (png_ptr->height +
2955 png_pass_yinc[png_ptr->pass] - 1 -
2956 png_pass_ystart[png_ptr->pass]) /
2957 png_pass_yinc[png_ptr->pass];
2958 if (!(png_ptr->num_rows))
2959 continue;
2961 else /* if (png_ptr->transformations & PNG_INTERLACE) */
2962 break;
2963 } while (png_ptr->iwidth == 0);
2965 if (png_ptr->pass < 7)
2966 return;
2968 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2970 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
2972 #ifdef PNG_USE_LOCAL_ARRAYS
2973 PNG_CONST PNG_IDAT;
2974 #endif
2975 char extra;
2976 int ret;
2978 png_ptr->zstream.next_out = (Byte *)&extra;
2979 png_ptr->zstream.avail_out = (uInt)1;
2980 for (;;)
2982 if (!(png_ptr->zstream.avail_in))
2984 while (!png_ptr->idat_size)
2986 png_byte chunk_length[4];
2988 png_crc_finish(png_ptr, 0);
2990 png_read_data(png_ptr, chunk_length, 4);
2991 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
2992 png_reset_crc(png_ptr);
2993 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2994 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
2995 png_error(png_ptr, "Not enough image data");
2998 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2999 png_ptr->zstream.next_in = png_ptr->zbuf;
3000 if (png_ptr->zbuf_size > png_ptr->idat_size)
3001 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
3002 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
3003 png_ptr->idat_size -= png_ptr->zstream.avail_in;
3005 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
3006 if (ret == Z_STREAM_END)
3008 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
3009 png_ptr->idat_size)
3010 png_warning(png_ptr, "Extra compressed data");
3011 png_ptr->mode |= PNG_AFTER_IDAT;
3012 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3013 break;
3015 if (ret != Z_OK)
3016 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
3017 "Decompression Error");
3019 if (!(png_ptr->zstream.avail_out))
3021 png_warning(png_ptr, "Extra compressed data.");
3022 png_ptr->mode |= PNG_AFTER_IDAT;
3023 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3024 break;
3028 png_ptr->zstream.avail_out = 0;
3031 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
3032 png_warning(png_ptr, "Extra compression data");
3034 inflateReset(&png_ptr->zstream);
3036 png_ptr->mode |= PNG_AFTER_IDAT;
3038 #endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
3040 void /* PRIVATE */
3041 png_read_start_row(png_structp png_ptr)
3043 #ifdef PNG_USE_LOCAL_ARRAYS
3044 #ifdef PNG_READ_INTERLACING_SUPPORTED
3045 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3047 /* Start of interlace block */
3048 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3050 /* Offset to next interlace block */
3051 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3053 /* Start of interlace block in the y direction */
3054 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3056 /* Offset to next interlace block in the y direction */
3057 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3058 #endif
3059 #endif
3061 int max_pixel_depth;
3062 png_size_t row_bytes;
3064 png_debug(1, "in png_read_start_row");
3065 png_ptr->zstream.avail_in = 0;
3066 png_init_read_transformations(png_ptr);
3067 #ifdef PNG_READ_INTERLACING_SUPPORTED
3068 if (png_ptr->interlaced)
3070 if (!(png_ptr->transformations & PNG_INTERLACE))
3071 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
3072 png_pass_ystart[0]) / png_pass_yinc[0];
3073 else
3074 png_ptr->num_rows = png_ptr->height;
3076 png_ptr->iwidth = (png_ptr->width +
3077 png_pass_inc[png_ptr->pass] - 1 -
3078 png_pass_start[png_ptr->pass]) /
3079 png_pass_inc[png_ptr->pass];
3081 png_ptr->irowbytes =
3082 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1;
3084 else
3085 #endif /* PNG_READ_INTERLACING_SUPPORTED */
3087 png_ptr->num_rows = png_ptr->height;
3088 png_ptr->iwidth = png_ptr->width;
3089 png_ptr->irowbytes = png_ptr->rowbytes + 1;
3091 max_pixel_depth = png_ptr->pixel_depth;
3093 #if defined(PNG_READ_PACK_SUPPORTED)
3094 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
3095 max_pixel_depth = 8;
3096 #endif
3098 #if defined(PNG_READ_EXPAND_SUPPORTED)
3099 if (png_ptr->transformations & PNG_EXPAND)
3101 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3103 if (png_ptr->num_trans)
3104 max_pixel_depth = 32;
3105 else
3106 max_pixel_depth = 24;
3108 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3110 if (max_pixel_depth < 8)
3111 max_pixel_depth = 8;
3112 if (png_ptr->num_trans)
3113 max_pixel_depth *= 2;
3115 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3117 if (png_ptr->num_trans)
3119 max_pixel_depth *= 4;
3120 max_pixel_depth /= 3;
3124 #endif
3126 #if defined(PNG_READ_FILLER_SUPPORTED)
3127 if (png_ptr->transformations & (PNG_FILLER))
3129 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3130 max_pixel_depth = 32;
3131 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3133 if (max_pixel_depth <= 8)
3134 max_pixel_depth = 16;
3135 else
3136 max_pixel_depth = 32;
3138 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3140 if (max_pixel_depth <= 32)
3141 max_pixel_depth = 32;
3142 else
3143 max_pixel_depth = 64;
3146 #endif
3148 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
3149 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3151 if (
3152 #if defined(PNG_READ_EXPAND_SUPPORTED)
3153 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3154 #endif
3155 #if defined(PNG_READ_FILLER_SUPPORTED)
3156 (png_ptr->transformations & (PNG_FILLER)) ||
3157 #endif
3158 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3160 if (max_pixel_depth <= 16)
3161 max_pixel_depth = 32;
3162 else
3163 max_pixel_depth = 64;
3165 else
3167 if (max_pixel_depth <= 8)
3169 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3170 max_pixel_depth = 32;
3171 else
3172 max_pixel_depth = 24;
3174 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3175 max_pixel_depth = 64;
3176 else
3177 max_pixel_depth = 48;
3180 #endif
3182 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3183 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
3184 if (png_ptr->transformations & PNG_USER_TRANSFORM)
3186 int user_pixel_depth = png_ptr->user_transform_depth*
3187 png_ptr->user_transform_channels;
3188 if (user_pixel_depth > max_pixel_depth)
3189 max_pixel_depth=user_pixel_depth;
3191 #endif
3193 /* Align the width on the next larger 8 pixels. Mainly used
3194 * for interlacing
3196 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
3197 /* Calculate the maximum bytes needed, adding a byte and a pixel
3198 * for safety's sake
3200 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
3201 1 + ((max_pixel_depth + 7) >> 3);
3202 #ifdef PNG_MAX_MALLOC_64K
3203 if (row_bytes > (png_uint_32)65536L)
3204 png_error(png_ptr, "This image requires a row greater than 64KB");
3205 #endif
3207 if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
3209 png_free(png_ptr, png_ptr->big_row_buf);
3210 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 64);
3211 if (png_ptr->interlaced)
3212 png_memset(png_ptr->big_row_buf, 0, row_bytes + 64);
3213 png_ptr->row_buf = png_ptr->big_row_buf + 32;
3214 png_ptr->old_big_row_buf_size = row_bytes + 64;
3217 #ifdef PNG_MAX_MALLOC_64K
3218 if ((png_uint_32)row_bytes + 1 > (png_uint_32)65536L)
3219 png_error(png_ptr, "This image requires a row greater than 64KB");
3220 #endif
3221 if ((png_uint_32)row_bytes > (png_uint_32)(PNG_SIZE_MAX - 1))
3222 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
3224 if (row_bytes + 1 > png_ptr->old_prev_row_size)
3226 png_free(png_ptr, png_ptr->prev_row);
3227 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3228 row_bytes + 1));
3229 png_memset_check(png_ptr, png_ptr->prev_row, 0, row_bytes + 1);
3230 png_ptr->old_prev_row_size = row_bytes + 1;
3233 png_ptr->rowbytes = row_bytes;
3235 png_debug1(3, "width = %lu,", png_ptr->width);
3236 png_debug1(3, "height = %lu,", png_ptr->height);
3237 png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
3238 png_debug1(3, "num_rows = %lu,", png_ptr->num_rows);
3239 png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
3240 png_debug1(3, "irowbytes = %lu", png_ptr->irowbytes);
3242 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3244 #endif /* PNG_READ_SUPPORTED */