Added "support" for the 64 bit data structures of EHCI in appendix B, in case the...
[cake.git] / compiler / libpng / pngrutil.c
blobbd22c566fb86e3024ae56e25ff9e2ffa34eda6bc
2 /* pngrutil.c - utilities to read a PNG file
4 * libpng 1.0.10 - March 30, 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.
14 #define PNG_INTERNAL
15 #include "png.h"
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)
22 double result = 0;
23 int len;
24 wchar_t *str, *end;
26 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
27 str = (wchar_t *)malloc(len * sizeof(wchar_t));
28 if ( NULL != str )
30 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
31 result = wcstod(str, &end);
32 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
33 *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
34 free(str);
36 return result;
38 # endif
39 #endif
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));
51 return (i);
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));
66 return (i);
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)));
77 return (i);
79 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
81 /* Read data, and (optionally) run it through the CRC. */
82 void /* PRIVATE */
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. */
93 int /* PRIVATE */
94 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
96 png_size_t i;
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);
103 if (i)
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");
117 else
119 png_chunk_error(png_ptr, "CRC error");
121 return (1);
124 return (0);
127 /* Compare the CRC stored in the PNG file with that calculated by libpng from
128 the data it has read thus far. */
129 int /* PRIVATE */
130 png_crc_error(png_structp png_ptr)
132 png_byte crc_bytes[4];
133 png_uint_32 crc;
134 int need_crc = 1;
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))
140 need_crc = 0;
142 else /* critical */
144 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
145 need_crc = 0;
148 png_read_data(png_ptr, crc_bytes, 4);
150 if (need_crc)
152 crc = png_get_uint_32(crc_bytes);
153 return ((int)(crc != png_ptr->crc));
155 else
156 return (0);
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)
179 int ret = Z_OK;
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;
185 text_size = 0;
186 text = NULL;
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);
195 else
196 png_warning(png_ptr, msg);
197 inflateReset(&png_ptr->zstream);
198 png_ptr->zstream.avail_in = 0;
200 if (text == NULL)
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);
213 break;
215 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
217 if (text == NULL)
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;
227 else
229 png_charp tmp;
231 tmp = text;
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)
242 break;
243 else
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)
253 char umsg[50];
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);
261 else
262 sprintf(umsg,"Incomplete compressed datastream in %s chunk",
263 png_ptr->chunk_name);
264 png_warning(png_ptr, umsg);
265 #else
266 png_warning(png_ptr,
267 "Incomplete compressed datastream in chunk other than IDAT");
268 #endif
269 text_size=prefix_size;
270 if (text == NULL)
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);
282 chunkdata = text;
283 *newlength=text_size;
285 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
287 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
288 char umsg[50];
290 sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
291 png_warning(png_ptr, umsg);
292 #else
293 png_warning(png_ptr, "Unknown zTXt compression type");
294 #endif
296 *(chunkdata + prefix_size) = 0x00;
297 *newlength=prefix_size;
300 return chunkdata;
302 #endif
304 /* read and check the IDHR chunk */
305 void /* PRIVATE */
306 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
308 png_byte buf[13];
309 png_uint_32 width, height;
310 int bit_depth, color_type, compression_type, filter_type;
311 int interlace_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 */
319 if (length != 13)
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);
329 bit_depth = buf[8];
330 color_type = buf[9];
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 png_ptr->filter_type = (png_byte)filter_type;
344 /* find number of channels */
345 switch (png_ptr->color_type)
347 case PNG_COLOR_TYPE_GRAY:
348 case PNG_COLOR_TYPE_PALETTE:
349 png_ptr->channels = 1;
350 break;
351 case PNG_COLOR_TYPE_RGB:
352 png_ptr->channels = 3;
353 break;
354 case PNG_COLOR_TYPE_GRAY_ALPHA:
355 png_ptr->channels = 2;
356 break;
357 case PNG_COLOR_TYPE_RGB_ALPHA:
358 png_ptr->channels = 4;
359 break;
362 /* set up other useful info */
363 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
364 png_ptr->channels);
365 png_ptr->rowbytes = ((png_ptr->width *
366 (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
367 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
368 png_debug1(3,"channels = %d\n", png_ptr->channels);
369 png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
370 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
371 color_type, interlace_type, compression_type, filter_type);
374 /* read and check the palette */
375 void /* PRIVATE */
376 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
378 png_color palette[PNG_MAX_PALETTE_LENGTH];
379 int num, i;
380 #ifndef PNG_NO_POINTER_INDEXING
381 png_colorp pal_ptr;
382 #endif
384 png_debug(1, "in png_handle_PLTE\n");
386 if (!(png_ptr->mode & PNG_HAVE_IHDR))
387 png_error(png_ptr, "Missing IHDR before PLTE");
388 else if (png_ptr->mode & PNG_HAVE_IDAT)
390 png_warning(png_ptr, "Invalid PLTE after IDAT");
391 png_crc_finish(png_ptr, length);
392 return;
394 else if (png_ptr->mode & PNG_HAVE_PLTE)
395 png_error(png_ptr, "Duplicate PLTE chunk");
397 png_ptr->mode |= PNG_HAVE_PLTE;
399 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
400 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
402 png_crc_finish(png_ptr, length);
403 return;
405 #endif
407 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
409 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
411 png_warning(png_ptr, "Invalid palette chunk");
412 png_crc_finish(png_ptr, length);
413 return;
415 else
417 png_error(png_ptr, "Invalid palette chunk");
421 num = (int)length / 3;
423 #ifndef PNG_NO_POINTER_INDEXING
424 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
426 png_byte buf[3];
428 png_crc_read(png_ptr, buf, 3);
429 pal_ptr->red = buf[0];
430 pal_ptr->green = buf[1];
431 pal_ptr->blue = buf[2];
433 #else
434 for (i = 0; i < num; i++)
436 png_byte buf[3];
438 png_crc_read(png_ptr, buf, 3);
439 /* don't depend upon png_color being any order */
440 palette[i].red = buf[0];
441 palette[i].green = buf[1];
442 palette[i].blue = buf[2];
444 #endif
446 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
447 whatever the normal CRC configuration tells us. However, if we
448 have an RGB image, the PLTE can be considered ancillary, so
449 we will act as though it is. */
450 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
451 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
452 #endif
454 png_crc_finish(png_ptr, 0);
456 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
457 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
459 /* If we don't want to use the data from an ancillary chunk,
460 we have two options: an error abort, or a warning and we
461 ignore the data in this chunk (which should be OK, since
462 it's considered ancillary for a RGB or RGBA image). */
463 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
465 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
467 png_chunk_error(png_ptr, "CRC error");
469 else
471 png_chunk_warning(png_ptr, "CRC error");
472 return;
475 /* Otherwise, we (optionally) emit a warning and use the chunk. */
476 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
478 png_chunk_warning(png_ptr, "CRC error");
481 #endif
483 png_set_PLTE(png_ptr, info_ptr, palette, num);
485 #if defined(PNG_READ_tRNS_SUPPORTED)
486 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
488 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
490 if (png_ptr->num_trans > (png_uint_16)num)
492 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
493 png_ptr->num_trans = (png_uint_16)num;
495 if (info_ptr->num_trans > (png_uint_16)num)
497 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
498 info_ptr->num_trans = (png_uint_16)num;
502 #endif
506 void /* PRIVATE */
507 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
509 png_debug(1, "in png_handle_IEND\n");
511 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
513 png_error(png_ptr, "No image in file");
515 /* to quiet compiler warnings about unused info_ptr */
516 if (info_ptr == NULL)
517 return;
520 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
522 if (length != 0)
524 png_warning(png_ptr, "Incorrect IEND chunk length");
526 png_crc_finish(png_ptr, length);
529 #if defined(PNG_READ_gAMA_SUPPORTED)
530 void /* PRIVATE */
531 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
533 png_fixed_point igamma;
534 #ifdef PNG_FLOATING_POINT_SUPPORTED
535 float file_gamma;
536 #endif
537 png_byte buf[4];
539 png_debug(1, "in png_handle_gAMA\n");
541 if (!(png_ptr->mode & PNG_HAVE_IHDR))
542 png_error(png_ptr, "Missing IHDR before gAMA");
543 else if (png_ptr->mode & PNG_HAVE_IDAT)
545 png_warning(png_ptr, "Invalid gAMA after IDAT");
546 png_crc_finish(png_ptr, length);
547 return;
549 else if (png_ptr->mode & PNG_HAVE_PLTE)
550 /* Should be an error, but we can cope with it */
551 png_warning(png_ptr, "Out of place gAMA chunk");
553 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
554 #if defined(PNG_READ_sRGB_SUPPORTED)
555 && !(info_ptr->valid & PNG_INFO_sRGB)
556 #endif
559 png_warning(png_ptr, "Duplicate gAMA chunk");
560 png_crc_finish(png_ptr, length);
561 return;
564 if (length != 4)
566 png_warning(png_ptr, "Incorrect gAMA chunk length");
567 png_crc_finish(png_ptr, length);
568 return;
571 png_crc_read(png_ptr, buf, 4);
572 if (png_crc_finish(png_ptr, 0))
573 return;
575 igamma = (png_fixed_point)png_get_uint_32(buf);
576 /* check for zero gamma */
577 if (igamma == 0)
579 png_warning(png_ptr,
580 "Ignoring gAMA chunk with gamma=0");
581 return;
584 #if defined(PNG_READ_sRGB_SUPPORTED)
585 if (info_ptr->valid & PNG_INFO_sRGB)
586 if(igamma < 45000L || igamma > 46000L)
588 png_warning(png_ptr,
589 "Ignoring incorrect gAMA value when sRGB is also present");
590 #ifndef PNG_NO_CONSOLE_IO
591 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
592 #endif
593 return;
595 #endif /* PNG_READ_sRGB_SUPPORTED */
597 #ifdef PNG_FLOATING_POINT_SUPPORTED
598 file_gamma = (float)igamma / (float)100000.0;
599 # ifdef PNG_READ_GAMMA_SUPPORTED
600 png_ptr->gamma = file_gamma;
601 # endif
602 png_set_gAMA(png_ptr, info_ptr, file_gamma);
603 #endif
604 #ifdef PNG_FIXED_POINT_SUPPORTED
605 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
606 #endif
608 #endif
610 #if defined(PNG_READ_sBIT_SUPPORTED)
611 void /* PRIVATE */
612 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
614 png_size_t truelen;
615 png_byte buf[4];
617 png_debug(1, "in png_handle_sBIT\n");
619 buf[0] = buf[1] = buf[2] = buf[3] = 0;
621 if (!(png_ptr->mode & PNG_HAVE_IHDR))
622 png_error(png_ptr, "Missing IHDR before sBIT");
623 else if (png_ptr->mode & PNG_HAVE_IDAT)
625 png_warning(png_ptr, "Invalid sBIT after IDAT");
626 png_crc_finish(png_ptr, length);
627 return;
629 else if (png_ptr->mode & PNG_HAVE_PLTE)
631 /* Should be an error, but we can cope with it */
632 png_warning(png_ptr, "Out of place sBIT chunk");
634 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
636 png_warning(png_ptr, "Duplicate sBIT chunk");
637 png_crc_finish(png_ptr, length);
638 return;
641 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
642 truelen = 3;
643 else
644 truelen = (png_size_t)png_ptr->channels;
646 if (length != truelen)
648 png_warning(png_ptr, "Incorrect sBIT chunk length");
649 png_crc_finish(png_ptr, length);
650 return;
653 png_crc_read(png_ptr, buf, truelen);
654 if (png_crc_finish(png_ptr, 0))
655 return;
657 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
659 png_ptr->sig_bit.red = buf[0];
660 png_ptr->sig_bit.green = buf[1];
661 png_ptr->sig_bit.blue = buf[2];
662 png_ptr->sig_bit.alpha = buf[3];
664 else
666 png_ptr->sig_bit.gray = buf[0];
667 png_ptr->sig_bit.red = buf[0];
668 png_ptr->sig_bit.green = buf[0];
669 png_ptr->sig_bit.blue = buf[0];
670 png_ptr->sig_bit.alpha = buf[1];
672 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
674 #endif
676 #if defined(PNG_READ_cHRM_SUPPORTED)
677 void /* PRIVATE */
678 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
680 png_byte buf[4];
681 #ifdef PNG_FLOATING_POINT_SUPPORTED
682 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
683 #endif
684 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
685 int_y_green, int_x_blue, int_y_blue;
687 png_debug(1, "in png_handle_cHRM\n");
689 if (!(png_ptr->mode & PNG_HAVE_IHDR))
690 png_error(png_ptr, "Missing IHDR before cHRM");
691 else if (png_ptr->mode & PNG_HAVE_IDAT)
693 png_warning(png_ptr, "Invalid cHRM after IDAT");
694 png_crc_finish(png_ptr, length);
695 return;
697 else if (png_ptr->mode & PNG_HAVE_PLTE)
698 /* Should be an error, but we can cope with it */
699 png_warning(png_ptr, "Missing PLTE before cHRM");
701 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
702 #if defined(PNG_READ_sRGB_SUPPORTED)
703 && !(info_ptr->valid & PNG_INFO_sRGB)
704 #endif
707 png_warning(png_ptr, "Duplicate cHRM chunk");
708 png_crc_finish(png_ptr, length);
709 return;
712 if (length != 32)
714 png_warning(png_ptr, "Incorrect cHRM chunk length");
715 png_crc_finish(png_ptr, length);
716 return;
719 png_crc_read(png_ptr, buf, 4);
720 int_x_white = (png_fixed_point)png_get_uint_32(buf);
722 png_crc_read(png_ptr, buf, 4);
723 int_y_white = (png_fixed_point)png_get_uint_32(buf);
725 if (int_x_white > 80000L || int_y_white > 80000L ||
726 int_x_white + int_y_white > 100000L)
728 png_warning(png_ptr, "Invalid cHRM white point");
729 png_crc_finish(png_ptr, 24);
730 return;
733 png_crc_read(png_ptr, buf, 4);
734 int_x_red = (png_fixed_point)png_get_uint_32(buf);
736 png_crc_read(png_ptr, buf, 4);
737 int_y_red = (png_fixed_point)png_get_uint_32(buf);
739 if (int_x_red > 80000L || int_y_red > 80000L ||
740 int_x_red + int_y_red > 100000L)
742 png_warning(png_ptr, "Invalid cHRM red point");
743 png_crc_finish(png_ptr, 16);
744 return;
747 png_crc_read(png_ptr, buf, 4);
748 int_x_green = (png_fixed_point)png_get_uint_32(buf);
750 png_crc_read(png_ptr, buf, 4);
751 int_y_green = (png_fixed_point)png_get_uint_32(buf);
753 if (int_x_green > 80000L || int_y_green > 80000L ||
754 int_x_green + int_y_green > 100000L)
756 png_warning(png_ptr, "Invalid cHRM green point");
757 png_crc_finish(png_ptr, 8);
758 return;
761 png_crc_read(png_ptr, buf, 4);
762 int_x_blue = (png_fixed_point)png_get_uint_32(buf);
764 png_crc_read(png_ptr, buf, 4);
765 int_y_blue = (png_fixed_point)png_get_uint_32(buf);
767 if (int_x_blue > 80000L || int_y_blue > 80000L ||
768 int_x_blue + int_y_blue > 100000L)
770 png_warning(png_ptr, "Invalid cHRM blue point");
771 png_crc_finish(png_ptr, 0);
772 return;
774 #ifdef PNG_FLOATING_POINT_SUPPORTED
775 white_x = (float)int_x_white / (float)100000.0;
776 white_y = (float)int_y_white / (float)100000.0;
777 red_x = (float)int_x_red / (float)100000.0;
778 red_y = (float)int_y_red / (float)100000.0;
779 green_x = (float)int_x_green / (float)100000.0;
780 green_y = (float)int_y_green / (float)100000.0;
781 blue_x = (float)int_x_blue / (float)100000.0;
782 blue_y = (float)int_y_blue / (float)100000.0;
783 #endif
785 #if defined(PNG_READ_sRGB_SUPPORTED)
786 if (info_ptr->valid & PNG_INFO_sRGB)
788 if (abs(int_x_white - 31270L) > 1000 ||
789 abs(int_y_white - 32900L) > 1000 ||
790 abs( int_x_red - 64000L) > 1000 ||
791 abs( int_y_red - 33000L) > 1000 ||
792 abs(int_x_green - 30000L) > 1000 ||
793 abs(int_y_green - 60000L) > 1000 ||
794 abs( int_x_blue - 15000L) > 1000 ||
795 abs( int_y_blue - 6000L) > 1000)
798 png_warning(png_ptr,
799 "Ignoring incorrect cHRM value when sRGB is also present");
800 #ifndef PNG_NO_CONSOLE_IO
801 #ifdef PNG_FLOATING_POINT_SUPPORTED
802 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
803 white_x, white_y, red_x, red_y);
804 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
805 green_x, green_y, blue_x, blue_y);
806 #else
807 fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
808 int_x_white, int_y_white, int_x_red, int_y_red);
809 fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
810 int_x_green, int_y_green, int_x_blue, int_y_blue);
811 #endif
812 #endif /* PNG_NO_CONSOLE_IO */
814 png_crc_finish(png_ptr, 0);
815 return;
817 #endif /* PNG_READ_sRGB_SUPPORTED */
819 #ifdef PNG_FLOATING_POINT_SUPPORTED
820 png_set_cHRM(png_ptr, info_ptr,
821 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
822 #endif
823 #ifdef PNG_FIXED_POINT_SUPPORTED
824 png_set_cHRM_fixed(png_ptr, info_ptr,
825 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
826 int_y_green, int_x_blue, int_y_blue);
827 #endif
828 if (png_crc_finish(png_ptr, 0))
829 return;
831 #endif
833 #if defined(PNG_READ_sRGB_SUPPORTED)
834 void /* PRIVATE */
835 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
837 int intent;
838 png_byte buf[1];
840 png_debug(1, "in png_handle_sRGB\n");
842 if (!(png_ptr->mode & PNG_HAVE_IHDR))
843 png_error(png_ptr, "Missing IHDR before sRGB");
844 else if (png_ptr->mode & PNG_HAVE_IDAT)
846 png_warning(png_ptr, "Invalid sRGB after IDAT");
847 png_crc_finish(png_ptr, length);
848 return;
850 else if (png_ptr->mode & PNG_HAVE_PLTE)
851 /* Should be an error, but we can cope with it */
852 png_warning(png_ptr, "Out of place sRGB chunk");
854 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
856 png_warning(png_ptr, "Duplicate sRGB chunk");
857 png_crc_finish(png_ptr, length);
858 return;
861 if (length != 1)
863 png_warning(png_ptr, "Incorrect sRGB chunk length");
864 png_crc_finish(png_ptr, length);
865 return;
868 png_crc_read(png_ptr, buf, 1);
869 if (png_crc_finish(png_ptr, 0))
870 return;
872 intent = buf[0];
873 /* check for bad intent */
874 if (intent >= PNG_sRGB_INTENT_LAST)
876 png_warning(png_ptr, "Unknown sRGB intent");
877 return;
880 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
881 if ((info_ptr->valid & PNG_INFO_gAMA))
883 int igamma;
884 #ifdef PNG_FIXED_POINT_SUPPORTED
885 igamma=(int)info_ptr->int_gamma;
886 #else
887 # ifdef PNG_FLOATING_POINT_SUPPORTED
888 igamma=(int)(info_ptr->gamma * 100000.);
889 # endif
890 #endif
891 #if 0 && defined(PNG_cHRM_SUPPORTED) && !defined(PNG_FIXED_POINT_SUPPORTED)
892 /* We need to define these here because they aren't in png.h */
893 png_fixed_point int_x_white;
894 png_fixed_point int_y_white;
895 png_fixed_point int_x_red;
896 png_fixed_point int_y_red;
897 png_fixed_point int_x_green;
898 png_fixed_point int_y_green;
899 png_fixed_point int_x_blue;
900 png_fixed_point int_y_blue;
901 #endif
902 if(igamma < 45000L || igamma > 46000L)
904 png_warning(png_ptr,
905 "Ignoring incorrect gAMA value when sRGB is also present");
906 #ifndef PNG_NO_CONSOLE_IO
907 # ifdef PNG_FIXED_POINT_SUPPORTED
908 fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
909 # else
910 # ifdef PNG_FLOATING_POINT_SUPPORTED
911 fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
912 # endif
913 # endif
914 #endif
917 #endif /* PNG_READ_gAMA_SUPPORTED */
919 #ifdef PNG_READ_cHRM_SUPPORTED
920 #ifdef PNG_FIXED_POINT_SUPPORTED
921 if (info_ptr->valid & PNG_INFO_cHRM)
922 if (abs(info_ptr->int_x_white - 31270L) > 1000 ||
923 abs(info_ptr->int_y_white - 32900L) > 1000 ||
924 abs( info_ptr->int_x_red - 64000L) > 1000 ||
925 abs( info_ptr->int_y_red - 33000L) > 1000 ||
926 abs(info_ptr->int_x_green - 30000L) > 1000 ||
927 abs(info_ptr->int_y_green - 60000L) > 1000 ||
928 abs( info_ptr->int_x_blue - 15000L) > 1000 ||
929 abs( info_ptr->int_y_blue - 6000L) > 1000)
931 png_warning(png_ptr,
932 "Ignoring incorrect cHRM value when sRGB is also present");
934 #endif /* PNG_FIXED_POINT_SUPPORTED */
935 #endif /* PNG_READ_cHRM_SUPPORTED */
937 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
939 #endif /* PNG_READ_sRGB_SUPPORTED */
941 #if defined(PNG_READ_iCCP_SUPPORTED)
942 void /* PRIVATE */
943 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
944 /* Note: this does not properly handle chunks that are > 64K under DOS */
946 png_charp chunkdata;
947 png_byte compression_type;
948 png_charp profile;
949 png_uint_32 skip = 0;
950 png_uint_32 profile_size = 0;
951 png_uint_32 profile_length = 0;
952 png_size_t slength, prefix_length, data_length;
954 png_debug(1, "in png_handle_iCCP\n");
956 if (!(png_ptr->mode & PNG_HAVE_IHDR))
957 png_error(png_ptr, "Missing IHDR before iCCP");
958 else if (png_ptr->mode & PNG_HAVE_IDAT)
960 png_warning(png_ptr, "Invalid iCCP after IDAT");
961 png_crc_finish(png_ptr, length);
962 return;
964 else if (png_ptr->mode & PNG_HAVE_PLTE)
965 /* Should be an error, but we can cope with it */
966 png_warning(png_ptr, "Out of place iCCP chunk");
968 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
970 png_warning(png_ptr, "Duplicate iCCP chunk");
971 png_crc_finish(png_ptr, length);
972 return;
975 #ifdef PNG_MAX_MALLOC_64K
976 if (length > (png_uint_32)65535L)
978 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
979 skip = length - (png_uint_32)65535L;
980 length = (png_uint_32)65535L;
982 #endif
984 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
985 slength = (png_size_t)length;
986 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
988 if (png_crc_finish(png_ptr, skip))
990 png_free(png_ptr, chunkdata);
991 return;
994 chunkdata[slength] = 0x00;
996 for (profile = chunkdata; *profile; profile++)
997 /* empty loop to find end of name */ ;
999 ++profile;
1001 /* there should be at least one zero (the compression type byte)
1002 following the separator, and we should be on it */
1003 if ( profile >= chunkdata + slength)
1005 png_free(png_ptr, chunkdata);
1006 png_warning(png_ptr, "Malformed iCCP chunk");
1007 return;
1010 /* compression_type should always be zero */
1011 compression_type = *profile++;
1012 if (compression_type)
1014 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1015 compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1016 wrote nonzero) */
1019 prefix_length = profile - chunkdata;
1020 chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
1021 slength, prefix_length, &data_length);
1023 profile_length = data_length - prefix_length;
1025 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1026 profile_size = ((*(chunkdata+prefix_length))<<24) |
1027 ((*(chunkdata+prefix_length+1))<<16) |
1028 ((*(chunkdata+prefix_length+2))<< 8) |
1029 ((*(chunkdata+prefix_length+3)) );
1031 if(profile_size < profile_length)
1032 profile_length = profile_size;
1034 if(profile_size > profile_length)
1036 png_warning(png_ptr, "Ignoring truncated iCCP profile.\n");
1037 return;
1040 png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
1041 chunkdata + prefix_length, profile_length);
1042 png_free(png_ptr, chunkdata);
1044 #endif /* PNG_READ_iCCP_SUPPORTED */
1046 #if defined(PNG_READ_sPLT_SUPPORTED)
1047 void /* PRIVATE */
1048 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1049 /* Note: this does not properly handle chunks that are > 64K under DOS */
1051 png_bytep chunkdata;
1052 png_bytep entry_start;
1053 png_sPLT_t new_palette;
1054 #ifdef PNG_NO_POINTER_INDEXING
1055 png_sPLT_entryp pp;
1056 #endif
1057 int data_length, entry_size, i;
1058 png_uint_32 skip = 0;
1059 png_size_t slength;
1061 png_debug(1, "in png_handle_sPLT\n");
1063 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1064 png_error(png_ptr, "Missing IHDR before sPLT");
1065 else if (png_ptr->mode & PNG_HAVE_IDAT)
1067 png_warning(png_ptr, "Invalid sPLT after IDAT");
1068 png_crc_finish(png_ptr, length);
1069 return;
1072 #ifdef PNG_MAX_MALLOC_64K
1073 if (length > (png_uint_32)65535L)
1075 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1076 skip = length - (png_uint_32)65535L;
1077 length = (png_uint_32)65535L;
1079 #endif
1081 chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
1082 slength = (png_size_t)length;
1083 png_crc_read(png_ptr, chunkdata, slength);
1085 if (png_crc_finish(png_ptr, skip))
1087 png_free(png_ptr, chunkdata);
1088 return;
1091 chunkdata[slength] = 0x00;
1093 for (entry_start = chunkdata; *entry_start; entry_start++)
1094 /* empty loop to find end of name */ ;
1095 ++entry_start;
1097 /* a sample depth should follow the separator, and we should be on it */
1098 if (entry_start > chunkdata + slength)
1100 png_free(png_ptr, chunkdata);
1101 png_warning(png_ptr, "malformed sPLT chunk");
1102 return;
1105 new_palette.depth = *entry_start++;
1106 entry_size = (new_palette.depth == 8 ? 6 : 10);
1107 data_length = (slength - (entry_start - chunkdata));
1109 /* integrity-check the data length */
1110 if (data_length % entry_size)
1112 png_free(png_ptr, chunkdata);
1113 png_error(png_ptr, "sPLT chunk has bad length");
1116 new_palette.nentries = data_length / entry_size;
1117 new_palette.entries = (png_sPLT_entryp)png_malloc(
1118 png_ptr, new_palette.nentries * sizeof(png_sPLT_entry));
1120 #ifndef PNG_NO_POINTER_INDEXING
1121 for (i = 0; i < new_palette.nentries; i++)
1123 png_sPLT_entryp pp = new_palette.entries + i;
1125 if (new_palette.depth == 8)
1127 pp->red = *entry_start++;
1128 pp->green = *entry_start++;
1129 pp->blue = *entry_start++;
1130 pp->alpha = *entry_start++;
1132 else
1134 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1135 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1136 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1137 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1139 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1141 #else
1142 pp = new_palette.entries;
1143 for (i = 0; i < new_palette.nentries; i++)
1146 if (new_palette.depth == 8)
1148 pp[i].red = *entry_start++;
1149 pp[i].green = *entry_start++;
1150 pp[i].blue = *entry_start++;
1151 pp[i].alpha = *entry_start++;
1153 else
1155 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1156 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1157 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1158 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1160 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1162 #endif
1164 /* discard all chunk data except the name and stash that */
1165 new_palette.name = (png_charp)chunkdata;
1167 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1169 png_free(png_ptr, chunkdata);
1170 png_free(png_ptr, new_palette.entries);
1172 #endif /* PNG_READ_sPLT_SUPPORTED */
1174 #if defined(PNG_READ_tRNS_SUPPORTED)
1175 void /* PRIVATE */
1176 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1178 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1180 png_debug(1, "in png_handle_tRNS\n");
1182 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1183 png_error(png_ptr, "Missing IHDR before tRNS");
1184 else if (png_ptr->mode & PNG_HAVE_IDAT)
1186 png_warning(png_ptr, "Invalid tRNS after IDAT");
1187 png_crc_finish(png_ptr, length);
1188 return;
1190 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1192 png_warning(png_ptr, "Duplicate tRNS chunk");
1193 png_crc_finish(png_ptr, length);
1194 return;
1197 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1199 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1201 /* Should be an error, but we can cope with it */
1202 png_warning(png_ptr, "Missing PLTE before tRNS");
1204 else if (length > (png_uint_32)png_ptr->num_palette)
1206 png_warning(png_ptr, "Incorrect tRNS chunk length");
1207 png_crc_finish(png_ptr, length);
1208 return;
1210 if (length == 0)
1212 png_warning(png_ptr, "Zero length tRNS chunk");
1213 png_crc_finish(png_ptr, length);
1214 return;
1217 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1218 png_ptr->num_trans = (png_uint_16)length;
1220 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1222 png_byte buf[6];
1224 if (length != 6)
1226 png_warning(png_ptr, "Incorrect tRNS chunk length");
1227 png_crc_finish(png_ptr, length);
1228 return;
1231 png_crc_read(png_ptr, buf, (png_size_t)length);
1232 png_ptr->num_trans = 1;
1233 png_ptr->trans_values.red = png_get_uint_16(buf);
1234 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1235 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1237 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1239 png_byte buf[6];
1241 if (length != 2)
1243 png_warning(png_ptr, "Incorrect tRNS chunk length");
1244 png_crc_finish(png_ptr, length);
1245 return;
1248 png_crc_read(png_ptr, buf, 2);
1249 png_ptr->num_trans = 1;
1250 png_ptr->trans_values.gray = png_get_uint_16(buf);
1252 else
1254 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1255 png_crc_finish(png_ptr, length);
1256 return;
1259 if (png_crc_finish(png_ptr, 0))
1260 return;
1262 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1263 &(png_ptr->trans_values));
1265 #endif
1267 #if defined(PNG_READ_bKGD_SUPPORTED)
1268 void /* PRIVATE */
1269 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1271 png_size_t truelen;
1272 png_byte buf[6];
1274 png_debug(1, "in png_handle_bKGD\n");
1276 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1277 png_error(png_ptr, "Missing IHDR before bKGD");
1278 else if (png_ptr->mode & PNG_HAVE_IDAT)
1280 png_warning(png_ptr, "Invalid bKGD after IDAT");
1281 png_crc_finish(png_ptr, length);
1282 return;
1284 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1285 !(png_ptr->mode & PNG_HAVE_PLTE))
1287 png_warning(png_ptr, "Missing PLTE before bKGD");
1288 png_crc_finish(png_ptr, length);
1289 return;
1291 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1293 png_warning(png_ptr, "Duplicate bKGD chunk");
1294 png_crc_finish(png_ptr, length);
1295 return;
1298 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1299 truelen = 1;
1300 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1301 truelen = 6;
1302 else
1303 truelen = 2;
1305 if (length != truelen)
1307 png_warning(png_ptr, "Incorrect bKGD chunk length");
1308 png_crc_finish(png_ptr, length);
1309 return;
1312 png_crc_read(png_ptr, buf, truelen);
1313 if (png_crc_finish(png_ptr, 0))
1314 return;
1316 /* We convert the index value into RGB components so that we can allow
1317 * arbitrary RGB values for background when we have transparency, and
1318 * so it is easy to determine the RGB values of the background color
1319 * from the info_ptr struct. */
1320 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1322 png_ptr->background.index = buf[0];
1323 if(info_ptr->num_palette)
1325 if(buf[0] > info_ptr->num_palette)
1327 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1328 return;
1330 png_ptr->background.red =
1331 (png_uint_16)png_ptr->palette[buf[0]].red;
1332 png_ptr->background.green =
1333 (png_uint_16)png_ptr->palette[buf[0]].green;
1334 png_ptr->background.blue =
1335 (png_uint_16)png_ptr->palette[buf[0]].blue;
1338 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1340 png_ptr->background.red =
1341 png_ptr->background.green =
1342 png_ptr->background.blue =
1343 png_ptr->background.gray = png_get_uint_16(buf);
1345 else
1347 png_ptr->background.red = png_get_uint_16(buf);
1348 png_ptr->background.green = png_get_uint_16(buf + 2);
1349 png_ptr->background.blue = png_get_uint_16(buf + 4);
1352 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1354 #endif
1356 #if defined(PNG_READ_hIST_SUPPORTED)
1357 void /* PRIVATE */
1358 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1360 int num, i;
1361 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1363 png_debug(1, "in png_handle_hIST\n");
1365 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1366 png_error(png_ptr, "Missing IHDR before hIST");
1367 else if (png_ptr->mode & PNG_HAVE_IDAT)
1369 png_warning(png_ptr, "Invalid hIST after IDAT");
1370 png_crc_finish(png_ptr, length);
1371 return;
1373 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1375 png_warning(png_ptr, "Missing PLTE before hIST");
1376 png_crc_finish(png_ptr, length);
1377 return;
1379 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1381 png_warning(png_ptr, "Duplicate hIST chunk");
1382 png_crc_finish(png_ptr, length);
1383 return;
1386 num = (int)length / 2 ;
1387 if (num != png_ptr->num_palette)
1389 png_warning(png_ptr, "Incorrect hIST chunk length");
1390 png_crc_finish(png_ptr, length);
1391 return;
1394 for (i = 0; i < num; i++)
1396 png_byte buf[2];
1398 png_crc_read(png_ptr, buf, 2);
1399 readbuf[i] = png_get_uint_16(buf);
1402 if (png_crc_finish(png_ptr, 0))
1403 return;
1405 png_set_hIST(png_ptr, info_ptr, readbuf);
1407 #endif
1409 #if defined(PNG_READ_pHYs_SUPPORTED)
1410 void /* PRIVATE */
1411 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1413 png_byte buf[9];
1414 png_uint_32 res_x, res_y;
1415 int unit_type;
1417 png_debug(1, "in png_handle_pHYs\n");
1419 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1420 png_error(png_ptr, "Missing IHDR before pHYs");
1421 else if (png_ptr->mode & PNG_HAVE_IDAT)
1423 png_warning(png_ptr, "Invalid pHYs after IDAT");
1424 png_crc_finish(png_ptr, length);
1425 return;
1427 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1429 png_warning(png_ptr, "Duplicate pHYs chunk");
1430 png_crc_finish(png_ptr, length);
1431 return;
1434 if (length != 9)
1436 png_warning(png_ptr, "Incorrect pHYs chunk length");
1437 png_crc_finish(png_ptr, length);
1438 return;
1441 png_crc_read(png_ptr, buf, 9);
1442 if (png_crc_finish(png_ptr, 0))
1443 return;
1445 res_x = png_get_uint_32(buf);
1446 res_y = png_get_uint_32(buf + 4);
1447 unit_type = buf[8];
1448 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1450 #endif
1452 #if defined(PNG_READ_oFFs_SUPPORTED)
1453 void /* PRIVATE */
1454 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1456 png_byte buf[9];
1457 png_int_32 offset_x, offset_y;
1458 int unit_type;
1460 png_debug(1, "in png_handle_oFFs\n");
1462 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1463 png_error(png_ptr, "Missing IHDR before oFFs");
1464 else if (png_ptr->mode & PNG_HAVE_IDAT)
1466 png_warning(png_ptr, "Invalid oFFs after IDAT");
1467 png_crc_finish(png_ptr, length);
1468 return;
1470 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1472 png_warning(png_ptr, "Duplicate oFFs chunk");
1473 png_crc_finish(png_ptr, length);
1474 return;
1477 if (length != 9)
1479 png_warning(png_ptr, "Incorrect oFFs chunk length");
1480 png_crc_finish(png_ptr, length);
1481 return;
1484 png_crc_read(png_ptr, buf, 9);
1485 if (png_crc_finish(png_ptr, 0))
1486 return;
1488 offset_x = png_get_int_32(buf);
1489 offset_y = png_get_int_32(buf + 4);
1490 unit_type = buf[8];
1491 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1493 #endif
1495 #if defined(PNG_READ_pCAL_SUPPORTED)
1496 /* read the pCAL chunk (described in the PNG Extensions document) */
1497 void /* PRIVATE */
1498 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1500 png_charp purpose;
1501 png_int_32 X0, X1;
1502 png_byte type, nparams;
1503 png_charp buf, units, endptr;
1504 png_charpp params;
1505 png_size_t slength;
1506 int i;
1508 png_debug(1, "in png_handle_pCAL\n");
1510 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1511 png_error(png_ptr, "Missing IHDR before pCAL");
1512 else if (png_ptr->mode & PNG_HAVE_IDAT)
1514 png_warning(png_ptr, "Invalid pCAL after IDAT");
1515 png_crc_finish(png_ptr, length);
1516 return;
1518 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1520 png_warning(png_ptr, "Duplicate pCAL chunk");
1521 png_crc_finish(png_ptr, length);
1522 return;
1525 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
1526 length + 1);
1527 purpose = (png_charp)png_malloc(png_ptr, length + 1);
1528 slength = (png_size_t)length;
1529 png_crc_read(png_ptr, (png_bytep)purpose, slength);
1531 if (png_crc_finish(png_ptr, 0))
1533 png_free(png_ptr, purpose);
1534 return;
1537 purpose[slength] = 0x00; /* null terminate the last string */
1539 png_debug(3, "Finding end of pCAL purpose string\n");
1540 for (buf = purpose; *buf; buf++)
1541 /* empty loop */ ;
1543 endptr = purpose + slength;
1545 /* We need to have at least 12 bytes after the purpose string
1546 in order to get the parameter information. */
1547 if (endptr <= buf + 12)
1549 png_warning(png_ptr, "Invalid pCAL data");
1550 png_free(png_ptr, purpose);
1551 return;
1554 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1555 X0 = png_get_int_32((png_bytep)buf+1);
1556 X1 = png_get_int_32((png_bytep)buf+5);
1557 type = buf[9];
1558 nparams = buf[10];
1559 units = buf + 11;
1561 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1562 /* Check that we have the right number of parameters for known
1563 equation types. */
1564 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1565 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1566 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1567 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1569 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1570 png_free(png_ptr, purpose);
1571 return;
1573 else if (type >= PNG_EQUATION_LAST)
1575 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1578 for (buf = units; *buf; buf++)
1579 /* Empty loop to move past the units string. */ ;
1581 png_debug(3, "Allocating pCAL parameters array\n");
1582 params = (png_charpp)png_malloc(png_ptr, (png_uint_32)(nparams
1583 *sizeof(png_charp))) ;
1585 /* Get pointers to the start of each parameter string. */
1586 for (i = 0; i < (int)nparams; i++)
1588 buf++; /* Skip the null string terminator from previous parameter. */
1590 png_debug1(3, "Reading pCAL parameter %d\n", i);
1591 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
1592 /* Empty loop to move past each parameter string */ ;
1594 /* Make sure we haven't run out of data yet */
1595 if (buf > endptr)
1597 png_warning(png_ptr, "Invalid pCAL data");
1598 png_free(png_ptr, purpose);
1599 png_free(png_ptr, params);
1600 return;
1604 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1605 units, params);
1607 png_free(png_ptr, purpose);
1608 png_free(png_ptr, params);
1610 #endif
1612 #if defined(PNG_READ_sCAL_SUPPORTED)
1613 /* read the sCAL chunk */
1614 void /* PRIVATE */
1615 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1617 png_charp buffer, ep;
1618 #ifdef PNG_FLOATING_POINT_SUPPORTED
1619 double width, height;
1620 png_charp vp;
1621 #else
1622 #ifdef PNG_FIXED_POINT_SUPPORTED
1623 png_charp swidth, sheight;
1624 #endif
1625 #endif
1626 png_size_t slength;
1628 png_debug(1, "in png_handle_sCAL\n");
1630 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1631 png_error(png_ptr, "Missing IHDR before sCAL");
1632 else if (png_ptr->mode & PNG_HAVE_IDAT)
1634 png_warning(png_ptr, "Invalid sCAL after IDAT");
1635 png_crc_finish(png_ptr, length);
1636 return;
1638 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1640 png_warning(png_ptr, "Duplicate sCAL chunk");
1641 png_crc_finish(png_ptr, length);
1642 return;
1645 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1646 length + 1);
1647 buffer = (png_charp)png_malloc(png_ptr, length + 1);
1648 slength = (png_size_t)length;
1649 png_crc_read(png_ptr, (png_bytep)buffer, slength);
1651 if (png_crc_finish(png_ptr, 0))
1653 png_free(png_ptr, buffer);
1654 return;
1657 buffer[slength] = 0x00; /* null terminate the last string */
1659 ep = buffer + 1; /* skip unit byte */
1661 #ifdef PNG_FLOATING_POINT_SUPPORTED
1662 width = strtod(ep, &vp);
1663 if (*vp)
1665 png_warning(png_ptr, "malformed width string in sCAL chunk");
1666 return;
1668 #else
1669 #ifdef PNG_FIXED_POINT_SUPPORTED
1670 swidth = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1);
1671 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1672 #endif
1673 #endif
1675 for (ep = buffer; *ep; ep++)
1676 /* empty loop */ ;
1677 ep++;
1679 #ifdef PNG_FLOATING_POINT_SUPPORTED
1680 height = strtod(ep, &vp);
1681 if (*vp)
1683 png_warning(png_ptr, "malformed height string in sCAL chunk");
1684 return;
1686 #else
1687 #ifdef PNG_FIXED_POINT_SUPPORTED
1688 sheight = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1);
1689 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1690 #endif
1691 #endif
1693 if (buffer + slength < ep
1694 #ifdef PNG_FLOATING_POINT_SUPPORTED
1695 || width <= 0. || height <= 0.
1696 #endif
1699 png_warning(png_ptr, "Invalid sCAL data");
1700 png_free(png_ptr, buffer);
1701 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1702 png_free(png_ptr, swidth);
1703 png_free(png_ptr, sheight);
1704 #endif
1705 return;
1709 #ifdef PNG_FLOATING_POINT_SUPPORTED
1710 png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1711 #else
1712 #ifdef PNG_FIXED_POINT_SUPPORTED
1713 png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1714 #endif
1715 #endif
1717 png_free(png_ptr, buffer);
1718 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1719 png_free(png_ptr, swidth);
1720 png_free(png_ptr, sheight);
1721 #endif
1723 #endif
1725 #if defined(PNG_READ_tIME_SUPPORTED)
1726 void /* PRIVATE */
1727 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1729 png_byte buf[7];
1730 png_time mod_time;
1732 png_debug(1, "in png_handle_tIME\n");
1734 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1735 png_error(png_ptr, "Out of place tIME chunk");
1736 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1738 png_warning(png_ptr, "Duplicate tIME chunk");
1739 png_crc_finish(png_ptr, length);
1740 return;
1743 if (png_ptr->mode & PNG_HAVE_IDAT)
1744 png_ptr->mode |= PNG_AFTER_IDAT;
1746 if (length != 7)
1748 png_warning(png_ptr, "Incorrect tIME chunk length");
1749 png_crc_finish(png_ptr, length);
1750 return;
1753 png_crc_read(png_ptr, buf, 7);
1754 if (png_crc_finish(png_ptr, 0))
1755 return;
1757 mod_time.second = buf[6];
1758 mod_time.minute = buf[5];
1759 mod_time.hour = buf[4];
1760 mod_time.day = buf[3];
1761 mod_time.month = buf[2];
1762 mod_time.year = png_get_uint_16(buf);
1764 png_set_tIME(png_ptr, info_ptr, &mod_time);
1766 #endif
1768 #if defined(PNG_READ_tEXt_SUPPORTED)
1769 /* Note: this does not properly handle chunks that are > 64K under DOS */
1770 void /* PRIVATE */
1771 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1773 png_textp text_ptr;
1774 png_charp key;
1775 png_charp text;
1776 png_uint_32 skip = 0;
1777 png_size_t slength;
1779 png_debug(1, "in png_handle_tEXt\n");
1781 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1782 png_error(png_ptr, "Missing IHDR before tEXt");
1784 if (png_ptr->mode & PNG_HAVE_IDAT)
1785 png_ptr->mode |= PNG_AFTER_IDAT;
1787 #ifdef PNG_MAX_MALLOC_64K
1788 if (length > (png_uint_32)65535L)
1790 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1791 skip = length - (png_uint_32)65535L;
1792 length = (png_uint_32)65535L;
1794 #endif
1796 key = (png_charp)png_malloc(png_ptr, length + 1);
1797 slength = (png_size_t)length;
1798 png_crc_read(png_ptr, (png_bytep)key, slength);
1800 if (png_crc_finish(png_ptr, skip))
1802 png_free(png_ptr, key);
1803 return;
1806 key[slength] = 0x00;
1808 for (text = key; *text; text++)
1809 /* empty loop to find end of key */ ;
1811 if (text != key + slength)
1812 text++;
1814 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1815 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1816 text_ptr->key = key;
1817 #ifdef PNG_iTXt_SUPPORTED
1818 text_ptr->lang = NULL;
1819 text_ptr->lang_key = NULL;
1820 text_ptr->itxt_length = 0;
1821 #endif
1822 text_ptr->text = text;
1823 text_ptr->text_length = png_strlen(text);
1825 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1827 png_free(png_ptr, key);
1828 png_free(png_ptr, text_ptr);
1830 #endif
1832 #if defined(PNG_READ_zTXt_SUPPORTED)
1833 /* note: this does not correctly handle chunks that are > 64K under DOS */
1834 void /* PRIVATE */
1835 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1837 png_textp text_ptr;
1838 png_charp chunkdata;
1839 png_charp text;
1840 int comp_type;
1841 png_size_t slength, prefix_len, data_len;
1843 png_debug(1, "in png_handle_zTXt\n");
1844 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1845 png_error(png_ptr, "Missing IHDR before zTXt");
1847 if (png_ptr->mode & PNG_HAVE_IDAT)
1848 png_ptr->mode |= PNG_AFTER_IDAT;
1850 #ifdef PNG_MAX_MALLOC_64K
1851 /* We will no doubt have problems with chunks even half this size, but
1852 there is no hard and fast rule to tell us where to stop. */
1853 if (length > (png_uint_32)65535L)
1855 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1856 png_crc_finish(png_ptr, length);
1857 return;
1859 #endif
1861 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1862 slength = (png_size_t)length;
1863 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1864 if (png_crc_finish(png_ptr, 0))
1866 png_free(png_ptr, chunkdata);
1867 return;
1870 chunkdata[slength] = 0x00;
1872 for (text = chunkdata; *text; text++)
1873 /* empty loop */ ;
1875 /* zTXt must have some text after the chunkdataword */
1876 if (text == chunkdata + slength)
1878 comp_type = PNG_TEXT_COMPRESSION_NONE;
1879 png_warning(png_ptr, "Zero length zTXt chunk");
1881 else
1883 comp_type = *(++text);
1884 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
1886 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
1887 comp_type = PNG_TEXT_COMPRESSION_zTXt;
1889 text++; /* skip the compression_method byte */
1891 prefix_len = text - chunkdata;
1893 chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
1894 (png_size_t)length, prefix_len, &data_len);
1896 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1897 text_ptr->compression = comp_type;
1898 text_ptr->key = chunkdata;
1899 #ifdef PNG_iTXt_SUPPORTED
1900 text_ptr->lang = NULL;
1901 text_ptr->lang_key = NULL;
1902 text_ptr->itxt_length = 0;
1903 #endif
1904 text_ptr->text = chunkdata + prefix_len;
1905 text_ptr->text_length = data_len;
1907 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1909 png_free(png_ptr, text_ptr);
1910 png_free(png_ptr, chunkdata);
1912 #endif
1914 #if defined(PNG_READ_iTXt_SUPPORTED)
1915 /* note: this does not correctly handle chunks that are > 64K under DOS */
1916 void /* PRIVATE */
1917 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1919 png_textp text_ptr;
1920 png_charp chunkdata;
1921 png_charp key, lang, text, lang_key;
1922 int comp_flag;
1923 int comp_type = 0;
1924 png_size_t slength, prefix_len, data_len;
1926 png_debug(1, "in png_handle_iTXt\n");
1928 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1929 png_error(png_ptr, "Missing IHDR before iTXt");
1931 if (png_ptr->mode & PNG_HAVE_IDAT)
1932 png_ptr->mode |= PNG_AFTER_IDAT;
1934 #ifdef PNG_MAX_MALLOC_64K
1935 /* We will no doubt have problems with chunks even half this size, but
1936 there is no hard and fast rule to tell us where to stop. */
1937 if (length > (png_uint_32)65535L)
1939 png_warning(png_ptr,"iTXt chunk too large to fit in memory");
1940 png_crc_finish(png_ptr, length);
1941 return;
1943 #endif
1945 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1946 slength = (png_size_t)length;
1947 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1948 if (png_crc_finish(png_ptr, 0))
1950 png_free(png_ptr, chunkdata);
1951 return;
1954 chunkdata[slength] = 0x00;
1956 for (lang = chunkdata; *lang; lang++)
1957 /* empty loop */ ;
1958 lang++; /* skip NUL separator */
1960 /* iTXt must have a language tag (possibly empty), two compression bytes,
1961 translated keyword (possibly empty), and possibly some text after the
1962 keyword */
1964 if (lang >= chunkdata + slength)
1966 comp_flag = PNG_TEXT_COMPRESSION_NONE;
1967 png_warning(png_ptr, "Zero length iTXt chunk");
1969 else
1971 comp_flag = *lang++;
1972 comp_type = *lang++;
1975 for (lang_key = lang; *lang_key; lang_key++)
1976 /* empty loop */ ;
1977 lang_key++; /* skip NUL separator */
1979 for (text = lang_key; *text; text++)
1980 /* empty loop */ ;
1981 text++; /* skip NUL separator */
1983 prefix_len = text - chunkdata;
1985 key=chunkdata;
1986 if (comp_flag)
1987 chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
1988 (size_t)length, prefix_len, &data_len);
1989 else
1990 data_len=png_strlen(chunkdata + prefix_len);
1991 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1992 text_ptr->compression = (int)comp_flag + 1;
1993 text_ptr->lang_key = chunkdata+(lang_key-key);
1994 text_ptr->lang = chunkdata+(lang-key);
1995 text_ptr->itxt_length = data_len;
1996 text_ptr->text_length = 0;
1997 text_ptr->key = chunkdata;
1998 text_ptr->text = chunkdata + prefix_len;
2000 png_set_text(png_ptr, info_ptr, text_ptr, 1);
2002 png_free(png_ptr, text_ptr);
2003 png_free(png_ptr, chunkdata);
2005 #endif
2007 /* This function is called when we haven't found a handler for a
2008 chunk. If there isn't a problem with the chunk itself (ie bad
2009 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2010 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2011 case it will be saved away to be written out later. */
2012 void /* PRIVATE */
2013 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2015 png_uint_32 skip = 0;
2017 png_debug(1, "in png_handle_unknown\n");
2019 if (png_ptr->mode & PNG_HAVE_IDAT)
2021 #ifdef PNG_USE_LOCAL_ARRAYS
2022 PNG_IDAT;
2023 #endif
2024 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2025 png_ptr->mode |= PNG_AFTER_IDAT;
2028 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
2030 if (!(png_ptr->chunk_name[0] & 0x20))
2032 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2033 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2034 HANDLE_CHUNK_ALWAYS
2035 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2036 && png_ptr->read_user_chunk_fn == (png_user_chunk_ptr)NULL
2037 #endif
2039 #endif
2040 png_chunk_error(png_ptr, "unknown critical chunk");
2043 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2044 if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
2046 png_unknown_chunk chunk;
2048 #ifdef PNG_MAX_MALLOC_64K
2049 if (length > (png_uint_32)65535L)
2051 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2052 skip = length - (png_uint_32)65535L;
2053 length = (png_uint_32)65535L;
2055 #endif
2056 png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
2057 chunk.data = (png_bytep)png_malloc(png_ptr, length);
2058 png_crc_read(png_ptr, chunk.data, length);
2059 chunk.size = length;
2060 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2061 if(png_ptr->read_user_chunk_fn != (png_user_chunk_ptr)NULL)
2063 /* callback to user unknown chunk handler */
2064 if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
2066 if (!(png_ptr->chunk_name[0] & 0x20))
2067 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2068 HANDLE_CHUNK_ALWAYS)
2069 png_chunk_error(png_ptr, "unknown critical chunk");
2070 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2073 else
2074 #endif
2075 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2076 png_free(png_ptr, chunk.data);
2078 else
2079 #endif
2080 skip = length;
2082 png_crc_finish(png_ptr, skip);
2084 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2085 if (info_ptr == NULL)
2086 /* quiet compiler warnings about unused info_ptr */ ;
2087 #endif
2090 /* This function is called to verify that a chunk name is valid.
2091 This function can't have the "critical chunk check" incorporated
2092 into it, since in the future we will need to be able to call user
2093 functions to handle unknown critical chunks after we check that
2094 the chunk name itself is valid. */
2096 #define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
2098 void /* PRIVATE */
2099 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2101 png_debug(1, "in png_check_chunk_name\n");
2102 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2103 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2105 png_chunk_error(png_ptr, "invalid chunk type");
2109 /* Combines the row recently read in with the existing pixels in the
2110 row. This routine takes care of alpha and transparency if requested.
2111 This routine also handles the two methods of progressive display
2112 of interlaced images, depending on the mask value.
2113 The mask value describes which pixels are to be combined with
2114 the row. The pattern always repeats every 8 pixels, so just 8
2115 bits are needed. A one indicates the pixel is to be combined,
2116 a zero indicates the pixel is to be skipped. This is in addition
2117 to any alpha or transparency value associated with the pixel. If
2118 you want all pixels to be combined, pass 0xff (255) in mask. */
2119 #ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
2120 void /* PRIVATE */
2121 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2123 png_debug(1,"in png_combine_row\n");
2124 if (mask == 0xff)
2126 png_memcpy(row, png_ptr->row_buf + 1,
2127 (png_size_t)((png_ptr->width *
2128 png_ptr->row_info.pixel_depth + 7) >> 3));
2130 else
2132 switch (png_ptr->row_info.pixel_depth)
2134 case 1:
2136 png_bytep sp = png_ptr->row_buf + 1;
2137 png_bytep dp = row;
2138 int s_inc, s_start, s_end;
2139 int m = 0x80;
2140 int shift;
2141 png_uint_32 i;
2142 png_uint_32 row_width = png_ptr->width;
2144 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2145 if (png_ptr->transformations & PNG_PACKSWAP)
2147 s_start = 0;
2148 s_end = 7;
2149 s_inc = 1;
2151 else
2152 #endif
2154 s_start = 7;
2155 s_end = 0;
2156 s_inc = -1;
2159 shift = s_start;
2161 for (i = 0; i < row_width; i++)
2163 if (m & mask)
2165 int value;
2167 value = (*sp >> shift) & 0x01;
2168 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2169 *dp |= (png_byte)(value << shift);
2172 if (shift == s_end)
2174 shift = s_start;
2175 sp++;
2176 dp++;
2178 else
2179 shift += s_inc;
2181 if (m == 1)
2182 m = 0x80;
2183 else
2184 m >>= 1;
2186 break;
2188 case 2:
2190 png_bytep sp = png_ptr->row_buf + 1;
2191 png_bytep dp = row;
2192 int s_start, s_end, s_inc;
2193 int m = 0x80;
2194 int shift;
2195 png_uint_32 i;
2196 png_uint_32 row_width = png_ptr->width;
2197 int value;
2199 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2200 if (png_ptr->transformations & PNG_PACKSWAP)
2202 s_start = 0;
2203 s_end = 6;
2204 s_inc = 2;
2206 else
2207 #endif
2209 s_start = 6;
2210 s_end = 0;
2211 s_inc = -2;
2214 shift = s_start;
2216 for (i = 0; i < row_width; i++)
2218 if (m & mask)
2220 value = (*sp >> shift) & 0x03;
2221 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2222 *dp |= (png_byte)(value << shift);
2225 if (shift == s_end)
2227 shift = s_start;
2228 sp++;
2229 dp++;
2231 else
2232 shift += s_inc;
2233 if (m == 1)
2234 m = 0x80;
2235 else
2236 m >>= 1;
2238 break;
2240 case 4:
2242 png_bytep sp = png_ptr->row_buf + 1;
2243 png_bytep dp = row;
2244 int s_start, s_end, s_inc;
2245 int m = 0x80;
2246 int shift;
2247 png_uint_32 i;
2248 png_uint_32 row_width = png_ptr->width;
2249 int value;
2251 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2252 if (png_ptr->transformations & PNG_PACKSWAP)
2254 s_start = 0;
2255 s_end = 4;
2256 s_inc = 4;
2258 else
2259 #endif
2261 s_start = 4;
2262 s_end = 0;
2263 s_inc = -4;
2265 shift = s_start;
2267 for (i = 0; i < row_width; i++)
2269 if (m & mask)
2271 value = (*sp >> shift) & 0xf;
2272 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2273 *dp |= (png_byte)(value << shift);
2276 if (shift == s_end)
2278 shift = s_start;
2279 sp++;
2280 dp++;
2282 else
2283 shift += s_inc;
2284 if (m == 1)
2285 m = 0x80;
2286 else
2287 m >>= 1;
2289 break;
2291 default:
2293 png_bytep sp = png_ptr->row_buf + 1;
2294 png_bytep dp = row;
2295 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2296 png_uint_32 i;
2297 png_uint_32 row_width = png_ptr->width;
2298 png_byte m = 0x80;
2301 for (i = 0; i < row_width; i++)
2303 if (m & mask)
2305 png_memcpy(dp, sp, pixel_bytes);
2308 sp += pixel_bytes;
2309 dp += pixel_bytes;
2311 if (m == 1)
2312 m = 0x80;
2313 else
2314 m >>= 1;
2316 break;
2321 #endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
2323 #ifdef PNG_READ_INTERLACING_SUPPORTED
2324 #ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */
2325 /* OLD pre-1.0.9 interface:
2326 void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2327 png_uint_32 transformations)
2329 void /* PRIVATE */
2330 png_do_read_interlace(png_structp png_ptr)
2332 png_row_infop row_info = &(png_ptr->row_info);
2333 png_bytep row = png_ptr->row_buf + 1;
2334 int pass = png_ptr->pass;
2335 png_uint_32 transformations = png_ptr->transformations;
2336 #ifdef PNG_USE_LOCAL_ARRAYS
2337 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2338 /* offset to next interlace block */
2339 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2340 #endif
2342 png_debug(1,"in png_do_read_interlace (stock C version)\n");
2343 if (row != NULL && row_info != NULL)
2345 png_uint_32 final_width;
2347 final_width = row_info->width * png_pass_inc[pass];
2349 switch (row_info->pixel_depth)
2351 case 1:
2353 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2354 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2355 int sshift, dshift;
2356 int s_start, s_end, s_inc;
2357 int jstop = png_pass_inc[pass];
2358 png_byte v;
2359 png_uint_32 i;
2360 int j;
2362 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2363 if (transformations & PNG_PACKSWAP)
2365 sshift = (int)((row_info->width + 7) & 0x07);
2366 dshift = (int)((final_width + 7) & 0x07);
2367 s_start = 7;
2368 s_end = 0;
2369 s_inc = -1;
2371 else
2372 #endif
2374 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2375 dshift = 7 - (int)((final_width + 7) & 0x07);
2376 s_start = 0;
2377 s_end = 7;
2378 s_inc = 1;
2381 for (i = 0; i < row_info->width; i++)
2383 v = (png_byte)((*sp >> sshift) & 0x01);
2384 for (j = 0; j < jstop; j++)
2386 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2387 *dp |= (png_byte)(v << dshift);
2388 if (dshift == s_end)
2390 dshift = s_start;
2391 dp--;
2393 else
2394 dshift += s_inc;
2396 if (sshift == s_end)
2398 sshift = s_start;
2399 sp--;
2401 else
2402 sshift += s_inc;
2404 break;
2406 case 2:
2408 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2409 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2410 int sshift, dshift;
2411 int s_start, s_end, s_inc;
2412 int jstop = png_pass_inc[pass];
2413 png_uint_32 i;
2415 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2416 if (transformations & PNG_PACKSWAP)
2418 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2419 dshift = (int)(((final_width + 3) & 0x03) << 1);
2420 s_start = 6;
2421 s_end = 0;
2422 s_inc = -2;
2424 else
2425 #endif
2427 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2428 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2429 s_start = 0;
2430 s_end = 6;
2431 s_inc = 2;
2434 for (i = 0; i < row_info->width; i++)
2436 png_byte v;
2437 int j;
2439 v = (png_byte)((*sp >> sshift) & 0x03);
2440 for (j = 0; j < jstop; j++)
2442 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2443 *dp |= (png_byte)(v << dshift);
2444 if (dshift == s_end)
2446 dshift = s_start;
2447 dp--;
2449 else
2450 dshift += s_inc;
2452 if (sshift == s_end)
2454 sshift = s_start;
2455 sp--;
2457 else
2458 sshift += s_inc;
2460 break;
2462 case 4:
2464 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2465 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2466 int sshift, dshift;
2467 int s_start, s_end, s_inc;
2468 png_uint_32 i;
2469 int jstop = png_pass_inc[pass];
2471 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2472 if (transformations & PNG_PACKSWAP)
2474 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2475 dshift = (int)(((final_width + 1) & 0x01) << 2);
2476 s_start = 4;
2477 s_end = 0;
2478 s_inc = -4;
2480 else
2481 #endif
2483 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2484 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2485 s_start = 0;
2486 s_end = 4;
2487 s_inc = 4;
2490 for (i = 0; i < row_info->width; i++)
2492 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2493 int j;
2495 for (j = 0; j < jstop; j++)
2497 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2498 *dp |= (png_byte)(v << dshift);
2499 if (dshift == s_end)
2501 dshift = s_start;
2502 dp--;
2504 else
2505 dshift += s_inc;
2507 if (sshift == s_end)
2509 sshift = s_start;
2510 sp--;
2512 else
2513 sshift += s_inc;
2515 break;
2517 default:
2519 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2520 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2521 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2523 int jstop = png_pass_inc[pass];
2524 png_uint_32 i;
2526 for (i = 0; i < row_info->width; i++)
2528 png_byte v[8];
2529 int j;
2531 png_memcpy(v, sp, pixel_bytes);
2532 for (j = 0; j < jstop; j++)
2534 png_memcpy(dp, v, pixel_bytes);
2535 dp -= pixel_bytes;
2537 sp -= pixel_bytes;
2539 break;
2542 row_info->width = final_width;
2543 row_info->rowbytes = ((final_width *
2544 (png_uint_32)row_info->pixel_depth + 7) >> 3);
2546 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2547 /* silence compiler warning */
2548 if (transformations)
2549 return;
2550 #endif
2552 #endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
2553 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2555 #ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
2556 void /* PRIVATE */
2557 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2558 png_bytep prev_row, int filter)
2560 png_debug(1, "in png_read_filter_row\n");
2561 png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
2562 switch (filter)
2564 case PNG_FILTER_VALUE_NONE:
2565 break;
2566 case PNG_FILTER_VALUE_SUB:
2568 png_uint_32 i;
2569 png_uint_32 istop = row_info->rowbytes;
2570 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2571 png_bytep rp = row + bpp;
2572 png_bytep lp = row;
2574 for (i = bpp; i < istop; i++)
2576 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2577 rp++;
2579 break;
2581 case PNG_FILTER_VALUE_UP:
2583 png_uint_32 i;
2584 png_uint_32 istop = row_info->rowbytes;
2585 png_bytep rp = row;
2586 png_bytep pp = prev_row;
2588 for (i = 0; i < istop; i++)
2590 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2591 rp++;
2593 break;
2595 case PNG_FILTER_VALUE_AVG:
2597 png_uint_32 i;
2598 png_bytep rp = row;
2599 png_bytep pp = prev_row;
2600 png_bytep lp = row;
2601 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2602 png_uint_32 istop = row_info->rowbytes - bpp;
2604 for (i = 0; i < bpp; i++)
2606 *rp = (png_byte)(((int)(*rp) +
2607 ((int)(*pp++) / 2 )) & 0xff);
2608 rp++;
2611 for (i = 0; i < istop; i++)
2613 *rp = (png_byte)(((int)(*rp) +
2614 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2615 rp++;
2617 break;
2619 case PNG_FILTER_VALUE_PAETH:
2621 png_uint_32 i;
2622 png_bytep rp = row;
2623 png_bytep pp = prev_row;
2624 png_bytep lp = row;
2625 png_bytep cp = prev_row;
2626 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2627 png_uint_32 istop=row_info->rowbytes - bpp;
2629 for (i = 0; i < bpp; i++)
2631 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2632 rp++;
2635 for (i = 0; i < istop; i++) /* use leftover rp,pp */
2637 int a, b, c, pa, pb, pc, p;
2639 a = *lp++;
2640 b = *pp++;
2641 c = *cp++;
2643 p = b - c;
2644 pc = a - c;
2646 #ifdef PNG_USE_ABS
2647 pa = abs(p);
2648 pb = abs(pc);
2649 pc = abs(p + pc);
2650 #else
2651 pa = p < 0 ? -p : p;
2652 pb = pc < 0 ? -pc : pc;
2653 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2654 #endif
2657 if (pa <= pb && pa <= pc)
2658 p = a;
2659 else if (pb <= pc)
2660 p = b;
2661 else
2662 p = c;
2665 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2667 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2668 rp++;
2670 break;
2672 default:
2673 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2674 *row=0;
2675 break;
2678 #endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
2680 void /* PRIVATE */
2681 png_read_finish_row(png_structp png_ptr)
2683 #ifdef PNG_USE_LOCAL_ARRAYS
2684 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2686 /* start of interlace block */
2687 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2689 /* offset to next interlace block */
2690 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2692 /* start of interlace block in the y direction */
2693 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2695 /* offset to next interlace block in the y direction */
2696 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2697 #endif
2699 png_debug(1, "in png_read_finish_row\n");
2700 png_ptr->row_number++;
2701 if (png_ptr->row_number < png_ptr->num_rows)
2702 return;
2704 if (png_ptr->interlaced)
2706 png_ptr->row_number = 0;
2707 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
2710 png_ptr->pass++;
2711 if (png_ptr->pass >= 7)
2712 break;
2713 png_ptr->iwidth = (png_ptr->width +
2714 png_pass_inc[png_ptr->pass] - 1 -
2715 png_pass_start[png_ptr->pass]) /
2716 png_pass_inc[png_ptr->pass];
2717 png_ptr->irowbytes = ((png_ptr->iwidth *
2718 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2720 if (!(png_ptr->transformations & PNG_INTERLACE))
2722 png_ptr->num_rows = (png_ptr->height +
2723 png_pass_yinc[png_ptr->pass] - 1 -
2724 png_pass_ystart[png_ptr->pass]) /
2725 png_pass_yinc[png_ptr->pass];
2726 if (!(png_ptr->num_rows))
2727 continue;
2729 else /* if (png_ptr->transformations & PNG_INTERLACE) */
2730 break;
2731 } while (png_ptr->iwidth == 0);
2733 if (png_ptr->pass < 7)
2734 return;
2737 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
2739 #ifdef PNG_USE_LOCAL_ARRAYS
2740 PNG_IDAT;
2741 #endif
2742 char extra;
2743 int ret;
2745 png_ptr->zstream.next_out = (Byte *)&extra;
2746 png_ptr->zstream.avail_out = (uInt)1;
2747 for(;;)
2749 if (!(png_ptr->zstream.avail_in))
2751 while (!png_ptr->idat_size)
2753 png_byte chunk_length[4];
2755 png_crc_finish(png_ptr, 0);
2757 png_read_data(png_ptr, chunk_length, 4);
2758 png_ptr->idat_size = png_get_uint_32(chunk_length);
2760 png_reset_crc(png_ptr);
2761 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2762 if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
2763 png_error(png_ptr, "Not enough image data");
2766 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2767 png_ptr->zstream.next_in = png_ptr->zbuf;
2768 if (png_ptr->zbuf_size > png_ptr->idat_size)
2769 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2770 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2771 png_ptr->idat_size -= png_ptr->zstream.avail_in;
2773 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
2774 if (ret == Z_STREAM_END)
2776 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
2777 png_ptr->idat_size)
2778 png_error(png_ptr, "Extra compressed data");
2779 png_ptr->mode |= PNG_AFTER_IDAT;
2780 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2781 break;
2783 if (ret != Z_OK)
2784 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
2785 "Decompression Error");
2787 if (!(png_ptr->zstream.avail_out))
2788 png_error(png_ptr, "Extra compressed data");
2791 png_ptr->zstream.avail_out = 0;
2794 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
2795 png_error(png_ptr, "Extra compression data");
2797 inflateReset(&png_ptr->zstream);
2799 png_ptr->mode |= PNG_AFTER_IDAT;
2802 void /* PRIVATE */
2803 png_read_start_row(png_structp png_ptr)
2805 #ifdef PNG_USE_LOCAL_ARRAYS
2806 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2808 /* start of interlace block */
2809 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2811 /* offset to next interlace block */
2812 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2814 /* start of interlace block in the y direction */
2815 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2817 /* offset to next interlace block in the y direction */
2818 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2819 #endif
2821 int max_pixel_depth;
2822 png_uint_32 row_bytes;
2824 png_debug(1, "in png_read_start_row\n");
2825 png_ptr->zstream.avail_in = 0;
2826 png_init_read_transformations(png_ptr);
2827 if (png_ptr->interlaced)
2829 if (!(png_ptr->transformations & PNG_INTERLACE))
2830 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2831 png_pass_ystart[0]) / png_pass_yinc[0];
2832 else
2833 png_ptr->num_rows = png_ptr->height;
2835 png_ptr->iwidth = (png_ptr->width +
2836 png_pass_inc[png_ptr->pass] - 1 -
2837 png_pass_start[png_ptr->pass]) /
2838 png_pass_inc[png_ptr->pass];
2840 row_bytes = ((png_ptr->iwidth *
2841 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2842 png_ptr->irowbytes = (png_size_t)row_bytes;
2843 if((png_uint_32)png_ptr->irowbytes != row_bytes)
2844 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
2846 else
2848 png_ptr->num_rows = png_ptr->height;
2849 png_ptr->iwidth = png_ptr->width;
2850 png_ptr->irowbytes = png_ptr->rowbytes + 1;
2852 max_pixel_depth = png_ptr->pixel_depth;
2854 #if defined(PNG_READ_PACK_SUPPORTED)
2855 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
2856 max_pixel_depth = 8;
2857 #endif
2859 #if defined(PNG_READ_EXPAND_SUPPORTED)
2860 if (png_ptr->transformations & PNG_EXPAND)
2862 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2864 if (png_ptr->num_trans)
2865 max_pixel_depth = 32;
2866 else
2867 max_pixel_depth = 24;
2869 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2871 if (max_pixel_depth < 8)
2872 max_pixel_depth = 8;
2873 if (png_ptr->num_trans)
2874 max_pixel_depth *= 2;
2876 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2878 if (png_ptr->num_trans)
2880 max_pixel_depth *= 4;
2881 max_pixel_depth /= 3;
2885 #endif
2887 #if defined(PNG_READ_FILLER_SUPPORTED)
2888 if (png_ptr->transformations & (PNG_FILLER))
2890 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2891 max_pixel_depth = 32;
2892 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2894 if (max_pixel_depth <= 8)
2895 max_pixel_depth = 16;
2896 else
2897 max_pixel_depth = 32;
2899 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2901 if (max_pixel_depth <= 32)
2902 max_pixel_depth = 32;
2903 else
2904 max_pixel_depth = 64;
2907 #endif
2909 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2910 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
2912 if (
2913 #if defined(PNG_READ_EXPAND_SUPPORTED)
2914 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
2915 #endif
2916 #if defined(PNG_READ_FILLER_SUPPORTED)
2917 (png_ptr->transformations & (PNG_FILLER)) ||
2918 #endif
2919 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2921 if (max_pixel_depth <= 16)
2922 max_pixel_depth = 32;
2923 else
2924 max_pixel_depth = 64;
2926 else
2928 if (max_pixel_depth <= 8)
2930 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2931 max_pixel_depth = 32;
2932 else
2933 max_pixel_depth = 24;
2935 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2936 max_pixel_depth = 64;
2937 else
2938 max_pixel_depth = 48;
2941 #endif
2943 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
2944 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
2945 if(png_ptr->transformations & PNG_USER_TRANSFORM)
2947 int user_pixel_depth=png_ptr->user_transform_depth*
2948 png_ptr->user_transform_channels;
2949 if(user_pixel_depth > max_pixel_depth)
2950 max_pixel_depth=user_pixel_depth;
2952 #endif
2954 /* align the width on the next larger 8 pixels. Mainly used
2955 for interlacing */
2956 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
2957 /* calculate the maximum bytes needed, adding a byte and a pixel
2958 for safety's sake */
2959 row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
2960 1 + ((max_pixel_depth + 7) >> 3);
2961 #ifdef PNG_MAX_MALLOC_64K
2962 if (row_bytes > (png_uint_32)65536L)
2963 png_error(png_ptr, "This image requires a row greater than 64KB");
2964 #endif
2965 png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, row_bytes);
2966 png_ptr->row_buf_size = row_bytes;
2968 #ifdef PNG_MAX_MALLOC_64K
2969 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
2970 png_error(png_ptr, "This image requires a row greater than 64KB");
2971 #endif
2972 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
2973 png_ptr->rowbytes + 1));
2975 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
2977 png_debug1(3, "width = %lu,\n", png_ptr->width);
2978 png_debug1(3, "height = %lu,\n", png_ptr->height);
2979 png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
2980 png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
2981 png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
2982 png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
2984 png_ptr->flags |= PNG_FLAG_ROW_INIT;