2 /* pngrutil.c - utilities to read a PNG file
4 * libpng 1.2.0 - September 1, 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 + (png_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];
336 /* set internal variables */
337 png_ptr->width = width;
338 png_ptr->height = height;
339 png_ptr->bit_depth = (png_byte)bit_depth;
340 png_ptr->interlaced = (png_byte)interlace_type;
341 png_ptr->color_type = (png_byte)color_type;
342 #if defined(PNG_MNG_FEATURES_SUPPORTED)
343 png_ptr->filter_type = (png_byte)filter_type;
346 /* find number of channels */
347 switch (png_ptr->color_type)
349 case PNG_COLOR_TYPE_GRAY:
350 case PNG_COLOR_TYPE_PALETTE:
351 png_ptr->channels = 1;
353 case PNG_COLOR_TYPE_RGB:
354 png_ptr->channels = 3;
356 case PNG_COLOR_TYPE_GRAY_ALPHA:
357 png_ptr->channels = 2;
359 case PNG_COLOR_TYPE_RGB_ALPHA:
360 png_ptr->channels = 4;
364 /* set up other useful info */
365 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
367 png_ptr->rowbytes = ((png_ptr->width *
368 (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
369 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
370 png_debug1(3,"channels = %d\n", png_ptr->channels);
371 png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
372 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
373 color_type, interlace_type, compression_type, filter_type);
376 /* read and check the palette */
378 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
380 png_color palette[PNG_MAX_PALETTE_LENGTH];
382 #ifndef PNG_NO_POINTER_INDEXING
386 png_debug(1, "in png_handle_PLTE\n");
388 if (!(png_ptr->mode & PNG_HAVE_IHDR))
389 png_error(png_ptr, "Missing IHDR before PLTE");
390 else if (png_ptr->mode & PNG_HAVE_IDAT)
392 png_warning(png_ptr, "Invalid PLTE after IDAT");
393 png_crc_finish(png_ptr, length);
396 else if (png_ptr->mode & PNG_HAVE_PLTE)
397 png_error(png_ptr, "Duplicate PLTE chunk");
399 png_ptr->mode |= PNG_HAVE_PLTE;
401 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
404 "Ignoring PLTE chunk in grayscale PNG");
405 png_crc_finish(png_ptr, length);
408 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
409 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
411 png_crc_finish(png_ptr, length);
416 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
418 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
420 png_warning(png_ptr, "Invalid palette chunk");
421 png_crc_finish(png_ptr, length);
426 png_error(png_ptr, "Invalid palette chunk");
430 num = (int)length / 3;
432 #ifndef PNG_NO_POINTER_INDEXING
433 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
437 png_crc_read(png_ptr, buf, 3);
438 pal_ptr->red = buf[0];
439 pal_ptr->green = buf[1];
440 pal_ptr->blue = buf[2];
443 for (i = 0; i < num; i++)
447 png_crc_read(png_ptr, buf, 3);
448 /* don't depend upon png_color being any order */
449 palette[i].red = buf[0];
450 palette[i].green = buf[1];
451 palette[i].blue = buf[2];
455 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
456 whatever the normal CRC configuration tells us. However, if we
457 have an RGB image, the PLTE can be considered ancillary, so
458 we will act as though it is. */
459 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
460 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
463 png_crc_finish(png_ptr, 0);
465 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
466 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
468 /* If we don't want to use the data from an ancillary chunk,
469 we have two options: an error abort, or a warning and we
470 ignore the data in this chunk (which should be OK, since
471 it's considered ancillary for a RGB or RGBA image). */
472 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
474 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
476 png_chunk_error(png_ptr, "CRC error");
480 png_chunk_warning(png_ptr, "CRC error");
484 /* Otherwise, we (optionally) emit a warning and use the chunk. */
485 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
487 png_chunk_warning(png_ptr, "CRC error");
492 png_set_PLTE(png_ptr, info_ptr, palette, num);
494 #if defined(PNG_READ_tRNS_SUPPORTED)
495 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
497 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
499 if (png_ptr->num_trans > (png_uint_16)num)
501 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
502 png_ptr->num_trans = (png_uint_16)num;
504 if (info_ptr->num_trans > (png_uint_16)num)
506 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
507 info_ptr->num_trans = (png_uint_16)num;
516 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
518 png_debug(1, "in png_handle_IEND\n");
520 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
522 png_error(png_ptr, "No image in file");
524 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
527 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
531 png_warning(png_ptr, "Incorrect IEND chunk length");
533 png_crc_finish(png_ptr, length);
536 #if defined(PNG_READ_gAMA_SUPPORTED)
538 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
540 png_fixed_point igamma;
541 #ifdef PNG_FLOATING_POINT_SUPPORTED
546 png_debug(1, "in png_handle_gAMA\n");
548 if (!(png_ptr->mode & PNG_HAVE_IHDR))
549 png_error(png_ptr, "Missing IHDR before gAMA");
550 else if (png_ptr->mode & PNG_HAVE_IDAT)
552 png_warning(png_ptr, "Invalid gAMA after IDAT");
553 png_crc_finish(png_ptr, length);
556 else if (png_ptr->mode & PNG_HAVE_PLTE)
557 /* Should be an error, but we can cope with it */
558 png_warning(png_ptr, "Out of place gAMA chunk");
560 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
561 #if defined(PNG_READ_sRGB_SUPPORTED)
562 && !(info_ptr->valid & PNG_INFO_sRGB)
566 png_warning(png_ptr, "Duplicate gAMA chunk");
567 png_crc_finish(png_ptr, length);
573 png_warning(png_ptr, "Incorrect gAMA chunk length");
574 png_crc_finish(png_ptr, length);
578 png_crc_read(png_ptr, buf, 4);
579 if (png_crc_finish(png_ptr, 0))
582 igamma = (png_fixed_point)png_get_uint_32(buf);
583 /* check for zero gamma */
587 "Ignoring gAMA chunk with gamma=0");
591 #if defined(PNG_READ_sRGB_SUPPORTED)
592 if (info_ptr->valid & PNG_INFO_sRGB)
593 if(igamma < 45000L || igamma > 46000L)
596 "Ignoring incorrect gAMA value when sRGB is also present");
597 #ifndef PNG_NO_CONSOLE_IO
598 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
602 #endif /* PNG_READ_sRGB_SUPPORTED */
604 #ifdef PNG_FLOATING_POINT_SUPPORTED
605 file_gamma = (float)igamma / (float)100000.0;
606 # ifdef PNG_READ_GAMMA_SUPPORTED
607 png_ptr->gamma = file_gamma;
609 png_set_gAMA(png_ptr, info_ptr, file_gamma);
611 #ifdef PNG_FIXED_POINT_SUPPORTED
612 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
617 #if defined(PNG_READ_sBIT_SUPPORTED)
619 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
624 png_debug(1, "in png_handle_sBIT\n");
626 buf[0] = buf[1] = buf[2] = buf[3] = 0;
628 if (!(png_ptr->mode & PNG_HAVE_IHDR))
629 png_error(png_ptr, "Missing IHDR before sBIT");
630 else if (png_ptr->mode & PNG_HAVE_IDAT)
632 png_warning(png_ptr, "Invalid sBIT after IDAT");
633 png_crc_finish(png_ptr, length);
636 else if (png_ptr->mode & PNG_HAVE_PLTE)
638 /* Should be an error, but we can cope with it */
639 png_warning(png_ptr, "Out of place sBIT chunk");
641 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
643 png_warning(png_ptr, "Duplicate sBIT chunk");
644 png_crc_finish(png_ptr, length);
648 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
651 truelen = (png_size_t)png_ptr->channels;
653 if (length != truelen)
655 png_warning(png_ptr, "Incorrect sBIT chunk length");
656 png_crc_finish(png_ptr, length);
660 png_crc_read(png_ptr, buf, truelen);
661 if (png_crc_finish(png_ptr, 0))
664 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
666 png_ptr->sig_bit.red = buf[0];
667 png_ptr->sig_bit.green = buf[1];
668 png_ptr->sig_bit.blue = buf[2];
669 png_ptr->sig_bit.alpha = buf[3];
673 png_ptr->sig_bit.gray = buf[0];
674 png_ptr->sig_bit.red = buf[0];
675 png_ptr->sig_bit.green = buf[0];
676 png_ptr->sig_bit.blue = buf[0];
677 png_ptr->sig_bit.alpha = buf[1];
679 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
683 #if defined(PNG_READ_cHRM_SUPPORTED)
685 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
688 #ifdef PNG_FLOATING_POINT_SUPPORTED
689 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
691 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
692 int_y_green, int_x_blue, int_y_blue;
694 png_debug(1, "in png_handle_cHRM\n");
696 if (!(png_ptr->mode & PNG_HAVE_IHDR))
697 png_error(png_ptr, "Missing IHDR before cHRM");
698 else if (png_ptr->mode & PNG_HAVE_IDAT)
700 png_warning(png_ptr, "Invalid cHRM after IDAT");
701 png_crc_finish(png_ptr, length);
704 else if (png_ptr->mode & PNG_HAVE_PLTE)
705 /* Should be an error, but we can cope with it */
706 png_warning(png_ptr, "Missing PLTE before cHRM");
708 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
709 #if defined(PNG_READ_sRGB_SUPPORTED)
710 && !(info_ptr->valid & PNG_INFO_sRGB)
714 png_warning(png_ptr, "Duplicate cHRM chunk");
715 png_crc_finish(png_ptr, length);
721 png_warning(png_ptr, "Incorrect cHRM chunk length");
722 png_crc_finish(png_ptr, length);
726 png_crc_read(png_ptr, buf, 4);
727 int_x_white = (png_fixed_point)png_get_uint_32(buf);
729 png_crc_read(png_ptr, buf, 4);
730 int_y_white = (png_fixed_point)png_get_uint_32(buf);
732 if (int_x_white > 80000L || int_y_white > 80000L ||
733 int_x_white + int_y_white > 100000L)
735 png_warning(png_ptr, "Invalid cHRM white point");
736 png_crc_finish(png_ptr, 24);
740 png_crc_read(png_ptr, buf, 4);
741 int_x_red = (png_fixed_point)png_get_uint_32(buf);
743 png_crc_read(png_ptr, buf, 4);
744 int_y_red = (png_fixed_point)png_get_uint_32(buf);
746 if (int_x_red > 80000L || int_y_red > 80000L ||
747 int_x_red + int_y_red > 100000L)
749 png_warning(png_ptr, "Invalid cHRM red point");
750 png_crc_finish(png_ptr, 16);
754 png_crc_read(png_ptr, buf, 4);
755 int_x_green = (png_fixed_point)png_get_uint_32(buf);
757 png_crc_read(png_ptr, buf, 4);
758 int_y_green = (png_fixed_point)png_get_uint_32(buf);
760 if (int_x_green > 80000L || int_y_green > 80000L ||
761 int_x_green + int_y_green > 100000L)
763 png_warning(png_ptr, "Invalid cHRM green point");
764 png_crc_finish(png_ptr, 8);
768 png_crc_read(png_ptr, buf, 4);
769 int_x_blue = (png_fixed_point)png_get_uint_32(buf);
771 png_crc_read(png_ptr, buf, 4);
772 int_y_blue = (png_fixed_point)png_get_uint_32(buf);
774 if (int_x_blue > 80000L || int_y_blue > 80000L ||
775 int_x_blue + int_y_blue > 100000L)
777 png_warning(png_ptr, "Invalid cHRM blue point");
778 png_crc_finish(png_ptr, 0);
781 #ifdef PNG_FLOATING_POINT_SUPPORTED
782 white_x = (float)int_x_white / (float)100000.0;
783 white_y = (float)int_y_white / (float)100000.0;
784 red_x = (float)int_x_red / (float)100000.0;
785 red_y = (float)int_y_red / (float)100000.0;
786 green_x = (float)int_x_green / (float)100000.0;
787 green_y = (float)int_y_green / (float)100000.0;
788 blue_x = (float)int_x_blue / (float)100000.0;
789 blue_y = (float)int_y_blue / (float)100000.0;
792 #if defined(PNG_READ_sRGB_SUPPORTED)
793 if (info_ptr->valid & PNG_INFO_sRGB)
795 if (abs(int_x_white - 31270L) > 1000 ||
796 abs(int_y_white - 32900L) > 1000 ||
797 abs(int_x_red - 64000L) > 1000 ||
798 abs(int_y_red - 33000L) > 1000 ||
799 abs(int_x_green - 30000L) > 1000 ||
800 abs(int_y_green - 60000L) > 1000 ||
801 abs(int_x_blue - 15000L) > 1000 ||
802 abs(int_y_blue - 6000L) > 1000)
806 "Ignoring incorrect cHRM value when sRGB is also present");
807 #ifndef PNG_NO_CONSOLE_IO
808 #ifdef PNG_FLOATING_POINT_SUPPORTED
809 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
810 white_x, white_y, red_x, red_y);
811 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
812 green_x, green_y, blue_x, blue_y);
814 fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
815 int_x_white, int_y_white, int_x_red, int_y_red);
816 fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
817 int_x_green, int_y_green, int_x_blue, int_y_blue);
819 #endif /* PNG_NO_CONSOLE_IO */
821 png_crc_finish(png_ptr, 0);
824 #endif /* PNG_READ_sRGB_SUPPORTED */
826 #ifdef PNG_FLOATING_POINT_SUPPORTED
827 png_set_cHRM(png_ptr, info_ptr,
828 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
830 #ifdef PNG_FIXED_POINT_SUPPORTED
831 png_set_cHRM_fixed(png_ptr, info_ptr,
832 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
833 int_y_green, int_x_blue, int_y_blue);
835 if (png_crc_finish(png_ptr, 0))
840 #if defined(PNG_READ_sRGB_SUPPORTED)
842 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
847 png_debug(1, "in png_handle_sRGB\n");
849 if (!(png_ptr->mode & PNG_HAVE_IHDR))
850 png_error(png_ptr, "Missing IHDR before sRGB");
851 else if (png_ptr->mode & PNG_HAVE_IDAT)
853 png_warning(png_ptr, "Invalid sRGB after IDAT");
854 png_crc_finish(png_ptr, length);
857 else if (png_ptr->mode & PNG_HAVE_PLTE)
858 /* Should be an error, but we can cope with it */
859 png_warning(png_ptr, "Out of place sRGB chunk");
861 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
863 png_warning(png_ptr, "Duplicate sRGB chunk");
864 png_crc_finish(png_ptr, length);
870 png_warning(png_ptr, "Incorrect sRGB chunk length");
871 png_crc_finish(png_ptr, length);
875 png_crc_read(png_ptr, buf, 1);
876 if (png_crc_finish(png_ptr, 0))
880 /* check for bad intent */
881 if (intent >= PNG_sRGB_INTENT_LAST)
883 png_warning(png_ptr, "Unknown sRGB intent");
887 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
888 if ((info_ptr->valid & PNG_INFO_gAMA))
891 #ifdef PNG_FIXED_POINT_SUPPORTED
892 igamma=(int)info_ptr->int_gamma;
894 # ifdef PNG_FLOATING_POINT_SUPPORTED
895 igamma=(int)(info_ptr->gamma * 100000.);
898 #if 0 && defined(PNG_cHRM_SUPPORTED) && !defined(PNG_FIXED_POINT_SUPPORTED)
899 /* We need to define these here because they aren't in png.h */
900 png_fixed_point int_x_white;
901 png_fixed_point int_y_white;
902 png_fixed_point int_x_red;
903 png_fixed_point int_y_red;
904 png_fixed_point int_x_green;
905 png_fixed_point int_y_green;
906 png_fixed_point int_x_blue;
907 png_fixed_point int_y_blue;
909 if(igamma < 45000L || igamma > 46000L)
912 "Ignoring incorrect gAMA value when sRGB is also present");
913 #ifndef PNG_NO_CONSOLE_IO
914 # ifdef PNG_FIXED_POINT_SUPPORTED
915 fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
917 # ifdef PNG_FLOATING_POINT_SUPPORTED
918 fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
924 #endif /* PNG_READ_gAMA_SUPPORTED */
926 #ifdef PNG_READ_cHRM_SUPPORTED
927 #ifdef PNG_FIXED_POINT_SUPPORTED
928 if (info_ptr->valid & PNG_INFO_cHRM)
929 if (abs(info_ptr->int_x_white - 31270L) > 1000 ||
930 abs(info_ptr->int_y_white - 32900L) > 1000 ||
931 abs(info_ptr->int_x_red - 64000L) > 1000 ||
932 abs(info_ptr->int_y_red - 33000L) > 1000 ||
933 abs(info_ptr->int_x_green - 30000L) > 1000 ||
934 abs(info_ptr->int_y_green - 60000L) > 1000 ||
935 abs(info_ptr->int_x_blue - 15000L) > 1000 ||
936 abs(info_ptr->int_y_blue - 6000L) > 1000)
939 "Ignoring incorrect cHRM value when sRGB is also present");
941 #endif /* PNG_FIXED_POINT_SUPPORTED */
942 #endif /* PNG_READ_cHRM_SUPPORTED */
944 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
946 #endif /* PNG_READ_sRGB_SUPPORTED */
948 #if defined(PNG_READ_iCCP_SUPPORTED)
950 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
951 /* Note: this does not properly handle chunks that are > 64K under DOS */
954 png_byte compression_type;
956 png_uint_32 skip = 0;
957 png_uint_32 profile_size = 0;
958 png_uint_32 profile_length = 0;
959 png_size_t slength, prefix_length, data_length;
961 png_debug(1, "in png_handle_iCCP\n");
963 if (!(png_ptr->mode & PNG_HAVE_IHDR))
964 png_error(png_ptr, "Missing IHDR before iCCP");
965 else if (png_ptr->mode & PNG_HAVE_IDAT)
967 png_warning(png_ptr, "Invalid iCCP after IDAT");
968 png_crc_finish(png_ptr, length);
971 else if (png_ptr->mode & PNG_HAVE_PLTE)
972 /* Should be an error, but we can cope with it */
973 png_warning(png_ptr, "Out of place iCCP chunk");
975 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
977 png_warning(png_ptr, "Duplicate iCCP chunk");
978 png_crc_finish(png_ptr, length);
982 #ifdef PNG_MAX_MALLOC_64K
983 if (length > (png_uint_32)65535L)
985 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
986 skip = length - (png_uint_32)65535L;
987 length = (png_uint_32)65535L;
991 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
992 slength = (png_size_t)length;
993 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
995 if (png_crc_finish(png_ptr, skip))
997 png_free(png_ptr, chunkdata);
1001 chunkdata[slength] = 0x00;
1003 for (profile = chunkdata; *profile; profile++)
1004 /* empty loop to find end of name */ ;
1008 /* there should be at least one zero (the compression type byte)
1009 following the separator, and we should be on it */
1010 if ( profile >= chunkdata + slength)
1012 png_free(png_ptr, chunkdata);
1013 png_warning(png_ptr, "Malformed iCCP chunk");
1017 /* compression_type should always be zero */
1018 compression_type = *profile++;
1019 if (compression_type)
1021 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1022 compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1026 prefix_length = profile - chunkdata;
1027 chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
1028 slength, prefix_length, &data_length);
1030 profile_length = data_length - prefix_length;
1032 if ( profile_length < 4)
1034 png_free(png_ptr, chunkdata);
1035 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1039 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1040 profile_size = ((*(chunkdata+prefix_length))<<24) |
1041 ((*(chunkdata+prefix_length+1))<<16) |
1042 ((*(chunkdata+prefix_length+2))<< 8) |
1043 ((*(chunkdata+prefix_length+3)) );
1045 if(profile_size < profile_length)
1046 profile_length = profile_size;
1048 if(profile_size > profile_length)
1050 png_free(png_ptr, chunkdata);
1051 png_warning(png_ptr, "Ignoring truncated iCCP profile.\n");
1055 png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
1056 chunkdata + prefix_length, profile_length);
1057 png_free(png_ptr, chunkdata);
1059 #endif /* PNG_READ_iCCP_SUPPORTED */
1061 #if defined(PNG_READ_sPLT_SUPPORTED)
1063 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1064 /* Note: this does not properly handle chunks that are > 64K under DOS */
1066 png_bytep chunkdata;
1067 png_bytep entry_start;
1068 png_sPLT_t new_palette;
1069 #ifdef PNG_NO_POINTER_INDEXING
1072 int data_length, entry_size, i;
1073 png_uint_32 skip = 0;
1076 png_debug(1, "in png_handle_sPLT\n");
1078 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1079 png_error(png_ptr, "Missing IHDR before sPLT");
1080 else if (png_ptr->mode & PNG_HAVE_IDAT)
1082 png_warning(png_ptr, "Invalid sPLT after IDAT");
1083 png_crc_finish(png_ptr, length);
1087 #ifdef PNG_MAX_MALLOC_64K
1088 if (length > (png_uint_32)65535L)
1090 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1091 skip = length - (png_uint_32)65535L;
1092 length = (png_uint_32)65535L;
1096 chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
1097 slength = (png_size_t)length;
1098 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1100 if (png_crc_finish(png_ptr, skip))
1102 png_free(png_ptr, chunkdata);
1106 chunkdata[slength] = 0x00;
1108 for (entry_start = chunkdata; *entry_start; entry_start++)
1109 /* empty loop to find end of name */ ;
1112 /* a sample depth should follow the separator, and we should be on it */
1113 if (entry_start > chunkdata + slength)
1115 png_free(png_ptr, chunkdata);
1116 png_warning(png_ptr, "malformed sPLT chunk");
1120 new_palette.depth = *entry_start++;
1121 entry_size = (new_palette.depth == 8 ? 6 : 10);
1122 data_length = (slength - (entry_start - chunkdata));
1124 /* integrity-check the data length */
1125 if (data_length % entry_size)
1127 png_free(png_ptr, chunkdata);
1128 png_warning(png_ptr, "sPLT chunk has bad length");
1132 new_palette.nentries = data_length / entry_size;
1133 new_palette.entries = (png_sPLT_entryp)png_malloc(
1134 png_ptr, new_palette.nentries * sizeof(png_sPLT_entry));
1136 #ifndef PNG_NO_POINTER_INDEXING
1137 for (i = 0; i < new_palette.nentries; i++)
1139 png_sPLT_entryp pp = new_palette.entries + i;
1141 if (new_palette.depth == 8)
1143 pp->red = *entry_start++;
1144 pp->green = *entry_start++;
1145 pp->blue = *entry_start++;
1146 pp->alpha = *entry_start++;
1150 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1151 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1152 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1153 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1155 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1158 pp = new_palette.entries;
1159 for (i = 0; i < new_palette.nentries; i++)
1162 if (new_palette.depth == 8)
1164 pp[i].red = *entry_start++;
1165 pp[i].green = *entry_start++;
1166 pp[i].blue = *entry_start++;
1167 pp[i].alpha = *entry_start++;
1171 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1172 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1173 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1174 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1176 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1180 /* discard all chunk data except the name and stash that */
1181 new_palette.name = (png_charp)chunkdata;
1183 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1185 png_free(png_ptr, chunkdata);
1186 png_free(png_ptr, new_palette.entries);
1188 #endif /* PNG_READ_sPLT_SUPPORTED */
1190 #if defined(PNG_READ_tRNS_SUPPORTED)
1192 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1194 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1196 png_debug(1, "in png_handle_tRNS\n");
1198 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1199 png_error(png_ptr, "Missing IHDR before tRNS");
1200 else if (png_ptr->mode & PNG_HAVE_IDAT)
1202 png_warning(png_ptr, "Invalid tRNS after IDAT");
1203 png_crc_finish(png_ptr, length);
1206 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1208 png_warning(png_ptr, "Duplicate tRNS chunk");
1209 png_crc_finish(png_ptr, length);
1213 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1215 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1217 /* Should be an error, but we can cope with it */
1218 png_warning(png_ptr, "Missing PLTE before tRNS");
1220 else if (length > (png_uint_32)png_ptr->num_palette)
1222 png_warning(png_ptr, "Incorrect tRNS chunk length");
1223 png_crc_finish(png_ptr, length);
1228 png_warning(png_ptr, "Zero length tRNS chunk");
1229 png_crc_finish(png_ptr, length);
1233 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1234 png_ptr->num_trans = (png_uint_16)length;
1236 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1242 png_warning(png_ptr, "Incorrect tRNS chunk length");
1243 png_crc_finish(png_ptr, length);
1247 png_crc_read(png_ptr, buf, (png_size_t)length);
1248 png_ptr->num_trans = 1;
1249 png_ptr->trans_values.red = png_get_uint_16(buf);
1250 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1251 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1253 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1259 png_warning(png_ptr, "Incorrect tRNS chunk length");
1260 png_crc_finish(png_ptr, length);
1264 png_crc_read(png_ptr, buf, 2);
1265 png_ptr->num_trans = 1;
1266 png_ptr->trans_values.gray = png_get_uint_16(buf);
1270 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1271 png_crc_finish(png_ptr, length);
1275 if (png_crc_finish(png_ptr, 0))
1278 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1279 &(png_ptr->trans_values));
1283 #if defined(PNG_READ_bKGD_SUPPORTED)
1285 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1290 png_debug(1, "in png_handle_bKGD\n");
1292 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1293 png_error(png_ptr, "Missing IHDR before bKGD");
1294 else if (png_ptr->mode & PNG_HAVE_IDAT)
1296 png_warning(png_ptr, "Invalid bKGD after IDAT");
1297 png_crc_finish(png_ptr, length);
1300 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1301 !(png_ptr->mode & PNG_HAVE_PLTE))
1303 png_warning(png_ptr, "Missing PLTE before bKGD");
1304 png_crc_finish(png_ptr, length);
1307 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1309 png_warning(png_ptr, "Duplicate bKGD chunk");
1310 png_crc_finish(png_ptr, length);
1314 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1316 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1321 if (length != truelen)
1323 png_warning(png_ptr, "Incorrect bKGD chunk length");
1324 png_crc_finish(png_ptr, length);
1328 png_crc_read(png_ptr, buf, truelen);
1329 if (png_crc_finish(png_ptr, 0))
1332 /* We convert the index value into RGB components so that we can allow
1333 * arbitrary RGB values for background when we have transparency, and
1334 * so it is easy to determine the RGB values of the background color
1335 * from the info_ptr struct. */
1336 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1338 png_ptr->background.index = buf[0];
1339 if(info_ptr->num_palette)
1341 if(buf[0] > info_ptr->num_palette)
1343 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1346 png_ptr->background.red =
1347 (png_uint_16)png_ptr->palette[buf[0]].red;
1348 png_ptr->background.green =
1349 (png_uint_16)png_ptr->palette[buf[0]].green;
1350 png_ptr->background.blue =
1351 (png_uint_16)png_ptr->palette[buf[0]].blue;
1354 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1356 png_ptr->background.red =
1357 png_ptr->background.green =
1358 png_ptr->background.blue =
1359 png_ptr->background.gray = png_get_uint_16(buf);
1363 png_ptr->background.red = png_get_uint_16(buf);
1364 png_ptr->background.green = png_get_uint_16(buf + 2);
1365 png_ptr->background.blue = png_get_uint_16(buf + 4);
1368 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1372 #if defined(PNG_READ_hIST_SUPPORTED)
1374 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1377 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1379 png_debug(1, "in png_handle_hIST\n");
1381 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1382 png_error(png_ptr, "Missing IHDR before hIST");
1383 else if (png_ptr->mode & PNG_HAVE_IDAT)
1385 png_warning(png_ptr, "Invalid hIST after IDAT");
1386 png_crc_finish(png_ptr, length);
1389 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1391 png_warning(png_ptr, "Missing PLTE before hIST");
1392 png_crc_finish(png_ptr, length);
1395 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1397 png_warning(png_ptr, "Duplicate hIST chunk");
1398 png_crc_finish(png_ptr, length);
1402 num = (int)length / 2 ;
1403 if (num != png_ptr->num_palette)
1405 png_warning(png_ptr, "Incorrect hIST chunk length");
1406 png_crc_finish(png_ptr, length);
1410 for (i = 0; i < num; i++)
1414 png_crc_read(png_ptr, buf, 2);
1415 readbuf[i] = png_get_uint_16(buf);
1418 if (png_crc_finish(png_ptr, 0))
1421 png_set_hIST(png_ptr, info_ptr, readbuf);
1425 #if defined(PNG_READ_pHYs_SUPPORTED)
1427 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1430 png_uint_32 res_x, res_y;
1433 png_debug(1, "in png_handle_pHYs\n");
1435 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1436 png_error(png_ptr, "Missing IHDR before pHYs");
1437 else if (png_ptr->mode & PNG_HAVE_IDAT)
1439 png_warning(png_ptr, "Invalid pHYs after IDAT");
1440 png_crc_finish(png_ptr, length);
1443 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1445 png_warning(png_ptr, "Duplicate pHYs chunk");
1446 png_crc_finish(png_ptr, length);
1452 png_warning(png_ptr, "Incorrect pHYs chunk length");
1453 png_crc_finish(png_ptr, length);
1457 png_crc_read(png_ptr, buf, 9);
1458 if (png_crc_finish(png_ptr, 0))
1461 res_x = png_get_uint_32(buf);
1462 res_y = png_get_uint_32(buf + 4);
1464 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1468 #if defined(PNG_READ_oFFs_SUPPORTED)
1470 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1473 png_int_32 offset_x, offset_y;
1476 png_debug(1, "in png_handle_oFFs\n");
1478 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1479 png_error(png_ptr, "Missing IHDR before oFFs");
1480 else if (png_ptr->mode & PNG_HAVE_IDAT)
1482 png_warning(png_ptr, "Invalid oFFs after IDAT");
1483 png_crc_finish(png_ptr, length);
1486 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1488 png_warning(png_ptr, "Duplicate oFFs chunk");
1489 png_crc_finish(png_ptr, length);
1495 png_warning(png_ptr, "Incorrect oFFs chunk length");
1496 png_crc_finish(png_ptr, length);
1500 png_crc_read(png_ptr, buf, 9);
1501 if (png_crc_finish(png_ptr, 0))
1504 offset_x = png_get_int_32(buf);
1505 offset_y = png_get_int_32(buf + 4);
1507 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1511 #if defined(PNG_READ_pCAL_SUPPORTED)
1512 /* read the pCAL chunk (described in the PNG Extensions document) */
1514 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1518 png_byte type, nparams;
1519 png_charp buf, units, endptr;
1524 png_debug(1, "in png_handle_pCAL\n");
1526 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1527 png_error(png_ptr, "Missing IHDR before pCAL");
1528 else if (png_ptr->mode & PNG_HAVE_IDAT)
1530 png_warning(png_ptr, "Invalid pCAL after IDAT");
1531 png_crc_finish(png_ptr, length);
1534 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1536 png_warning(png_ptr, "Duplicate pCAL chunk");
1537 png_crc_finish(png_ptr, length);
1541 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
1543 purpose = (png_charp)png_malloc(png_ptr, length + 1);
1544 slength = (png_size_t)length;
1545 png_crc_read(png_ptr, (png_bytep)purpose, slength);
1547 if (png_crc_finish(png_ptr, 0))
1549 png_free(png_ptr, purpose);
1553 purpose[slength] = 0x00; /* null terminate the last string */
1555 png_debug(3, "Finding end of pCAL purpose string\n");
1556 for (buf = purpose; *buf; buf++)
1559 endptr = purpose + slength;
1561 /* We need to have at least 12 bytes after the purpose string
1562 in order to get the parameter information. */
1563 if (endptr <= buf + 12)
1565 png_warning(png_ptr, "Invalid pCAL data");
1566 png_free(png_ptr, purpose);
1570 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1571 X0 = png_get_int_32((png_bytep)buf+1);
1572 X1 = png_get_int_32((png_bytep)buf+5);
1577 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1578 /* Check that we have the right number of parameters for known
1580 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1581 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1582 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1583 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1585 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1586 png_free(png_ptr, purpose);
1589 else if (type >= PNG_EQUATION_LAST)
1591 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1594 for (buf = units; *buf; buf++)
1595 /* Empty loop to move past the units string. */ ;
1597 png_debug(3, "Allocating pCAL parameters array\n");
1598 params = (png_charpp)png_malloc(png_ptr, (png_uint_32)(nparams
1599 *sizeof(png_charp))) ;
1601 /* Get pointers to the start of each parameter string. */
1602 for (i = 0; i < (int)nparams; i++)
1604 buf++; /* Skip the null string terminator from previous parameter. */
1606 png_debug1(3, "Reading pCAL parameter %d\n", i);
1607 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
1608 /* Empty loop to move past each parameter string */ ;
1610 /* Make sure we haven't run out of data yet */
1613 png_warning(png_ptr, "Invalid pCAL data");
1614 png_free(png_ptr, purpose);
1615 png_free(png_ptr, params);
1620 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1623 png_free(png_ptr, purpose);
1624 png_free(png_ptr, params);
1628 #if defined(PNG_READ_sCAL_SUPPORTED)
1629 /* read the sCAL chunk */
1631 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1633 png_charp buffer, ep;
1634 #ifdef PNG_FLOATING_POINT_SUPPORTED
1635 double width, height;
1638 #ifdef PNG_FIXED_POINT_SUPPORTED
1639 png_charp swidth, sheight;
1644 png_debug(1, "in png_handle_sCAL\n");
1646 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1647 png_error(png_ptr, "Missing IHDR before sCAL");
1648 else if (png_ptr->mode & PNG_HAVE_IDAT)
1650 png_warning(png_ptr, "Invalid sCAL after IDAT");
1651 png_crc_finish(png_ptr, length);
1654 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1656 png_warning(png_ptr, "Duplicate sCAL chunk");
1657 png_crc_finish(png_ptr, length);
1661 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1663 buffer = (png_charp)png_malloc(png_ptr, length + 1);
1664 slength = (png_size_t)length;
1665 png_crc_read(png_ptr, (png_bytep)buffer, slength);
1667 if (png_crc_finish(png_ptr, 0))
1669 png_free(png_ptr, buffer);
1673 buffer[slength] = 0x00; /* null terminate the last string */
1675 ep = buffer + 1; /* skip unit byte */
1677 #ifdef PNG_FLOATING_POINT_SUPPORTED
1678 width = strtod(ep, &vp);
1681 png_warning(png_ptr, "malformed width string in sCAL chunk");
1685 #ifdef PNG_FIXED_POINT_SUPPORTED
1686 swidth = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1);
1687 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1691 for (ep = buffer; *ep; ep++)
1695 #ifdef PNG_FLOATING_POINT_SUPPORTED
1696 height = strtod(ep, &vp);
1699 png_warning(png_ptr, "malformed height string in sCAL chunk");
1703 #ifdef PNG_FIXED_POINT_SUPPORTED
1704 sheight = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1);
1705 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1709 if (buffer + slength < ep
1710 #ifdef PNG_FLOATING_POINT_SUPPORTED
1711 || width <= 0. || height <= 0.
1715 png_warning(png_ptr, "Invalid sCAL data");
1716 png_free(png_ptr, buffer);
1717 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1718 png_free(png_ptr, swidth);
1719 png_free(png_ptr, sheight);
1725 #ifdef PNG_FLOATING_POINT_SUPPORTED
1726 png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1728 #ifdef PNG_FIXED_POINT_SUPPORTED
1729 png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1733 png_free(png_ptr, buffer);
1734 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1735 png_free(png_ptr, swidth);
1736 png_free(png_ptr, sheight);
1741 #if defined(PNG_READ_tIME_SUPPORTED)
1743 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1748 png_debug(1, "in png_handle_tIME\n");
1750 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1751 png_error(png_ptr, "Out of place tIME chunk");
1752 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1754 png_warning(png_ptr, "Duplicate tIME chunk");
1755 png_crc_finish(png_ptr, length);
1759 if (png_ptr->mode & PNG_HAVE_IDAT)
1760 png_ptr->mode |= PNG_AFTER_IDAT;
1764 png_warning(png_ptr, "Incorrect tIME chunk length");
1765 png_crc_finish(png_ptr, length);
1769 png_crc_read(png_ptr, buf, 7);
1770 if (png_crc_finish(png_ptr, 0))
1773 mod_time.second = buf[6];
1774 mod_time.minute = buf[5];
1775 mod_time.hour = buf[4];
1776 mod_time.day = buf[3];
1777 mod_time.month = buf[2];
1778 mod_time.year = png_get_uint_16(buf);
1780 png_set_tIME(png_ptr, info_ptr, &mod_time);
1784 #if defined(PNG_READ_tEXt_SUPPORTED)
1785 /* Note: this does not properly handle chunks that are > 64K under DOS */
1787 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1792 png_uint_32 skip = 0;
1795 png_debug(1, "in png_handle_tEXt\n");
1797 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1798 png_error(png_ptr, "Missing IHDR before tEXt");
1800 if (png_ptr->mode & PNG_HAVE_IDAT)
1801 png_ptr->mode |= PNG_AFTER_IDAT;
1803 #ifdef PNG_MAX_MALLOC_64K
1804 if (length > (png_uint_32)65535L)
1806 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1807 skip = length - (png_uint_32)65535L;
1808 length = (png_uint_32)65535L;
1812 key = (png_charp)png_malloc(png_ptr, length + 1);
1813 slength = (png_size_t)length;
1814 png_crc_read(png_ptr, (png_bytep)key, slength);
1816 if (png_crc_finish(png_ptr, skip))
1818 png_free(png_ptr, key);
1822 key[slength] = 0x00;
1824 for (text = key; *text; text++)
1825 /* empty loop to find end of key */ ;
1827 if (text != key + slength)
1830 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1831 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1832 text_ptr->key = key;
1833 #ifdef PNG_iTXt_SUPPORTED
1834 text_ptr->lang = NULL;
1835 text_ptr->lang_key = NULL;
1836 text_ptr->itxt_length = 0;
1838 text_ptr->text = text;
1839 text_ptr->text_length = png_strlen(text);
1841 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1843 png_free(png_ptr, key);
1844 png_free(png_ptr, text_ptr);
1848 #if defined(PNG_READ_zTXt_SUPPORTED)
1849 /* note: this does not correctly handle chunks that are > 64K under DOS */
1851 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1854 png_charp chunkdata;
1857 png_size_t slength, prefix_len, data_len;
1859 png_debug(1, "in png_handle_zTXt\n");
1860 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1861 png_error(png_ptr, "Missing IHDR before zTXt");
1863 if (png_ptr->mode & PNG_HAVE_IDAT)
1864 png_ptr->mode |= PNG_AFTER_IDAT;
1866 #ifdef PNG_MAX_MALLOC_64K
1867 /* We will no doubt have problems with chunks even half this size, but
1868 there is no hard and fast rule to tell us where to stop. */
1869 if (length > (png_uint_32)65535L)
1871 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1872 png_crc_finish(png_ptr, length);
1877 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1878 slength = (png_size_t)length;
1879 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1880 if (png_crc_finish(png_ptr, 0))
1882 png_free(png_ptr, chunkdata);
1886 chunkdata[slength] = 0x00;
1888 for (text = chunkdata; *text; text++)
1891 /* zTXt must have some text after the chunkdataword */
1892 if (text == chunkdata + slength)
1894 comp_type = PNG_TEXT_COMPRESSION_NONE;
1895 png_warning(png_ptr, "Zero length zTXt chunk");
1899 comp_type = *(++text);
1900 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
1902 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
1903 comp_type = PNG_TEXT_COMPRESSION_zTXt;
1905 text++; /* skip the compression_method byte */
1907 prefix_len = text - chunkdata;
1909 chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
1910 (png_size_t)length, prefix_len, &data_len);
1912 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1913 text_ptr->compression = comp_type;
1914 text_ptr->key = chunkdata;
1915 #ifdef PNG_iTXt_SUPPORTED
1916 text_ptr->lang = NULL;
1917 text_ptr->lang_key = NULL;
1918 text_ptr->itxt_length = 0;
1920 text_ptr->text = chunkdata + prefix_len;
1921 text_ptr->text_length = data_len;
1923 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1925 png_free(png_ptr, text_ptr);
1926 png_free(png_ptr, chunkdata);
1930 #if defined(PNG_READ_iTXt_SUPPORTED)
1931 /* note: this does not correctly handle chunks that are > 64K under DOS */
1933 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1936 png_charp chunkdata;
1937 png_charp key, lang, text, lang_key;
1940 png_size_t slength, prefix_len, data_len;
1942 png_debug(1, "in png_handle_iTXt\n");
1944 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1945 png_error(png_ptr, "Missing IHDR before iTXt");
1947 if (png_ptr->mode & PNG_HAVE_IDAT)
1948 png_ptr->mode |= PNG_AFTER_IDAT;
1950 #ifdef PNG_MAX_MALLOC_64K
1951 /* We will no doubt have problems with chunks even half this size, but
1952 there is no hard and fast rule to tell us where to stop. */
1953 if (length > (png_uint_32)65535L)
1955 png_warning(png_ptr,"iTXt chunk too large to fit in memory");
1956 png_crc_finish(png_ptr, length);
1961 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1962 slength = (png_size_t)length;
1963 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1964 if (png_crc_finish(png_ptr, 0))
1966 png_free(png_ptr, chunkdata);
1970 chunkdata[slength] = 0x00;
1972 for (lang = chunkdata; *lang; lang++)
1974 lang++; /* skip NUL separator */
1976 /* iTXt must have a language tag (possibly empty), two compression bytes,
1977 translated keyword (possibly empty), and possibly some text after the
1980 if (lang >= chunkdata + slength)
1982 comp_flag = PNG_TEXT_COMPRESSION_NONE;
1983 png_warning(png_ptr, "Zero length iTXt chunk");
1987 comp_flag = *lang++;
1988 comp_type = *lang++;
1991 for (lang_key = lang; *lang_key; lang_key++)
1993 lang_key++; /* skip NUL separator */
1995 for (text = lang_key; *text; text++)
1997 text++; /* skip NUL separator */
1999 prefix_len = text - chunkdata;
2003 chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
2004 (size_t)length, prefix_len, &data_len);
2006 data_len=png_strlen(chunkdata + prefix_len);
2007 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
2008 text_ptr->compression = (int)comp_flag + 1;
2009 text_ptr->lang_key = chunkdata+(lang_key-key);
2010 text_ptr->lang = chunkdata+(lang-key);
2011 text_ptr->itxt_length = data_len;
2012 text_ptr->text_length = 0;
2013 text_ptr->key = chunkdata;
2014 text_ptr->text = chunkdata + prefix_len;
2016 png_set_text(png_ptr, info_ptr, text_ptr, 1);
2018 png_free(png_ptr, text_ptr);
2019 png_free(png_ptr, chunkdata);
2023 /* This function is called when we haven't found a handler for a
2024 chunk. If there isn't a problem with the chunk itself (ie bad
2025 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2026 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2027 case it will be saved away to be written out later. */
2029 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2031 png_uint_32 skip = 0;
2033 png_debug(1, "in png_handle_unknown\n");
2035 if (png_ptr->mode & PNG_HAVE_IDAT)
2037 #ifdef PNG_USE_LOCAL_ARRAYS
2040 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2041 png_ptr->mode |= PNG_AFTER_IDAT;
2044 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
2046 if (!(png_ptr->chunk_name[0] & 0x20))
2048 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2049 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2051 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2052 && png_ptr->read_user_chunk_fn == NULL
2056 png_chunk_error(png_ptr, "unknown critical chunk");
2059 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2060 if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
2062 png_unknown_chunk chunk;
2064 #ifdef PNG_MAX_MALLOC_64K
2065 if (length > (png_uint_32)65535L)
2067 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2068 skip = length - (png_uint_32)65535L;
2069 length = (png_uint_32)65535L;
2072 png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
2073 chunk.data = (png_bytep)png_malloc(png_ptr, length);
2074 chunk.size = (png_size_t)length;
2075 png_crc_read(png_ptr, (png_bytep)chunk.data, length);
2076 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2077 if(png_ptr->read_user_chunk_fn != NULL)
2079 /* callback to user unknown chunk handler */
2080 if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
2082 if (!(png_ptr->chunk_name[0] & 0x20))
2083 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2084 HANDLE_CHUNK_ALWAYS)
2085 png_chunk_error(png_ptr, "unknown critical chunk");
2086 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2091 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2092 png_free(png_ptr, chunk.data);
2098 png_crc_finish(png_ptr, skip);
2100 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2101 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
2105 /* This function is called to verify that a chunk name is valid.
2106 This function can't have the "critical chunk check" incorporated
2107 into it, since in the future we will need to be able to call user
2108 functions to handle unknown critical chunks after we check that
2109 the chunk name itself is valid. */
2111 #define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
2114 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2116 png_debug(1, "in png_check_chunk_name\n");
2117 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2118 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2120 png_chunk_error(png_ptr, "invalid chunk type");
2124 /* Combines the row recently read in with the existing pixels in the
2125 row. This routine takes care of alpha and transparency if requested.
2126 This routine also handles the two methods of progressive display
2127 of interlaced images, depending on the mask value.
2128 The mask value describes which pixels are to be combined with
2129 the row. The pattern always repeats every 8 pixels, so just 8
2130 bits are needed. A one indicates the pixel is to be combined,
2131 a zero indicates the pixel is to be skipped. This is in addition
2132 to any alpha or transparency value associated with the pixel. If
2133 you want all pixels to be combined, pass 0xff (255) in mask. */
2134 #ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
2136 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2138 png_debug(1,"in png_combine_row\n");
2141 png_memcpy(row, png_ptr->row_buf + 1,
2142 (png_size_t)((png_ptr->width *
2143 png_ptr->row_info.pixel_depth + 7) >> 3));
2147 switch (png_ptr->row_info.pixel_depth)
2151 png_bytep sp = png_ptr->row_buf + 1;
2153 int s_inc, s_start, s_end;
2157 png_uint_32 row_width = png_ptr->width;
2159 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2160 if (png_ptr->transformations & PNG_PACKSWAP)
2176 for (i = 0; i < row_width; i++)
2182 value = (*sp >> shift) & 0x01;
2183 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2184 *dp |= (png_byte)(value << shift);
2205 png_bytep sp = png_ptr->row_buf + 1;
2207 int s_start, s_end, s_inc;
2211 png_uint_32 row_width = png_ptr->width;
2214 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2215 if (png_ptr->transformations & PNG_PACKSWAP)
2231 for (i = 0; i < row_width; i++)
2235 value = (*sp >> shift) & 0x03;
2236 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2237 *dp |= (png_byte)(value << shift);
2257 png_bytep sp = png_ptr->row_buf + 1;
2259 int s_start, s_end, s_inc;
2263 png_uint_32 row_width = png_ptr->width;
2266 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2267 if (png_ptr->transformations & PNG_PACKSWAP)
2282 for (i = 0; i < row_width; i++)
2286 value = (*sp >> shift) & 0xf;
2287 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2288 *dp |= (png_byte)(value << shift);
2308 png_bytep sp = png_ptr->row_buf + 1;
2310 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2312 png_uint_32 row_width = png_ptr->width;
2316 for (i = 0; i < row_width; i++)
2320 png_memcpy(dp, sp, pixel_bytes);
2336 #endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
2338 #ifdef PNG_READ_INTERLACING_SUPPORTED
2339 #ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */
2340 /* OLD pre-1.0.9 interface:
2341 void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2342 png_uint_32 transformations)
2345 png_do_read_interlace(png_structp png_ptr)
2347 png_row_infop row_info = &(png_ptr->row_info);
2348 png_bytep row = png_ptr->row_buf + 1;
2349 int pass = png_ptr->pass;
2350 png_uint_32 transformations = png_ptr->transformations;
2351 #ifdef PNG_USE_LOCAL_ARRAYS
2352 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2353 /* offset to next interlace block */
2354 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2357 png_debug(1,"in png_do_read_interlace (stock C version)\n");
2358 if (row != NULL && row_info != NULL)
2360 png_uint_32 final_width;
2362 final_width = row_info->width * png_pass_inc[pass];
2364 switch (row_info->pixel_depth)
2368 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2369 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2371 int s_start, s_end, s_inc;
2372 int jstop = png_pass_inc[pass];
2377 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2378 if (transformations & PNG_PACKSWAP)
2380 sshift = (int)((row_info->width + 7) & 0x07);
2381 dshift = (int)((final_width + 7) & 0x07);
2389 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2390 dshift = 7 - (int)((final_width + 7) & 0x07);
2396 for (i = 0; i < row_info->width; i++)
2398 v = (png_byte)((*sp >> sshift) & 0x01);
2399 for (j = 0; j < jstop; j++)
2401 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2402 *dp |= (png_byte)(v << dshift);
2403 if (dshift == s_end)
2411 if (sshift == s_end)
2423 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2424 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2426 int s_start, s_end, s_inc;
2427 int jstop = png_pass_inc[pass];
2430 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2431 if (transformations & PNG_PACKSWAP)
2433 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2434 dshift = (int)(((final_width + 3) & 0x03) << 1);
2442 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2443 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2449 for (i = 0; i < row_info->width; i++)
2454 v = (png_byte)((*sp >> sshift) & 0x03);
2455 for (j = 0; j < jstop; j++)
2457 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2458 *dp |= (png_byte)(v << dshift);
2459 if (dshift == s_end)
2467 if (sshift == s_end)
2479 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2480 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2482 int s_start, s_end, s_inc;
2484 int jstop = png_pass_inc[pass];
2486 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2487 if (transformations & PNG_PACKSWAP)
2489 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2490 dshift = (int)(((final_width + 1) & 0x01) << 2);
2498 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2499 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2505 for (i = 0; i < row_info->width; i++)
2507 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2510 for (j = 0; j < jstop; j++)
2512 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2513 *dp |= (png_byte)(v << dshift);
2514 if (dshift == s_end)
2522 if (sshift == s_end)
2534 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2535 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2536 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2538 int jstop = png_pass_inc[pass];
2541 for (i = 0; i < row_info->width; i++)
2546 png_memcpy(v, sp, pixel_bytes);
2547 for (j = 0; j < jstop; j++)
2549 png_memcpy(dp, v, pixel_bytes);
2557 row_info->width = final_width;
2558 row_info->rowbytes = ((final_width *
2559 (png_uint_32)row_info->pixel_depth + 7) >> 3);
2561 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2562 transformations = transformations; /* silence compiler warning */
2565 #endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
2566 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2568 #ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
2570 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2571 png_bytep prev_row, int filter)
2573 png_debug(1, "in png_read_filter_row\n");
2574 png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
2577 case PNG_FILTER_VALUE_NONE:
2579 case PNG_FILTER_VALUE_SUB:
2582 png_uint_32 istop = row_info->rowbytes;
2583 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2584 png_bytep rp = row + bpp;
2587 for (i = bpp; i < istop; i++)
2589 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2594 case PNG_FILTER_VALUE_UP:
2597 png_uint_32 istop = row_info->rowbytes;
2599 png_bytep pp = prev_row;
2601 for (i = 0; i < istop; i++)
2603 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2608 case PNG_FILTER_VALUE_AVG:
2612 png_bytep pp = prev_row;
2614 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2615 png_uint_32 istop = row_info->rowbytes - bpp;
2617 for (i = 0; i < bpp; i++)
2619 *rp = (png_byte)(((int)(*rp) +
2620 ((int)(*pp++) / 2 )) & 0xff);
2624 for (i = 0; i < istop; i++)
2626 *rp = (png_byte)(((int)(*rp) +
2627 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2632 case PNG_FILTER_VALUE_PAETH:
2636 png_bytep pp = prev_row;
2638 png_bytep cp = prev_row;
2639 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2640 png_uint_32 istop=row_info->rowbytes - bpp;
2642 for (i = 0; i < bpp; i++)
2644 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2648 for (i = 0; i < istop; i++) /* use leftover rp,pp */
2650 int a, b, c, pa, pb, pc, p;
2664 pa = p < 0 ? -p : p;
2665 pb = pc < 0 ? -pc : pc;
2666 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2670 if (pa <= pb && pa <= pc)
2678 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2680 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2686 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2691 #endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
2694 png_read_finish_row(png_structp png_ptr)
2696 #ifdef PNG_USE_LOCAL_ARRAYS
2697 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2699 /* start of interlace block */
2700 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2702 /* offset to next interlace block */
2703 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2705 /* start of interlace block in the y direction */
2706 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2708 /* offset to next interlace block in the y direction */
2709 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2712 png_debug(1, "in png_read_finish_row\n");
2713 png_ptr->row_number++;
2714 if (png_ptr->row_number < png_ptr->num_rows)
2717 if (png_ptr->interlaced)
2719 png_ptr->row_number = 0;
2720 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
2724 if (png_ptr->pass >= 7)
2726 png_ptr->iwidth = (png_ptr->width +
2727 png_pass_inc[png_ptr->pass] - 1 -
2728 png_pass_start[png_ptr->pass]) /
2729 png_pass_inc[png_ptr->pass];
2730 png_ptr->irowbytes = ((png_ptr->iwidth *
2731 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2733 if (!(png_ptr->transformations & PNG_INTERLACE))
2735 png_ptr->num_rows = (png_ptr->height +
2736 png_pass_yinc[png_ptr->pass] - 1 -
2737 png_pass_ystart[png_ptr->pass]) /
2738 png_pass_yinc[png_ptr->pass];
2739 if (!(png_ptr->num_rows))
2742 else /* if (png_ptr->transformations & PNG_INTERLACE) */
2744 } while (png_ptr->iwidth == 0);
2746 if (png_ptr->pass < 7)
2750 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
2752 #ifdef PNG_USE_LOCAL_ARRAYS
2758 png_ptr->zstream.next_out = (Byte *)&extra;
2759 png_ptr->zstream.avail_out = (uInt)1;
2762 if (!(png_ptr->zstream.avail_in))
2764 while (!png_ptr->idat_size)
2766 png_byte chunk_length[4];
2768 png_crc_finish(png_ptr, 0);
2770 png_read_data(png_ptr, chunk_length, 4);
2771 png_ptr->idat_size = png_get_uint_32(chunk_length);
2773 png_reset_crc(png_ptr);
2774 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2775 if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
2776 png_error(png_ptr, "Not enough image data");
2779 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2780 png_ptr->zstream.next_in = png_ptr->zbuf;
2781 if (png_ptr->zbuf_size > png_ptr->idat_size)
2782 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2783 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2784 png_ptr->idat_size -= png_ptr->zstream.avail_in;
2786 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
2787 if (ret == Z_STREAM_END)
2789 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
2791 png_error(png_ptr, "Extra compressed data");
2792 png_ptr->mode |= PNG_AFTER_IDAT;
2793 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2797 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
2798 "Decompression Error");
2800 if (!(png_ptr->zstream.avail_out))
2801 png_error(png_ptr, "Extra compressed data");
2804 png_ptr->zstream.avail_out = 0;
2807 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
2808 png_error(png_ptr, "Extra compression data");
2810 inflateReset(&png_ptr->zstream);
2812 png_ptr->mode |= PNG_AFTER_IDAT;
2816 png_read_start_row(png_structp png_ptr)
2818 #ifdef PNG_USE_LOCAL_ARRAYS
2819 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2821 /* start of interlace block */
2822 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2824 /* offset to next interlace block */
2825 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2827 /* start of interlace block in the y direction */
2828 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2830 /* offset to next interlace block in the y direction */
2831 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2834 int max_pixel_depth;
2835 png_uint_32 row_bytes;
2837 png_debug(1, "in png_read_start_row\n");
2838 png_ptr->zstream.avail_in = 0;
2839 png_init_read_transformations(png_ptr);
2840 if (png_ptr->interlaced)
2842 if (!(png_ptr->transformations & PNG_INTERLACE))
2843 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2844 png_pass_ystart[0]) / png_pass_yinc[0];
2846 png_ptr->num_rows = png_ptr->height;
2848 png_ptr->iwidth = (png_ptr->width +
2849 png_pass_inc[png_ptr->pass] - 1 -
2850 png_pass_start[png_ptr->pass]) /
2851 png_pass_inc[png_ptr->pass];
2853 row_bytes = ((png_ptr->iwidth *
2854 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2855 png_ptr->irowbytes = (png_size_t)row_bytes;
2856 if((png_uint_32)png_ptr->irowbytes != row_bytes)
2857 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
2861 png_ptr->num_rows = png_ptr->height;
2862 png_ptr->iwidth = png_ptr->width;
2863 png_ptr->irowbytes = png_ptr->rowbytes + 1;
2865 max_pixel_depth = png_ptr->pixel_depth;
2867 #if defined(PNG_READ_PACK_SUPPORTED)
2868 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
2869 max_pixel_depth = 8;
2872 #if defined(PNG_READ_EXPAND_SUPPORTED)
2873 if (png_ptr->transformations & PNG_EXPAND)
2875 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2877 if (png_ptr->num_trans)
2878 max_pixel_depth = 32;
2880 max_pixel_depth = 24;
2882 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2884 if (max_pixel_depth < 8)
2885 max_pixel_depth = 8;
2886 if (png_ptr->num_trans)
2887 max_pixel_depth *= 2;
2889 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2891 if (png_ptr->num_trans)
2893 max_pixel_depth *= 4;
2894 max_pixel_depth /= 3;
2900 #if defined(PNG_READ_FILLER_SUPPORTED)
2901 if (png_ptr->transformations & (PNG_FILLER))
2903 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2904 max_pixel_depth = 32;
2905 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2907 if (max_pixel_depth <= 8)
2908 max_pixel_depth = 16;
2910 max_pixel_depth = 32;
2912 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2914 if (max_pixel_depth <= 32)
2915 max_pixel_depth = 32;
2917 max_pixel_depth = 64;
2922 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2923 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
2926 #if defined(PNG_READ_EXPAND_SUPPORTED)
2927 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
2929 #if defined(PNG_READ_FILLER_SUPPORTED)
2930 (png_ptr->transformations & (PNG_FILLER)) ||
2932 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2934 if (max_pixel_depth <= 16)
2935 max_pixel_depth = 32;
2937 max_pixel_depth = 64;
2941 if (max_pixel_depth <= 8)
2943 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2944 max_pixel_depth = 32;
2946 max_pixel_depth = 24;
2948 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2949 max_pixel_depth = 64;
2951 max_pixel_depth = 48;
2956 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
2957 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
2958 if(png_ptr->transformations & PNG_USER_TRANSFORM)
2960 int user_pixel_depth=png_ptr->user_transform_depth*
2961 png_ptr->user_transform_channels;
2962 if(user_pixel_depth > max_pixel_depth)
2963 max_pixel_depth=user_pixel_depth;
2967 /* align the width on the next larger 8 pixels. Mainly used
2969 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
2970 /* calculate the maximum bytes needed, adding a byte and a pixel
2971 for safety's sake */
2972 row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
2973 1 + ((max_pixel_depth + 7) >> 3);
2974 #ifdef PNG_MAX_MALLOC_64K
2975 if (row_bytes > (png_uint_32)65536L)
2976 png_error(png_ptr, "This image requires a row greater than 64KB");
2978 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
2979 png_ptr->row_buf = png_ptr->big_row_buf+32;
2980 #if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
2981 png_ptr->row_buf_size = row_bytes;
2984 #ifdef PNG_MAX_MALLOC_64K
2985 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
2986 png_error(png_ptr, "This image requires a row greater than 64KB");
2988 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
2989 png_ptr->rowbytes + 1));
2991 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
2993 png_debug1(3, "width = %lu,\n", png_ptr->width);
2994 png_debug1(3, "height = %lu,\n", png_ptr->height);
2995 png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
2996 png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
2997 png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
2998 png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
3000 png_ptr->flags |= PNG_FLAG_ROW_INIT;