2 /* pngrutil.c - utilities to read a PNG file
4 * libpng 1.0.9 - January 31, 2001
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2001 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.
17 #if defined(_WIN32_WCE)
18 /* strtod() function is not supported on WindowsCE */
19 # ifdef PNG_FLOATING_POINT_SUPPORTED
20 __inline double strtod(const char *nptr, char **endptr)
26 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
27 str = (wchar_t *)malloc(len * sizeof(wchar_t));
30 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
31 result = wcstod(str, &end);
32 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
33 *endptr = (char *)nptr + (strlen(nptr) - len + 1);
41 #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
42 /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
43 png_uint_32 /* PRIVATE */
44 png_get_uint_32(png_bytep buf)
46 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
47 ((png_uint_32)(*(buf + 1)) << 16) +
48 ((png_uint_32)(*(buf + 2)) << 8) +
49 (png_uint_32)(*(buf + 3));
54 #if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED)
55 /* Grab a signed 32-bit integer from a buffer in big-endian format. The
56 * data is stored in the PNG file in two's complement format, and it is
57 * assumed that the machine format for signed integers is the same. */
58 png_int_32 /* PRIVATE */
59 png_get_int_32(png_bytep buf)
61 png_int_32 i = ((png_int_32)(*buf) << 24) +
62 ((png_int_32)(*(buf + 1)) << 16) +
63 ((png_int_32)(*(buf + 2)) << 8) +
64 (png_int_32)(*(buf + 3));
68 #endif /* PNG_READ_pCAL_SUPPORTED */
70 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
71 png_uint_16 /* PRIVATE */
72 png_get_uint_16(png_bytep buf)
74 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
75 (png_uint_16)(*(buf + 1)));
79 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
81 /* Read data, and (optionally) run it through the CRC. */
83 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
85 png_read_data(png_ptr, buf, length);
86 png_calculate_crc(png_ptr, buf, length);
89 /* Optionally skip data and then check the CRC. Depending on whether we
90 are reading a ancillary or critical chunk, and how the program has set
91 things up, we may calculate the CRC on the data and print a message.
92 Returns '1' if there was a CRC error, '0' otherwise. */
94 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
97 png_size_t istop = png_ptr->zbuf_size;
99 for (i = (png_size_t)skip; i > istop; i -= istop)
101 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
105 png_crc_read(png_ptr, png_ptr->zbuf, i);
108 if (png_crc_error(png_ptr))
110 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
111 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
112 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
113 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
115 png_chunk_warning(png_ptr, "CRC error");
119 png_chunk_error(png_ptr, "CRC error");
127 /* Compare the CRC stored in the PNG file with that calculated by libpng from
128 the data it has read thus far. */
130 png_crc_error(png_structp png_ptr)
132 png_byte crc_bytes[4];
136 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
138 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
139 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
144 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
148 png_read_data(png_ptr, crc_bytes, 4);
152 crc = png_get_uint_32(crc_bytes);
153 return ((int)(crc != png_ptr->crc));
159 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
160 defined(PNG_READ_iCCP_SUPPORTED)
162 * Decompress trailing data in a chunk. The assumption is that chunkdata
163 * points at an allocated area holding the contents of a chunk with a
164 * trailing compressed part. What we get back is an allocated area
165 * holding the original prefix part and an uncompressed version of the
166 * trailing part (the malloc area passed in is freed).
168 png_charp /* PRIVATE */
169 png_decompress_chunk(png_structp png_ptr, int comp_type,
170 png_charp chunkdata, png_size_t chunklength,
171 png_size_t prefix_size, png_size_t *newlength)
173 static char msg[] = "Error decoding compressed text";
174 png_charp text = NULL;
175 png_size_t text_size;
177 if (comp_type == PNG_COMPRESSION_TYPE_BASE)
180 png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
181 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
182 png_ptr->zstream.next_out = png_ptr->zbuf;
183 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
188 while (png_ptr->zstream.avail_in)
190 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
191 if (ret != Z_OK && ret != Z_STREAM_END)
193 if (png_ptr->zstream.msg != NULL)
194 png_warning(png_ptr, png_ptr->zstream.msg);
196 png_warning(png_ptr, msg);
197 inflateReset(&png_ptr->zstream);
198 png_ptr->zstream.avail_in = 0;
202 text_size = prefix_size + sizeof(msg) + 1;
203 text = (png_charp)png_malloc(png_ptr, text_size);
204 png_memcpy(text, chunkdata, prefix_size);
207 text[text_size - 1] = 0x00;
209 /* Copy what we can of the error message into the text chunk */
210 text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
211 text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
212 png_memcpy(text + prefix_size, msg, text_size + 1);
215 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
219 text_size = prefix_size +
220 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
221 text = (png_charp)png_malloc(png_ptr, text_size + 1);
222 png_memcpy(text + prefix_size, png_ptr->zbuf,
223 text_size - prefix_size);
224 png_memcpy(text, chunkdata, prefix_size);
225 *(text + text_size) = 0x00;
232 text = (png_charp)png_malloc(png_ptr, (png_uint_32)(text_size +
233 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
234 png_memcpy(text, tmp, text_size);
235 png_free(png_ptr, tmp);
236 png_memcpy(text + text_size, png_ptr->zbuf,
237 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
238 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
239 *(text + text_size) = 0x00;
241 if (ret == Z_STREAM_END)
245 png_ptr->zstream.next_out = png_ptr->zbuf;
246 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
250 if (ret != Z_STREAM_END)
252 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
255 if (ret == Z_BUF_ERROR)
256 sprintf(umsg,"Buffer error in compressed datastream in %s chunk",
257 png_ptr->chunk_name);
258 else if (ret == Z_DATA_ERROR)
259 sprintf(umsg,"Data error in compressed datastream in %s chunk",
260 png_ptr->chunk_name);
262 sprintf(umsg,"Incomplete compressed datastream in %s chunk",
263 png_ptr->chunk_name);
264 png_warning(png_ptr, umsg);
267 "Incomplete compressed datastream in chunk other than IDAT");
269 text_size=prefix_size;
272 text = (png_charp)png_malloc(png_ptr, text_size+1);
273 png_memcpy(text, chunkdata, prefix_size);
275 *(text + text_size) = 0x00;
278 inflateReset(&png_ptr->zstream);
279 png_ptr->zstream.avail_in = 0;
281 png_free(png_ptr, chunkdata);
283 *newlength=text_size;
285 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
287 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
290 sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
291 png_warning(png_ptr, umsg);
293 png_warning(png_ptr, "Unknown zTXt compression type");
296 *(chunkdata + prefix_size) = 0x00;
297 *newlength=prefix_size;
304 /* read and check the IDHR chunk */
306 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
309 png_uint_32 width, height;
310 int bit_depth, color_type, compression_type, filter_type;
313 png_debug(1, "in png_handle_IHDR\n");
315 if (png_ptr->mode & PNG_HAVE_IHDR)
316 png_error(png_ptr, "Out of place IHDR");
318 /* check the length */
320 png_error(png_ptr, "Invalid IHDR chunk");
322 png_ptr->mode |= PNG_HAVE_IHDR;
324 png_crc_read(png_ptr, buf, 13);
325 png_crc_finish(png_ptr, 0);
327 width = png_get_uint_32(buf);
328 height = png_get_uint_32(buf + 4);
331 compression_type = buf[10];
332 filter_type = buf[11];
333 interlace_type = buf[12];
335 /* check for width and height valid values */
336 if (width == 0 || width > PNG_MAX_UINT || height == 0 ||
337 height > PNG_MAX_UINT)
338 png_error(png_ptr, "Invalid image size in IHDR");
340 /* check other values */
341 if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
342 bit_depth != 8 && bit_depth != 16)
343 png_error(png_ptr, "Invalid bit depth in IHDR");
345 if (color_type < 0 || color_type == 1 ||
346 color_type == 5 || color_type > 6)
347 png_error(png_ptr, "Invalid color type in IHDR");
349 if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
350 ((color_type == PNG_COLOR_TYPE_RGB ||
351 color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
352 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
353 png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");
355 if (interlace_type >= PNG_INTERLACE_LAST)
356 png_error(png_ptr, "Unknown interlace method in IHDR");
358 if (compression_type != PNG_COMPRESSION_TYPE_BASE)
359 png_error(png_ptr, "Unknown compression method in IHDR");
361 #if defined(PNG_MNG_FEATURES_SUPPORTED)
362 /* Accept filter_method 64 (intrapixel differencing) only if
363 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
364 * 2. Libpng did not read a PNG signature (this filter_method is only
365 * used in PNG datastreams that are embedded in MNG datastreams) and
366 * 3. The application called png_permit_mng_features with a mask that
367 * included PNG_FLAG_MNG_FILTER_64 and
368 * 4. The filter_method is 64 and
369 * 5. The color_type is RGB or RGBA
371 if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)
372 png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n");
373 if(filter_type != PNG_FILTER_TYPE_BASE)
375 if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
376 (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
377 ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
378 (color_type == PNG_COLOR_TYPE_RGB ||
379 color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
380 png_error(png_ptr, "Unknown filter method in IHDR");
381 if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
382 png_warning(png_ptr, "Invalid filter method in IHDR");
385 if(filter_type != PNG_FILTER_TYPE_BASE)
386 png_error(png_ptr, "Unknown filter method in IHDR");
389 /* set internal variables */
390 png_ptr->width = width;
391 png_ptr->height = height;
392 png_ptr->bit_depth = (png_byte)bit_depth;
393 png_ptr->interlaced = (png_byte)interlace_type;
394 png_ptr->color_type = (png_byte)color_type;
395 png_ptr->filter_type = (png_byte)filter_type;
397 /* find number of channels */
398 switch (png_ptr->color_type)
400 case PNG_COLOR_TYPE_GRAY:
401 case PNG_COLOR_TYPE_PALETTE:
402 png_ptr->channels = 1;
404 case PNG_COLOR_TYPE_RGB:
405 png_ptr->channels = 3;
407 case PNG_COLOR_TYPE_GRAY_ALPHA:
408 png_ptr->channels = 2;
410 case PNG_COLOR_TYPE_RGB_ALPHA:
411 png_ptr->channels = 4;
415 /* set up other useful info */
416 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
418 png_ptr->rowbytes = ((png_ptr->width *
419 (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
420 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
421 png_debug1(3,"channels = %d\n", png_ptr->channels);
422 png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
423 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
424 color_type, interlace_type, compression_type, filter_type);
427 /* read and check the palette */
429 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
431 png_color palette[PNG_MAX_PALETTE_LENGTH];
433 #ifndef PNG_NO_POINTER_INDEXING
437 png_debug(1, "in png_handle_PLTE\n");
439 if (!(png_ptr->mode & PNG_HAVE_IHDR))
440 png_error(png_ptr, "Missing IHDR before PLTE");
441 else if (png_ptr->mode & PNG_HAVE_IDAT)
443 png_warning(png_ptr, "Invalid PLTE after IDAT");
444 png_crc_finish(png_ptr, length);
447 else if (png_ptr->mode & PNG_HAVE_PLTE)
448 png_error(png_ptr, "Duplicate PLTE chunk");
450 png_ptr->mode |= PNG_HAVE_PLTE;
452 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
453 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
455 png_crc_finish(png_ptr, length);
460 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
462 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
464 png_warning(png_ptr, "Invalid palette chunk");
465 png_crc_finish(png_ptr, length);
470 png_error(png_ptr, "Invalid palette chunk");
474 num = (int)length / 3;
476 #ifndef PNG_NO_POINTER_INDEXING
477 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
481 png_crc_read(png_ptr, buf, 3);
482 pal_ptr->red = buf[0];
483 pal_ptr->green = buf[1];
484 pal_ptr->blue = buf[2];
487 for (i = 0; i < num; i++)
491 png_crc_read(png_ptr, buf, 3);
492 /* don't depend upon png_color being any order */
493 palette[i].red = buf[0];
494 palette[i].green = buf[1];
495 palette[i].blue = buf[2];
499 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
500 whatever the normal CRC configuration tells us. However, if we
501 have an RGB image, the PLTE can be considered ancillary, so
502 we will act as though it is. */
503 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
504 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
507 png_crc_finish(png_ptr, 0);
509 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
510 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
512 /* If we don't want to use the data from an ancillary chunk,
513 we have two options: an error abort, or a warning and we
514 ignore the data in this chunk (which should be OK, since
515 it's considered ancillary for a RGB or RGBA image). */
516 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
518 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
520 png_chunk_error(png_ptr, "CRC error");
524 png_chunk_warning(png_ptr, "CRC error");
528 /* Otherwise, we (optionally) emit a warning and use the chunk. */
529 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
531 png_chunk_warning(png_ptr, "CRC error");
536 png_set_PLTE(png_ptr, info_ptr, palette, num);
538 #if defined(PNG_READ_tRNS_SUPPORTED)
539 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
541 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
543 if (png_ptr->num_trans > (png_uint_16)num)
545 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
546 png_ptr->num_trans = (png_uint_16)num;
548 if (info_ptr->num_trans > (png_uint_16)num)
550 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
551 info_ptr->num_trans = (png_uint_16)num;
560 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
562 png_debug(1, "in png_handle_IEND\n");
564 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
566 png_error(png_ptr, "No image in file");
568 /* to quiet compiler warnings about unused info_ptr */
569 if (info_ptr == NULL)
573 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
577 png_warning(png_ptr, "Incorrect IEND chunk length");
579 png_crc_finish(png_ptr, length);
582 #if defined(PNG_READ_gAMA_SUPPORTED)
584 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
586 png_fixed_point igamma;
587 #ifdef PNG_FLOATING_POINT_SUPPORTED
592 png_debug(1, "in png_handle_gAMA\n");
594 if (!(png_ptr->mode & PNG_HAVE_IHDR))
595 png_error(png_ptr, "Missing IHDR before gAMA");
596 else if (png_ptr->mode & PNG_HAVE_IDAT)
598 png_warning(png_ptr, "Invalid gAMA after IDAT");
599 png_crc_finish(png_ptr, length);
602 else if (png_ptr->mode & PNG_HAVE_PLTE)
603 /* Should be an error, but we can cope with it */
604 png_warning(png_ptr, "Out of place gAMA chunk");
606 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
607 #if defined(PNG_READ_sRGB_SUPPORTED)
608 && !(info_ptr->valid & PNG_INFO_sRGB)
612 png_warning(png_ptr, "Duplicate gAMA chunk");
613 png_crc_finish(png_ptr, length);
619 png_warning(png_ptr, "Incorrect gAMA chunk length");
620 png_crc_finish(png_ptr, length);
624 png_crc_read(png_ptr, buf, 4);
625 if (png_crc_finish(png_ptr, 0))
628 igamma = (png_fixed_point)png_get_uint_32(buf);
629 /* check for zero gamma */
633 #if defined(PNG_READ_sRGB_SUPPORTED)
634 if (info_ptr->valid & PNG_INFO_sRGB)
635 if(igamma < 45000L || igamma > 46000L)
638 "Ignoring incorrect gAMA value when sRGB is also present");
639 #ifndef PNG_NO_CONSOLE_IO
640 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
644 #endif /* PNG_READ_sRGB_SUPPORTED */
646 #ifdef PNG_FLOATING_POINT_SUPPORTED
647 file_gamma = (float)igamma / (float)100000.0;
648 # ifdef PNG_READ_GAMMA_SUPPORTED
649 png_ptr->gamma = file_gamma;
651 png_set_gAMA(png_ptr, info_ptr, file_gamma);
653 #ifdef PNG_FIXED_POINT_SUPPORTED
654 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
659 #if defined(PNG_READ_sBIT_SUPPORTED)
661 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
666 png_debug(1, "in png_handle_sBIT\n");
668 buf[0] = buf[1] = buf[2] = buf[3] = 0;
670 if (!(png_ptr->mode & PNG_HAVE_IHDR))
671 png_error(png_ptr, "Missing IHDR before sBIT");
672 else if (png_ptr->mode & PNG_HAVE_IDAT)
674 png_warning(png_ptr, "Invalid sBIT after IDAT");
675 png_crc_finish(png_ptr, length);
678 else if (png_ptr->mode & PNG_HAVE_PLTE)
680 /* Should be an error, but we can cope with it */
681 png_warning(png_ptr, "Out of place sBIT chunk");
683 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
685 png_warning(png_ptr, "Duplicate sBIT chunk");
686 png_crc_finish(png_ptr, length);
690 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
693 truelen = (png_size_t)png_ptr->channels;
695 if (length != truelen)
697 png_warning(png_ptr, "Incorrect sBIT chunk length");
698 png_crc_finish(png_ptr, length);
702 png_crc_read(png_ptr, buf, truelen);
703 if (png_crc_finish(png_ptr, 0))
706 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
708 png_ptr->sig_bit.red = buf[0];
709 png_ptr->sig_bit.green = buf[1];
710 png_ptr->sig_bit.blue = buf[2];
711 png_ptr->sig_bit.alpha = buf[3];
715 png_ptr->sig_bit.gray = buf[0];
716 png_ptr->sig_bit.red = buf[0];
717 png_ptr->sig_bit.green = buf[0];
718 png_ptr->sig_bit.blue = buf[0];
719 png_ptr->sig_bit.alpha = buf[1];
721 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
725 #if defined(PNG_READ_cHRM_SUPPORTED)
727 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
730 #ifdef PNG_FLOATING_POINT_SUPPORTED
731 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
733 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
734 int_y_green, int_x_blue, int_y_blue;
736 png_debug(1, "in png_handle_cHRM\n");
738 if (!(png_ptr->mode & PNG_HAVE_IHDR))
739 png_error(png_ptr, "Missing IHDR before cHRM");
740 else if (png_ptr->mode & PNG_HAVE_IDAT)
742 png_warning(png_ptr, "Invalid cHRM after IDAT");
743 png_crc_finish(png_ptr, length);
746 else if (png_ptr->mode & PNG_HAVE_PLTE)
747 /* Should be an error, but we can cope with it */
748 png_warning(png_ptr, "Missing PLTE before cHRM");
750 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
751 #if defined(PNG_READ_sRGB_SUPPORTED)
752 && !(info_ptr->valid & PNG_INFO_sRGB)
756 png_warning(png_ptr, "Duplicate cHRM chunk");
757 png_crc_finish(png_ptr, length);
763 png_warning(png_ptr, "Incorrect cHRM chunk length");
764 png_crc_finish(png_ptr, length);
768 png_crc_read(png_ptr, buf, 4);
769 int_x_white = (png_fixed_point)png_get_uint_32(buf);
771 png_crc_read(png_ptr, buf, 4);
772 int_y_white = (png_fixed_point)png_get_uint_32(buf);
774 if (int_x_white > 80000L || int_y_white > 80000L ||
775 int_x_white + int_y_white > 100000L)
777 png_warning(png_ptr, "Invalid cHRM white point");
778 png_crc_finish(png_ptr, 24);
782 png_crc_read(png_ptr, buf, 4);
783 int_x_red = (png_fixed_point)png_get_uint_32(buf);
785 png_crc_read(png_ptr, buf, 4);
786 int_y_red = (png_fixed_point)png_get_uint_32(buf);
788 if (int_x_red > 80000L || int_y_red > 80000L ||
789 int_x_red + int_y_red > 100000L)
791 png_warning(png_ptr, "Invalid cHRM red point");
792 png_crc_finish(png_ptr, 16);
796 png_crc_read(png_ptr, buf, 4);
797 int_x_green = (png_fixed_point)png_get_uint_32(buf);
799 png_crc_read(png_ptr, buf, 4);
800 int_y_green = (png_fixed_point)png_get_uint_32(buf);
802 if (int_x_green > 80000L || int_y_green > 80000L ||
803 int_x_green + int_y_green > 100000L)
805 png_warning(png_ptr, "Invalid cHRM green point");
806 png_crc_finish(png_ptr, 8);
810 png_crc_read(png_ptr, buf, 4);
811 int_x_blue = (png_fixed_point)png_get_uint_32(buf);
813 png_crc_read(png_ptr, buf, 4);
814 int_y_blue = (png_fixed_point)png_get_uint_32(buf);
816 if (int_x_blue > 80000L || int_y_blue > 80000L ||
817 int_x_blue + int_y_blue > 100000L)
819 png_warning(png_ptr, "Invalid cHRM blue point");
820 png_crc_finish(png_ptr, 0);
823 #ifdef PNG_FLOATING_POINT_SUPPORTED
824 white_x = (float)int_x_white / (float)100000.0;
825 white_y = (float)int_y_white / (float)100000.0;
826 red_x = (float)int_x_red / (float)100000.0;
827 red_y = (float)int_y_red / (float)100000.0;
828 green_x = (float)int_x_green / (float)100000.0;
829 green_y = (float)int_y_green / (float)100000.0;
830 blue_x = (float)int_x_blue / (float)100000.0;
831 blue_y = (float)int_y_blue / (float)100000.0;
834 #if defined(PNG_READ_sRGB_SUPPORTED)
835 if (info_ptr->valid & PNG_INFO_sRGB)
837 if (abs(int_x_white - 31270L) > 1000 ||
838 abs(int_y_white - 32900L) > 1000 ||
839 abs( int_x_red - 64000L) > 1000 ||
840 abs( int_y_red - 33000L) > 1000 ||
841 abs(int_x_green - 30000L) > 1000 ||
842 abs(int_y_green - 60000L) > 1000 ||
843 abs( int_x_blue - 15000L) > 1000 ||
844 abs( int_y_blue - 6000L) > 1000)
848 "Ignoring incorrect cHRM value when sRGB is also present");
849 #ifndef PNG_NO_CONSOLE_IO
850 #ifdef PNG_FLOATING_POINT_SUPPORTED
851 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
852 white_x, white_y, red_x, red_y);
853 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
854 green_x, green_y, blue_x, blue_y);
856 fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
857 int_x_white, int_y_white, int_x_red, int_y_red);
858 fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
859 int_x_green, int_y_green, int_x_blue, int_y_blue);
861 #endif /* PNG_NO_CONSOLE_IO */
863 png_crc_finish(png_ptr, 0);
866 #endif /* PNG_READ_sRGB_SUPPORTED */
868 #ifdef PNG_FLOATING_POINT_SUPPORTED
869 png_set_cHRM(png_ptr, info_ptr,
870 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
872 #ifdef PNG_FIXED_POINT_SUPPORTED
873 png_set_cHRM_fixed(png_ptr, info_ptr,
874 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
875 int_y_green, int_x_blue, int_y_blue);
877 if (png_crc_finish(png_ptr, 0))
882 #if defined(PNG_READ_sRGB_SUPPORTED)
884 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
889 png_debug(1, "in png_handle_sRGB\n");
891 if (!(png_ptr->mode & PNG_HAVE_IHDR))
892 png_error(png_ptr, "Missing IHDR before sRGB");
893 else if (png_ptr->mode & PNG_HAVE_IDAT)
895 png_warning(png_ptr, "Invalid sRGB after IDAT");
896 png_crc_finish(png_ptr, length);
899 else if (png_ptr->mode & PNG_HAVE_PLTE)
900 /* Should be an error, but we can cope with it */
901 png_warning(png_ptr, "Out of place sRGB chunk");
903 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
905 png_warning(png_ptr, "Duplicate sRGB chunk");
906 png_crc_finish(png_ptr, length);
912 png_warning(png_ptr, "Incorrect sRGB chunk length");
913 png_crc_finish(png_ptr, length);
917 png_crc_read(png_ptr, buf, 1);
918 if (png_crc_finish(png_ptr, 0))
922 /* check for bad intent */
923 if (intent >= PNG_sRGB_INTENT_LAST)
925 png_warning(png_ptr, "Unknown sRGB intent");
929 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
930 if ((info_ptr->valid & PNG_INFO_gAMA))
933 #ifdef PNG_FIXED_POINT_SUPPORTED
934 igamma=(int)info_ptr->int_gamma;
936 # ifdef PNG_FLOATING_POINT_SUPPORTED
937 igamma=(int)(info_ptr->gamma * 100000.);
940 #if 0 && defined(PNG_cHRM_SUPPORTED) && !defined(PNG_FIXED_POINT_SUPPORTED)
941 /* We need to define these here because they aren't in png.h */
942 png_fixed_point int_x_white;
943 png_fixed_point int_y_white;
944 png_fixed_point int_x_red;
945 png_fixed_point int_y_red;
946 png_fixed_point int_x_green;
947 png_fixed_point int_y_green;
948 png_fixed_point int_x_blue;
949 png_fixed_point int_y_blue;
951 if(igamma < 45000L || igamma > 46000L)
954 "Ignoring incorrect gAMA value when sRGB is also present");
955 #ifndef PNG_NO_CONSOLE_IO
956 # ifdef PNG_FIXED_POINT_SUPPORTED
957 fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
959 # ifdef PNG_FLOATING_POINT_SUPPORTED
960 fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
966 #endif /* PNG_READ_gAMA_SUPPORTED */
968 #ifdef PNG_READ_cHRM_SUPPORTED
969 #ifdef PNG_FIXED_POINT_SUPPORTED
970 if (info_ptr->valid & PNG_INFO_cHRM)
971 if (abs(info_ptr->int_x_white - 31270L) > 1000 ||
972 abs(info_ptr->int_y_white - 32900L) > 1000 ||
973 abs( info_ptr->int_x_red - 64000L) > 1000 ||
974 abs( info_ptr->int_y_red - 33000L) > 1000 ||
975 abs(info_ptr->int_x_green - 30000L) > 1000 ||
976 abs(info_ptr->int_y_green - 60000L) > 1000 ||
977 abs( info_ptr->int_x_blue - 15000L) > 1000 ||
978 abs( info_ptr->int_y_blue - 6000L) > 1000)
981 "Ignoring incorrect cHRM value when sRGB is also present");
983 #endif /* PNG_FIXED_POINT_SUPPORTED */
984 #endif /* PNG_READ_cHRM_SUPPORTED */
986 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
988 #endif /* PNG_READ_sRGB_SUPPORTED */
990 #if defined(PNG_READ_iCCP_SUPPORTED)
992 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
993 /* Note: this does not properly handle chunks that are > 64K under DOS */
996 png_byte compression_type;
998 png_uint_32 skip = 0;
999 png_uint_32 profile_size = 0;
1000 png_uint_32 profile_length = 0;
1001 png_size_t slength, prefix_length, data_length;
1003 png_debug(1, "in png_handle_iCCP\n");
1005 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1006 png_error(png_ptr, "Missing IHDR before iCCP");
1007 else if (png_ptr->mode & PNG_HAVE_IDAT)
1009 png_warning(png_ptr, "Invalid iCCP after IDAT");
1010 png_crc_finish(png_ptr, length);
1013 else if (png_ptr->mode & PNG_HAVE_PLTE)
1014 /* Should be an error, but we can cope with it */
1015 png_warning(png_ptr, "Out of place iCCP chunk");
1017 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1019 png_warning(png_ptr, "Duplicate iCCP chunk");
1020 png_crc_finish(png_ptr, length);
1024 #ifdef PNG_MAX_MALLOC_64K
1025 if (length > (png_uint_32)65535L)
1027 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1028 skip = length - (png_uint_32)65535L;
1029 length = (png_uint_32)65535L;
1033 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1034 slength = (png_size_t)length;
1035 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1037 if (png_crc_finish(png_ptr, skip))
1039 png_free(png_ptr, chunkdata);
1043 chunkdata[slength] = 0x00;
1045 for (profile = chunkdata; *profile; profile++)
1046 /* empty loop to find end of name */ ;
1050 /* there should be at least one zero (the compression type byte)
1051 following the separator, and we should be on it */
1052 if ( profile >= chunkdata + slength)
1054 png_free(png_ptr, chunkdata);
1055 png_warning(png_ptr, "Malformed iCCP chunk");
1059 /* compression_type should always be zero */
1060 compression_type = *profile++;
1061 if (compression_type)
1063 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1064 compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1068 prefix_length = profile - chunkdata;
1069 chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
1070 slength, prefix_length, &data_length);
1072 profile_length = data_length - prefix_length;
1074 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1075 profile_size = ((*(chunkdata+prefix_length))<<24) |
1076 ((*(chunkdata+prefix_length+1))<<16) |
1077 ((*(chunkdata+prefix_length+2))<< 8) |
1078 ((*(chunkdata+prefix_length+3)) );
1080 if(profile_size < profile_length)
1081 profile_length = profile_size;
1083 if(profile_size > profile_length)
1085 png_warning(png_ptr, "Ignoring truncated iCCP profile.\n");
1089 png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
1090 chunkdata + prefix_length, profile_length);
1091 png_free(png_ptr, chunkdata);
1093 #endif /* PNG_READ_iCCP_SUPPORTED */
1095 #if defined(PNG_READ_sPLT_SUPPORTED)
1097 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1098 /* Note: this does not properly handle chunks that are > 64K under DOS */
1100 png_bytep chunkdata;
1101 png_bytep entry_start;
1102 png_sPLT_t new_palette;
1103 #ifdef PNG_NO_POINTER_INDEXING
1106 int data_length, entry_size, i;
1107 png_uint_32 skip = 0;
1110 png_debug(1, "in png_handle_sPLT\n");
1112 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1113 png_error(png_ptr, "Missing IHDR before sPLT");
1114 else if (png_ptr->mode & PNG_HAVE_IDAT)
1116 png_warning(png_ptr, "Invalid sPLT after IDAT");
1117 png_crc_finish(png_ptr, length);
1121 #ifdef PNG_MAX_MALLOC_64K
1122 if (length > (png_uint_32)65535L)
1124 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1125 skip = length - (png_uint_32)65535L;
1126 length = (png_uint_32)65535L;
1130 chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
1131 slength = (png_size_t)length;
1132 png_crc_read(png_ptr, chunkdata, slength);
1134 if (png_crc_finish(png_ptr, skip))
1136 png_free(png_ptr, chunkdata);
1140 chunkdata[slength] = 0x00;
1142 for (entry_start = chunkdata; *entry_start; entry_start++)
1143 /* empty loop to find end of name */ ;
1146 /* a sample depth should follow the separator, and we should be on it */
1147 if (entry_start > chunkdata + slength)
1149 png_free(png_ptr, chunkdata);
1150 png_warning(png_ptr, "malformed sPLT chunk");
1154 new_palette.depth = *entry_start++;
1155 entry_size = (new_palette.depth == 8 ? 6 : 10);
1156 data_length = (slength - (entry_start - chunkdata));
1158 /* integrity-check the data length */
1159 if (data_length % entry_size)
1161 png_free(png_ptr, chunkdata);
1162 png_error(png_ptr, "sPLT chunk has bad length");
1165 new_palette.nentries = data_length / entry_size;
1166 new_palette.entries = (png_sPLT_entryp)png_malloc(
1167 png_ptr, new_palette.nentries * sizeof(png_sPLT_entry));
1169 #ifndef PNG_NO_POINTER_INDEXING
1170 for (i = 0; i < new_palette.nentries; i++)
1172 png_sPLT_entryp pp = new_palette.entries + i;
1174 if (new_palette.depth == 8)
1176 pp->red = *entry_start++;
1177 pp->green = *entry_start++;
1178 pp->blue = *entry_start++;
1179 pp->alpha = *entry_start++;
1183 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1184 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1185 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1186 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1188 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1191 pp = new_palette.entries;
1192 for (i = 0; i < new_palette.nentries; i++)
1195 if (new_palette.depth == 8)
1197 pp[i].red = *entry_start++;
1198 pp[i].green = *entry_start++;
1199 pp[i].blue = *entry_start++;
1200 pp[i].alpha = *entry_start++;
1204 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1205 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1206 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1207 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1209 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1213 /* discard all chunk data except the name and stash that */
1214 new_palette.name = (png_charp)chunkdata;
1216 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1218 png_free(png_ptr, chunkdata);
1219 png_free(png_ptr, new_palette.entries);
1221 #endif /* PNG_READ_sPLT_SUPPORTED */
1223 #if defined(PNG_READ_tRNS_SUPPORTED)
1225 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1227 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1229 png_debug(1, "in png_handle_tRNS\n");
1231 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1232 png_error(png_ptr, "Missing IHDR before tRNS");
1233 else if (png_ptr->mode & PNG_HAVE_IDAT)
1235 png_warning(png_ptr, "Invalid tRNS after IDAT");
1236 png_crc_finish(png_ptr, length);
1239 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1241 png_warning(png_ptr, "Duplicate tRNS chunk");
1242 png_crc_finish(png_ptr, length);
1246 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1248 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1250 /* Should be an error, but we can cope with it */
1251 png_warning(png_ptr, "Missing PLTE before tRNS");
1253 else if (length > (png_uint_32)png_ptr->num_palette)
1255 png_warning(png_ptr, "Incorrect tRNS chunk length");
1256 png_crc_finish(png_ptr, length);
1261 png_warning(png_ptr, "Zero length tRNS chunk");
1262 png_crc_finish(png_ptr, length);
1266 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1267 png_ptr->num_trans = (png_uint_16)length;
1269 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1275 png_warning(png_ptr, "Incorrect tRNS chunk length");
1276 png_crc_finish(png_ptr, length);
1280 png_crc_read(png_ptr, buf, (png_size_t)length);
1281 png_ptr->num_trans = 1;
1282 png_ptr->trans_values.red = png_get_uint_16(buf);
1283 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1284 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1286 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1292 png_warning(png_ptr, "Incorrect tRNS chunk length");
1293 png_crc_finish(png_ptr, length);
1297 png_crc_read(png_ptr, buf, 2);
1298 png_ptr->num_trans = 1;
1299 png_ptr->trans_values.gray = png_get_uint_16(buf);
1303 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1304 png_crc_finish(png_ptr, length);
1308 if (png_crc_finish(png_ptr, 0))
1311 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1312 &(png_ptr->trans_values));
1316 #if defined(PNG_READ_bKGD_SUPPORTED)
1318 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1323 png_debug(1, "in png_handle_bKGD\n");
1325 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1326 png_error(png_ptr, "Missing IHDR before bKGD");
1327 else if (png_ptr->mode & PNG_HAVE_IDAT)
1329 png_warning(png_ptr, "Invalid bKGD after IDAT");
1330 png_crc_finish(png_ptr, length);
1333 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1334 !(png_ptr->mode & PNG_HAVE_PLTE))
1336 png_warning(png_ptr, "Missing PLTE before bKGD");
1337 png_crc_finish(png_ptr, length);
1340 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1342 png_warning(png_ptr, "Duplicate bKGD chunk");
1343 png_crc_finish(png_ptr, length);
1347 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1349 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1354 if (length != truelen)
1356 png_warning(png_ptr, "Incorrect bKGD chunk length");
1357 png_crc_finish(png_ptr, length);
1361 png_crc_read(png_ptr, buf, truelen);
1362 if (png_crc_finish(png_ptr, 0))
1365 /* We convert the index value into RGB components so that we can allow
1366 * arbitrary RGB values for background when we have transparency, and
1367 * so it is easy to determine the RGB values of the background color
1368 * from the info_ptr struct. */
1369 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1371 png_ptr->background.index = buf[0];
1372 if(info_ptr->num_palette)
1374 if(buf[0] > info_ptr->num_palette)
1376 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1379 png_ptr->background.red =
1380 (png_uint_16)png_ptr->palette[buf[0]].red;
1381 png_ptr->background.green =
1382 (png_uint_16)png_ptr->palette[buf[0]].green;
1383 png_ptr->background.blue =
1384 (png_uint_16)png_ptr->palette[buf[0]].blue;
1387 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1389 png_ptr->background.red =
1390 png_ptr->background.green =
1391 png_ptr->background.blue =
1392 png_ptr->background.gray = png_get_uint_16(buf);
1396 png_ptr->background.red = png_get_uint_16(buf);
1397 png_ptr->background.green = png_get_uint_16(buf + 2);
1398 png_ptr->background.blue = png_get_uint_16(buf + 4);
1401 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1405 #if defined(PNG_READ_hIST_SUPPORTED)
1407 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1410 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1412 png_debug(1, "in png_handle_hIST\n");
1414 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1415 png_error(png_ptr, "Missing IHDR before hIST");
1416 else if (png_ptr->mode & PNG_HAVE_IDAT)
1418 png_warning(png_ptr, "Invalid hIST after IDAT");
1419 png_crc_finish(png_ptr, length);
1422 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1424 png_warning(png_ptr, "Missing PLTE before hIST");
1425 png_crc_finish(png_ptr, length);
1428 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1430 png_warning(png_ptr, "Duplicate hIST chunk");
1431 png_crc_finish(png_ptr, length);
1435 num = (int)length / 2 ;
1436 if (num != png_ptr->num_palette)
1438 png_warning(png_ptr, "Incorrect hIST chunk length");
1439 png_crc_finish(png_ptr, length);
1443 for (i = 0; i < num; i++)
1447 png_crc_read(png_ptr, buf, 2);
1448 readbuf[i] = png_get_uint_16(buf);
1451 if (png_crc_finish(png_ptr, 0))
1454 png_set_hIST(png_ptr, info_ptr, readbuf);
1458 #if defined(PNG_READ_pHYs_SUPPORTED)
1460 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1463 png_uint_32 res_x, res_y;
1466 png_debug(1, "in png_handle_pHYs\n");
1468 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1469 png_error(png_ptr, "Missing IHDR before pHYs");
1470 else if (png_ptr->mode & PNG_HAVE_IDAT)
1472 png_warning(png_ptr, "Invalid pHYs after IDAT");
1473 png_crc_finish(png_ptr, length);
1476 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1478 png_warning(png_ptr, "Duplicate pHYs chunk");
1479 png_crc_finish(png_ptr, length);
1485 png_warning(png_ptr, "Incorrect pHYs chunk length");
1486 png_crc_finish(png_ptr, length);
1490 png_crc_read(png_ptr, buf, 9);
1491 if (png_crc_finish(png_ptr, 0))
1494 res_x = png_get_uint_32(buf);
1495 res_y = png_get_uint_32(buf + 4);
1497 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1501 #if defined(PNG_READ_oFFs_SUPPORTED)
1503 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1506 png_int_32 offset_x, offset_y;
1509 png_debug(1, "in png_handle_oFFs\n");
1511 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1512 png_error(png_ptr, "Missing IHDR before oFFs");
1513 else if (png_ptr->mode & PNG_HAVE_IDAT)
1515 png_warning(png_ptr, "Invalid oFFs after IDAT");
1516 png_crc_finish(png_ptr, length);
1519 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1521 png_warning(png_ptr, "Duplicate oFFs chunk");
1522 png_crc_finish(png_ptr, length);
1528 png_warning(png_ptr, "Incorrect oFFs chunk length");
1529 png_crc_finish(png_ptr, length);
1533 png_crc_read(png_ptr, buf, 9);
1534 if (png_crc_finish(png_ptr, 0))
1537 offset_x = png_get_int_32(buf);
1538 offset_y = png_get_int_32(buf + 4);
1540 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1544 #if defined(PNG_READ_pCAL_SUPPORTED)
1545 /* read the pCAL chunk (described in the PNG Extensions document) */
1547 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1551 png_byte type, nparams;
1552 png_charp buf, units, endptr;
1557 png_debug(1, "in png_handle_pCAL\n");
1559 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1560 png_error(png_ptr, "Missing IHDR before pCAL");
1561 else if (png_ptr->mode & PNG_HAVE_IDAT)
1563 png_warning(png_ptr, "Invalid pCAL after IDAT");
1564 png_crc_finish(png_ptr, length);
1567 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1569 png_warning(png_ptr, "Duplicate pCAL chunk");
1570 png_crc_finish(png_ptr, length);
1574 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
1576 purpose = (png_charp)png_malloc(png_ptr, length + 1);
1577 slength = (png_size_t)length;
1578 png_crc_read(png_ptr, (png_bytep)purpose, slength);
1580 if (png_crc_finish(png_ptr, 0))
1582 png_free(png_ptr, purpose);
1586 purpose[slength] = 0x00; /* null terminate the last string */
1588 png_debug(3, "Finding end of pCAL purpose string\n");
1589 for (buf = purpose; *buf; buf++)
1592 endptr = purpose + slength;
1594 /* We need to have at least 12 bytes after the purpose string
1595 in order to get the parameter information. */
1596 if (endptr <= buf + 12)
1598 png_warning(png_ptr, "Invalid pCAL data");
1599 png_free(png_ptr, purpose);
1603 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1604 X0 = png_get_int_32((png_bytep)buf+1);
1605 X1 = png_get_int_32((png_bytep)buf+5);
1610 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1611 /* Check that we have the right number of parameters for known
1613 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1614 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1615 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1616 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1618 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1619 png_free(png_ptr, purpose);
1622 else if (type >= PNG_EQUATION_LAST)
1624 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1627 for (buf = units; *buf; buf++)
1628 /* Empty loop to move past the units string. */ ;
1630 png_debug(3, "Allocating pCAL parameters array\n");
1631 params = (png_charpp)png_malloc(png_ptr, (png_uint_32)(nparams
1632 *sizeof(png_charp))) ;
1634 /* Get pointers to the start of each parameter string. */
1635 for (i = 0; i < (int)nparams; i++)
1637 buf++; /* Skip the null string terminator from previous parameter. */
1639 png_debug1(3, "Reading pCAL parameter %d\n", i);
1640 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
1641 /* Empty loop to move past each parameter string */ ;
1643 /* Make sure we haven't run out of data yet */
1646 png_warning(png_ptr, "Invalid pCAL data");
1647 png_free(png_ptr, purpose);
1648 png_free(png_ptr, params);
1653 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1656 png_free(png_ptr, purpose);
1657 png_free(png_ptr, params);
1661 #if defined(PNG_READ_sCAL_SUPPORTED)
1662 /* read the sCAL chunk */
1664 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1666 png_charp buffer, ep;
1667 #ifdef PNG_FLOATING_POINT_SUPPORTED
1668 double width, height;
1671 #ifdef PNG_FIXED_POINT_SUPPORTED
1672 png_charp swidth, sheight;
1677 png_debug(1, "in png_handle_sCAL\n");
1679 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1680 png_error(png_ptr, "Missing IHDR before sCAL");
1681 else if (png_ptr->mode & PNG_HAVE_IDAT)
1683 png_warning(png_ptr, "Invalid sCAL after IDAT");
1684 png_crc_finish(png_ptr, length);
1687 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1689 png_warning(png_ptr, "Duplicate sCAL chunk");
1690 png_crc_finish(png_ptr, length);
1694 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1696 buffer = (png_charp)png_malloc(png_ptr, length + 1);
1697 slength = (png_size_t)length;
1698 png_crc_read(png_ptr, (png_bytep)buffer, slength);
1700 if (png_crc_finish(png_ptr, 0))
1702 png_free(png_ptr, buffer);
1706 buffer[slength] = 0x00; /* null terminate the last string */
1708 ep = buffer + 1; /* skip unit byte */
1710 #ifdef PNG_FLOATING_POINT_SUPPORTED
1711 width = strtod(ep, &vp);
1714 png_warning(png_ptr, "malformed width string in sCAL chunk");
1718 #ifdef PNG_FIXED_POINT_SUPPORTED
1719 swidth = (png_charp)png_malloc(png_ptr, strlen(ep) + 1);
1720 png_memcpy(swidth, ep, (png_size_t)strlen(ep));
1724 for (ep = buffer; *ep; ep++)
1728 #ifdef PNG_FLOATING_POINT_SUPPORTED
1729 height = strtod(ep, &vp);
1732 png_warning(png_ptr, "malformed height string in sCAL chunk");
1736 #ifdef PNG_FIXED_POINT_SUPPORTED
1737 sheight = (png_charp)png_malloc(png_ptr, strlen(ep) + 1);
1738 png_memcpy(sheight, ep, (png_size_t)strlen(ep));
1742 if (buffer + slength < ep
1743 #ifdef PNG_FLOATING_POINT_SUPPORTED
1744 || width <= 0. || height <= 0.
1748 png_warning(png_ptr, "Invalid sCAL data");
1749 png_free(png_ptr, buffer);
1750 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1751 png_free(png_ptr, swidth);
1752 png_free(png_ptr, sheight);
1758 #ifdef PNG_FLOATING_POINT_SUPPORTED
1759 png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1761 #ifdef PNG_FIXED_POINT_SUPPORTED
1762 png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1766 png_free(png_ptr, buffer);
1767 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1768 png_free(png_ptr, swidth);
1769 png_free(png_ptr, sheight);
1774 #if defined(PNG_READ_tIME_SUPPORTED)
1776 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1781 png_debug(1, "in png_handle_tIME\n");
1783 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1784 png_error(png_ptr, "Out of place tIME chunk");
1785 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1787 png_warning(png_ptr, "Duplicate tIME chunk");
1788 png_crc_finish(png_ptr, length);
1792 if (png_ptr->mode & PNG_HAVE_IDAT)
1793 png_ptr->mode |= PNG_AFTER_IDAT;
1797 png_warning(png_ptr, "Incorrect tIME chunk length");
1798 png_crc_finish(png_ptr, length);
1802 png_crc_read(png_ptr, buf, 7);
1803 if (png_crc_finish(png_ptr, 0))
1806 mod_time.second = buf[6];
1807 mod_time.minute = buf[5];
1808 mod_time.hour = buf[4];
1809 mod_time.day = buf[3];
1810 mod_time.month = buf[2];
1811 mod_time.year = png_get_uint_16(buf);
1813 png_set_tIME(png_ptr, info_ptr, &mod_time);
1817 #if defined(PNG_READ_tEXt_SUPPORTED)
1818 /* Note: this does not properly handle chunks that are > 64K under DOS */
1820 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1825 png_uint_32 skip = 0;
1828 png_debug(1, "in png_handle_tEXt\n");
1830 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1831 png_error(png_ptr, "Missing IHDR before tEXt");
1833 if (png_ptr->mode & PNG_HAVE_IDAT)
1834 png_ptr->mode |= PNG_AFTER_IDAT;
1836 #ifdef PNG_MAX_MALLOC_64K
1837 if (length > (png_uint_32)65535L)
1839 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1840 skip = length - (png_uint_32)65535L;
1841 length = (png_uint_32)65535L;
1845 key = (png_charp)png_malloc(png_ptr, length + 1);
1846 slength = (png_size_t)length;
1847 png_crc_read(png_ptr, (png_bytep)key, slength);
1849 if (png_crc_finish(png_ptr, skip))
1851 png_free(png_ptr, key);
1855 key[slength] = 0x00;
1857 for (text = key; *text; text++)
1858 /* empty loop to find end of key */ ;
1860 if (text != key + slength)
1863 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1864 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1865 text_ptr->key = key;
1866 #ifdef PNG_iTXt_SUPPORTED
1867 text_ptr->lang = NULL;
1868 text_ptr->lang_key = NULL;
1869 text_ptr->itxt_length = 0;
1871 text_ptr->text = text;
1872 text_ptr->text_length = png_strlen(text);
1874 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1876 png_free(png_ptr, key);
1877 png_free(png_ptr, text_ptr);
1881 #if defined(PNG_READ_zTXt_SUPPORTED)
1882 /* note: this does not correctly handle chunks that are > 64K under DOS */
1884 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1887 png_charp chunkdata;
1890 png_size_t slength, prefix_len, data_len;
1892 png_debug(1, "in png_handle_zTXt\n");
1893 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1894 png_error(png_ptr, "Missing IHDR before zTXt");
1896 if (png_ptr->mode & PNG_HAVE_IDAT)
1897 png_ptr->mode |= PNG_AFTER_IDAT;
1899 #ifdef PNG_MAX_MALLOC_64K
1900 /* We will no doubt have problems with chunks even half this size, but
1901 there is no hard and fast rule to tell us where to stop. */
1902 if (length > (png_uint_32)65535L)
1904 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1905 png_crc_finish(png_ptr, length);
1910 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1911 slength = (png_size_t)length;
1912 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1913 if (png_crc_finish(png_ptr, 0))
1915 png_free(png_ptr, chunkdata);
1919 chunkdata[slength] = 0x00;
1921 for (text = chunkdata; *text; text++)
1924 /* zTXt must have some text after the chunkdataword */
1925 if (text == chunkdata + slength)
1927 comp_type = PNG_TEXT_COMPRESSION_NONE;
1928 png_warning(png_ptr, "Zero length zTXt chunk");
1932 comp_type = *(++text);
1933 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
1935 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
1936 comp_type = PNG_TEXT_COMPRESSION_zTXt;
1938 text++; /* skip the compression_method byte */
1940 prefix_len = text - chunkdata;
1942 chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
1943 (png_size_t)length, prefix_len, &data_len);
1945 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1946 text_ptr->compression = comp_type;
1947 text_ptr->key = chunkdata;
1948 #ifdef PNG_iTXt_SUPPORTED
1949 text_ptr->lang = NULL;
1950 text_ptr->lang_key = NULL;
1951 text_ptr->itxt_length = 0;
1953 text_ptr->text = chunkdata + prefix_len;
1954 text_ptr->text_length = data_len;
1956 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1958 png_free(png_ptr, text_ptr);
1959 png_free(png_ptr, chunkdata);
1963 #if defined(PNG_READ_iTXt_SUPPORTED)
1964 /* note: this does not correctly handle chunks that are > 64K under DOS */
1966 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1969 png_charp chunkdata;
1970 png_charp key, lang, text, lang_key;
1973 png_size_t slength, prefix_len, data_len;
1975 png_debug(1, "in png_handle_iTXt\n");
1977 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1978 png_error(png_ptr, "Missing IHDR before iTXt");
1980 if (png_ptr->mode & PNG_HAVE_IDAT)
1981 png_ptr->mode |= PNG_AFTER_IDAT;
1983 #ifdef PNG_MAX_MALLOC_64K
1984 /* We will no doubt have problems with chunks even half this size, but
1985 there is no hard and fast rule to tell us where to stop. */
1986 if (length > (png_uint_32)65535L)
1988 png_warning(png_ptr,"iTXt chunk too large to fit in memory");
1989 png_crc_finish(png_ptr, length);
1994 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1995 slength = (png_size_t)length;
1996 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1997 if (png_crc_finish(png_ptr, 0))
1999 png_free(png_ptr, chunkdata);
2003 chunkdata[slength] = 0x00;
2005 for (lang = chunkdata; *lang; lang++)
2007 lang++; /* skip NUL separator */
2009 /* iTXt must have a language tag (possibly empty), two compression bytes,
2010 translated keyword (possibly empty), and possibly some text after the
2013 if (lang >= chunkdata + slength)
2015 comp_flag = PNG_TEXT_COMPRESSION_NONE;
2016 png_warning(png_ptr, "Zero length iTXt chunk");
2020 comp_flag = *lang++;
2021 comp_type = *lang++;
2024 for (lang_key = lang; *lang_key; lang_key++)
2026 lang_key++; /* skip NUL separator */
2028 for (text = lang_key; *text; text++)
2030 text++; /* skip NUL separator */
2032 prefix_len = text - chunkdata;
2036 chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
2037 (size_t)length, prefix_len, &data_len);
2039 data_len=png_strlen(chunkdata + prefix_len);
2040 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
2041 text_ptr->compression = (int)comp_flag + 1;
2042 text_ptr->lang_key = chunkdata+(lang_key-key);
2043 text_ptr->lang = chunkdata+(lang-key);
2044 text_ptr->itxt_length = data_len;
2045 text_ptr->text_length = 0;
2046 text_ptr->key = chunkdata;
2047 text_ptr->text = chunkdata + prefix_len;
2049 png_set_text(png_ptr, info_ptr, text_ptr, 1);
2051 png_free(png_ptr, text_ptr);
2052 png_free(png_ptr, chunkdata);
2056 /* This function is called when we haven't found a handler for a
2057 chunk. If there isn't a problem with the chunk itself (ie bad
2058 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2059 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2060 case it will be saved away to be written out later. */
2062 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2064 png_uint_32 skip = 0;
2066 png_debug(1, "in png_handle_unknown\n");
2068 if (png_ptr->mode & PNG_HAVE_IDAT)
2070 #ifdef PNG_USE_LOCAL_ARRAYS
2073 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2074 png_ptr->mode |= PNG_AFTER_IDAT;
2077 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
2079 if (!(png_ptr->chunk_name[0] & 0x20))
2081 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2082 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2084 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2085 && png_ptr->read_user_chunk_fn == (png_user_chunk_ptr)NULL
2089 png_chunk_error(png_ptr, "unknown critical chunk");
2092 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2093 if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
2095 png_unknown_chunk chunk;
2097 #ifdef PNG_MAX_MALLOC_64K
2098 if (length > (png_uint_32)65535L)
2100 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2101 skip = length - (png_uint_32)65535L;
2102 length = (png_uint_32)65535L;
2105 strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
2106 chunk.data = (png_bytep)png_malloc(png_ptr, length);
2107 png_crc_read(png_ptr, chunk.data, length);
2108 chunk.size = length;
2109 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2110 if(png_ptr->read_user_chunk_fn != (png_user_chunk_ptr)NULL)
2112 /* callback to user unknown chunk handler */
2113 if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
2115 if (!(png_ptr->chunk_name[0] & 0x20))
2116 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2117 HANDLE_CHUNK_ALWAYS)
2118 png_chunk_error(png_ptr, "unknown critical chunk");
2119 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2124 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2125 png_free(png_ptr, chunk.data);
2131 png_crc_finish(png_ptr, skip);
2133 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2134 if (info_ptr == NULL)
2135 /* quiet compiler warnings about unused info_ptr */ ;
2139 /* This function is called to verify that a chunk name is valid.
2140 This function can't have the "critical chunk check" incorporated
2141 into it, since in the future we will need to be able to call user
2142 functions to handle unknown critical chunks after we check that
2143 the chunk name itself is valid. */
2145 #define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
2148 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2150 png_debug(1, "in png_check_chunk_name\n");
2151 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2152 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2154 png_chunk_error(png_ptr, "invalid chunk type");
2158 /* Combines the row recently read in with the existing pixels in the
2159 row. This routine takes care of alpha and transparency if requested.
2160 This routine also handles the two methods of progressive display
2161 of interlaced images, depending on the mask value.
2162 The mask value describes which pixels are to be combined with
2163 the row. The pattern always repeats every 8 pixels, so just 8
2164 bits are needed. A one indicates the pixel is to be combined,
2165 a zero indicates the pixel is to be skipped. This is in addition
2166 to any alpha or transparency value associated with the pixel. If
2167 you want all pixels to be combined, pass 0xff (255) in mask. */
2168 #ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
2170 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2172 png_debug(1,"in png_combine_row\n");
2175 png_memcpy(row, png_ptr->row_buf + 1,
2176 (png_size_t)((png_ptr->width *
2177 png_ptr->row_info.pixel_depth + 7) >> 3));
2181 switch (png_ptr->row_info.pixel_depth)
2185 png_bytep sp = png_ptr->row_buf + 1;
2187 int s_inc, s_start, s_end;
2191 png_uint_32 row_width = png_ptr->width;
2193 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2194 if (png_ptr->transformations & PNG_PACKSWAP)
2210 for (i = 0; i < row_width; i++)
2216 value = (*sp >> shift) & 0x01;
2217 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2218 *dp |= (png_byte)(value << shift);
2239 png_bytep sp = png_ptr->row_buf + 1;
2241 int s_start, s_end, s_inc;
2245 png_uint_32 row_width = png_ptr->width;
2248 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2249 if (png_ptr->transformations & PNG_PACKSWAP)
2265 for (i = 0; i < row_width; i++)
2269 value = (*sp >> shift) & 0x03;
2270 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2271 *dp |= (png_byte)(value << shift);
2291 png_bytep sp = png_ptr->row_buf + 1;
2293 int s_start, s_end, s_inc;
2297 png_uint_32 row_width = png_ptr->width;
2300 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2301 if (png_ptr->transformations & PNG_PACKSWAP)
2316 for (i = 0; i < row_width; i++)
2320 value = (*sp >> shift) & 0xf;
2321 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2322 *dp |= (png_byte)(value << shift);
2342 png_bytep sp = png_ptr->row_buf + 1;
2344 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2346 png_uint_32 row_width = png_ptr->width;
2350 for (i = 0; i < row_width; i++)
2354 png_memcpy(dp, sp, pixel_bytes);
2370 #endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
2372 #ifdef PNG_READ_INTERLACING_SUPPORTED
2373 #ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */
2375 png_do_read_interlace(png_structp png_ptr)
2377 png_row_infop row_info = &(png_ptr->row_info);
2378 png_bytep row = png_ptr->row_buf + 1;
2379 int pass = png_ptr->pass;
2380 png_uint_32 transformations = png_ptr->transformations;
2381 #ifdef PNG_USE_LOCAL_ARRAYS
2382 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2383 /* offset to next interlace block */
2384 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2387 png_debug(1,"in png_do_read_interlace (stock C version)\n");
2388 if (row != NULL && row_info != NULL)
2390 png_uint_32 final_width;
2392 final_width = row_info->width * png_pass_inc[pass];
2394 switch (row_info->pixel_depth)
2398 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2399 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2401 int s_start, s_end, s_inc;
2402 int jstop = png_pass_inc[pass];
2407 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2408 if (transformations & PNG_PACKSWAP)
2410 sshift = (int)((row_info->width + 7) & 0x07);
2411 dshift = (int)((final_width + 7) & 0x07);
2419 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2420 dshift = 7 - (int)((final_width + 7) & 0x07);
2426 for (i = 0; i < row_info->width; i++)
2428 v = (png_byte)((*sp >> sshift) & 0x01);
2429 for (j = 0; j < jstop; j++)
2431 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2432 *dp |= (png_byte)(v << dshift);
2433 if (dshift == s_end)
2441 if (sshift == s_end)
2453 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2454 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2456 int s_start, s_end, s_inc;
2457 int jstop = png_pass_inc[pass];
2460 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2461 if (transformations & PNG_PACKSWAP)
2463 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2464 dshift = (int)(((final_width + 3) & 0x03) << 1);
2472 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2473 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2479 for (i = 0; i < row_info->width; i++)
2484 v = (png_byte)((*sp >> sshift) & 0x03);
2485 for (j = 0; j < jstop; j++)
2487 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2488 *dp |= (png_byte)(v << dshift);
2489 if (dshift == s_end)
2497 if (sshift == s_end)
2509 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2510 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2512 int s_start, s_end, s_inc;
2514 int jstop = png_pass_inc[pass];
2516 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2517 if (transformations & PNG_PACKSWAP)
2519 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2520 dshift = (int)(((final_width + 1) & 0x01) << 2);
2528 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2529 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2535 for (i = 0; i < row_info->width; i++)
2537 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2540 for (j = 0; j < jstop; j++)
2542 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2543 *dp |= (png_byte)(v << dshift);
2544 if (dshift == s_end)
2552 if (sshift == s_end)
2564 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2565 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2566 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2568 int jstop = png_pass_inc[pass];
2571 for (i = 0; i < row_info->width; i++)
2576 png_memcpy(v, sp, pixel_bytes);
2577 for (j = 0; j < jstop; j++)
2579 png_memcpy(dp, v, pixel_bytes);
2587 row_info->width = final_width;
2588 row_info->rowbytes = ((final_width *
2589 (png_uint_32)row_info->pixel_depth + 7) >> 3);
2591 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2592 /* silence compiler warning */
2593 if (transformations)
2597 #endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
2598 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2600 #ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
2602 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2603 png_bytep prev_row, int filter)
2605 png_debug(1, "in png_read_filter_row\n");
2606 png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
2609 case PNG_FILTER_VALUE_NONE:
2611 case PNG_FILTER_VALUE_SUB:
2614 png_uint_32 istop = row_info->rowbytes;
2615 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2616 png_bytep rp = row + bpp;
2619 for (i = bpp; i < istop; i++)
2621 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2626 case PNG_FILTER_VALUE_UP:
2629 png_uint_32 istop = row_info->rowbytes;
2631 png_bytep pp = prev_row;
2633 for (i = 0; i < istop; i++)
2635 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2640 case PNG_FILTER_VALUE_AVG:
2644 png_bytep pp = prev_row;
2646 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2647 png_uint_32 istop = row_info->rowbytes - bpp;
2649 for (i = 0; i < bpp; i++)
2651 *rp = (png_byte)(((int)(*rp) +
2652 ((int)(*pp++) / 2 )) & 0xff);
2656 for (i = 0; i < istop; i++)
2658 *rp = (png_byte)(((int)(*rp) +
2659 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2664 case PNG_FILTER_VALUE_PAETH:
2668 png_bytep pp = prev_row;
2670 png_bytep cp = prev_row;
2671 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2672 png_uint_32 istop=row_info->rowbytes - bpp;
2674 for (i = 0; i < bpp; i++)
2676 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2680 for (i = 0; i < istop; i++) /* use leftover rp,pp */
2682 int a, b, c, pa, pb, pc, p;
2696 pa = p < 0 ? -p : p;
2697 pb = pc < 0 ? -pc : pc;
2698 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2702 if (pa <= pb && pa <= pc)
2710 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2712 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2718 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2723 #endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
2726 png_read_finish_row(png_structp png_ptr)
2728 #ifdef PNG_USE_LOCAL_ARRAYS
2729 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2731 /* start of interlace block */
2732 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2734 /* offset to next interlace block */
2735 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2737 /* start of interlace block in the y direction */
2738 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2740 /* offset to next interlace block in the y direction */
2741 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2744 png_debug(1, "in png_read_finish_row\n");
2745 png_ptr->row_number++;
2746 if (png_ptr->row_number < png_ptr->num_rows)
2749 if (png_ptr->interlaced)
2751 png_ptr->row_number = 0;
2752 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
2756 if (png_ptr->pass >= 7)
2758 png_ptr->iwidth = (png_ptr->width +
2759 png_pass_inc[png_ptr->pass] - 1 -
2760 png_pass_start[png_ptr->pass]) /
2761 png_pass_inc[png_ptr->pass];
2762 png_ptr->irowbytes = ((png_ptr->iwidth *
2763 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2765 if (!(png_ptr->transformations & PNG_INTERLACE))
2767 png_ptr->num_rows = (png_ptr->height +
2768 png_pass_yinc[png_ptr->pass] - 1 -
2769 png_pass_ystart[png_ptr->pass]) /
2770 png_pass_yinc[png_ptr->pass];
2771 if (!(png_ptr->num_rows))
2774 else /* if (png_ptr->transformations & PNG_INTERLACE) */
2776 } while (png_ptr->iwidth == 0);
2778 if (png_ptr->pass < 7)
2782 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
2784 #ifdef PNG_USE_LOCAL_ARRAYS
2790 png_ptr->zstream.next_out = (Byte *)&extra;
2791 png_ptr->zstream.avail_out = (uInt)1;
2794 if (!(png_ptr->zstream.avail_in))
2796 while (!png_ptr->idat_size)
2798 png_byte chunk_length[4];
2800 png_crc_finish(png_ptr, 0);
2802 png_read_data(png_ptr, chunk_length, 4);
2803 png_ptr->idat_size = png_get_uint_32(chunk_length);
2805 png_reset_crc(png_ptr);
2806 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2807 if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
2808 png_error(png_ptr, "Not enough image data");
2811 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2812 png_ptr->zstream.next_in = png_ptr->zbuf;
2813 if (png_ptr->zbuf_size > png_ptr->idat_size)
2814 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2815 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2816 png_ptr->idat_size -= png_ptr->zstream.avail_in;
2818 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
2819 if (ret == Z_STREAM_END)
2821 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
2823 png_error(png_ptr, "Extra compressed data");
2824 png_ptr->mode |= PNG_AFTER_IDAT;
2825 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2829 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
2830 "Decompression Error");
2832 if (!(png_ptr->zstream.avail_out))
2833 png_error(png_ptr, "Extra compressed data");
2836 png_ptr->zstream.avail_out = 0;
2839 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
2840 png_error(png_ptr, "Extra compression data");
2842 inflateReset(&png_ptr->zstream);
2844 png_ptr->mode |= PNG_AFTER_IDAT;
2848 png_read_start_row(png_structp png_ptr)
2850 #ifdef PNG_USE_LOCAL_ARRAYS
2851 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2853 /* start of interlace block */
2854 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2856 /* offset to next interlace block */
2857 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2859 /* start of interlace block in the y direction */
2860 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2862 /* offset to next interlace block in the y direction */
2863 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2866 int max_pixel_depth;
2867 png_uint_32 row_bytes;
2869 png_debug(1, "in png_read_start_row\n");
2870 png_ptr->zstream.avail_in = 0;
2871 png_init_read_transformations(png_ptr);
2872 if (png_ptr->interlaced)
2874 if (!(png_ptr->transformations & PNG_INTERLACE))
2875 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2876 png_pass_ystart[0]) / png_pass_yinc[0];
2878 png_ptr->num_rows = png_ptr->height;
2880 png_ptr->iwidth = (png_ptr->width +
2881 png_pass_inc[png_ptr->pass] - 1 -
2882 png_pass_start[png_ptr->pass]) /
2883 png_pass_inc[png_ptr->pass];
2885 row_bytes = ((png_ptr->iwidth *
2886 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2887 png_ptr->irowbytes = (png_size_t)row_bytes;
2888 if((png_uint_32)png_ptr->irowbytes != row_bytes)
2889 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
2893 png_ptr->num_rows = png_ptr->height;
2894 png_ptr->iwidth = png_ptr->width;
2895 png_ptr->irowbytes = png_ptr->rowbytes + 1;
2897 max_pixel_depth = png_ptr->pixel_depth;
2899 #if defined(PNG_READ_PACK_SUPPORTED)
2900 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
2901 max_pixel_depth = 8;
2904 #if defined(PNG_READ_EXPAND_SUPPORTED)
2905 if (png_ptr->transformations & PNG_EXPAND)
2907 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2909 if (png_ptr->num_trans)
2910 max_pixel_depth = 32;
2912 max_pixel_depth = 24;
2914 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2916 if (max_pixel_depth < 8)
2917 max_pixel_depth = 8;
2918 if (png_ptr->num_trans)
2919 max_pixel_depth *= 2;
2921 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2923 if (png_ptr->num_trans)
2925 max_pixel_depth *= 4;
2926 max_pixel_depth /= 3;
2932 #if defined(PNG_READ_FILLER_SUPPORTED)
2933 if (png_ptr->transformations & (PNG_FILLER))
2935 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2936 max_pixel_depth = 32;
2937 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2939 if (max_pixel_depth <= 8)
2940 max_pixel_depth = 16;
2942 max_pixel_depth = 32;
2944 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2946 if (max_pixel_depth <= 32)
2947 max_pixel_depth = 32;
2949 max_pixel_depth = 64;
2954 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2955 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
2958 #if defined(PNG_READ_EXPAND_SUPPORTED)
2959 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
2961 #if defined(PNG_READ_FILLER_SUPPORTED)
2962 (png_ptr->transformations & (PNG_FILLER)) ||
2964 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2966 if (max_pixel_depth <= 16)
2967 max_pixel_depth = 32;
2969 max_pixel_depth = 64;
2973 if (max_pixel_depth <= 8)
2975 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2976 max_pixel_depth = 32;
2978 max_pixel_depth = 24;
2980 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2981 max_pixel_depth = 64;
2983 max_pixel_depth = 48;
2988 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
2989 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
2990 if(png_ptr->transformations & PNG_USER_TRANSFORM)
2992 int user_pixel_depth=png_ptr->user_transform_depth*
2993 png_ptr->user_transform_channels;
2994 if(user_pixel_depth > max_pixel_depth)
2995 max_pixel_depth=user_pixel_depth;
2999 /* align the width on the next larger 8 pixels. Mainly used
3001 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
3002 /* calculate the maximum bytes needed, adding a byte and a pixel
3003 for safety's sake */
3004 row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
3005 1 + ((max_pixel_depth + 7) >> 3);
3006 #ifdef PNG_MAX_MALLOC_64K
3007 if (row_bytes > (png_uint_32)65536L)
3008 png_error(png_ptr, "This image requires a row greater than 64KB");
3010 png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, row_bytes);
3012 #ifdef PNG_MAX_MALLOC_64K
3013 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
3014 png_error(png_ptr, "This image requires a row greater than 64KB");
3016 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3017 png_ptr->rowbytes + 1));
3019 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
3021 png_debug1(3, "width = %lu,\n", png_ptr->width);
3022 png_debug1(3, "height = %lu,\n", png_ptr->height);
3023 png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
3024 png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
3025 png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
3026 png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
3028 png_ptr->flags |= PNG_FLAG_ROW_INIT;