2 /* pngrutil.c - utilities to read a PNG file
\r
4 * Last changed in libpng 1.2.33 [October 31, 2008]
\r
5 * For conditions of distribution and use, see copyright notice in png.h
\r
6 * Copyright (c) 1998-2008 Glenn Randers-Pehrson
\r
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
\r
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
\r
10 * This file contains routines that are only called from within
\r
11 * libpng itself during the course of reading an image.
\r
14 #define PNG_INTERNAL
\r
16 #if defined(PNG_READ_SUPPORTED)
\r
18 #if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
\r
19 # define WIN32_WCE_OLD
\r
22 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
23 # if defined(WIN32_WCE_OLD)
\r
24 /* strtod() function is not supported on WindowsCE */
\r
25 __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr)
\r
31 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
\r
32 str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
\r
35 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
\r
36 result = wcstod(str, &end);
\r
37 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
\r
38 *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
\r
39 png_free(png_ptr, str);
\r
44 # define png_strtod(p,a,b) strtod(a,b)
\r
49 png_get_uint_31(png_structp png_ptr, png_bytep buf)
\r
51 #ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
\r
52 png_uint_32 i = png_get_uint_32(buf);
\r
54 /* Avoid an extra function call by inlining the result. */
\r
55 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
\r
56 ((png_uint_32)(*(buf + 1)) << 16) +
\r
57 ((png_uint_32)(*(buf + 2)) << 8) +
\r
58 (png_uint_32)(*(buf + 3));
\r
60 if (i > PNG_UINT_31_MAX)
\r
61 png_error(png_ptr, "PNG unsigned integer out of range.");
\r
64 #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
\r
65 /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
\r
67 png_get_uint_32(png_bytep buf)
\r
69 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
\r
70 ((png_uint_32)(*(buf + 1)) << 16) +
\r
71 ((png_uint_32)(*(buf + 2)) << 8) +
\r
72 (png_uint_32)(*(buf + 3));
\r
77 /* Grab a signed 32-bit integer from a buffer in big-endian format. The
\r
78 * data is stored in the PNG file in two's complement format, and it is
\r
79 * assumed that the machine format for signed integers is the same. */
\r
81 png_get_int_32(png_bytep buf)
\r
83 png_int_32 i = ((png_int_32)(*buf) << 24) +
\r
84 ((png_int_32)(*(buf + 1)) << 16) +
\r
85 ((png_int_32)(*(buf + 2)) << 8) +
\r
86 (png_int_32)(*(buf + 3));
\r
91 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
\r
93 png_get_uint_16(png_bytep buf)
\r
95 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
\r
96 (png_uint_16)(*(buf + 1)));
\r
100 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
\r
102 /* Read the chunk header (length + type name).
\r
103 * Put the type name into png_ptr->chunk_name, and return the length.
\r
105 png_uint_32 /* PRIVATE */
\r
106 png_read_chunk_header(png_structp png_ptr)
\r
109 png_uint_32 length;
\r
111 /* read the length and the chunk name */
\r
112 png_read_data(png_ptr, buf, 8);
\r
113 length = png_get_uint_31(png_ptr, buf);
\r
115 /* put the chunk name into png_ptr->chunk_name */
\r
116 png_memcpy(png_ptr->chunk_name, buf + 4, 4);
\r
118 png_debug2(0, "Reading %s chunk, length = %lu\n",
\r
119 png_ptr->chunk_name, length);
\r
121 /* reset the crc and run it over the chunk name */
\r
122 png_reset_crc(png_ptr);
\r
123 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
\r
125 /* check to see if chunk name is valid */
\r
126 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
\r
131 /* Read data, and (optionally) run it through the CRC. */
\r
133 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
\r
135 if (png_ptr == NULL) return;
\r
136 png_read_data(png_ptr, buf, length);
\r
137 png_calculate_crc(png_ptr, buf, length);
\r
140 /* Optionally skip data and then check the CRC. Depending on whether we
\r
141 are reading a ancillary or critical chunk, and how the program has set
\r
142 things up, we may calculate the CRC on the data and print a message.
\r
143 Returns '1' if there was a CRC error, '0' otherwise. */
\r
145 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
\r
148 png_size_t istop = png_ptr->zbuf_size;
\r
150 for (i = (png_size_t)skip; i > istop; i -= istop)
\r
152 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
\r
156 png_crc_read(png_ptr, png_ptr->zbuf, i);
\r
159 if (png_crc_error(png_ptr))
\r
161 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
\r
162 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
\r
163 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
\r
164 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
\r
166 png_chunk_warning(png_ptr, "CRC error");
\r
170 png_chunk_error(png_ptr, "CRC error");
\r
178 /* Compare the CRC stored in the PNG file with that calculated by libpng from
\r
179 the data it has read thus far. */
\r
181 png_crc_error(png_structp png_ptr)
\r
183 png_byte crc_bytes[4];
\r
187 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
\r
189 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
\r
190 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
\r
193 else /* critical */
\r
195 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
\r
199 png_read_data(png_ptr, crc_bytes, 4);
\r
203 crc = png_get_uint_32(crc_bytes);
\r
204 return ((int)(crc != png_ptr->crc));
\r
210 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
\r
211 defined(PNG_READ_iCCP_SUPPORTED)
\r
213 * Decompress trailing data in a chunk. The assumption is that chunkdata
\r
214 * points at an allocated area holding the contents of a chunk with a
\r
215 * trailing compressed part. What we get back is an allocated area
\r
216 * holding the original prefix part and an uncompressed version of the
\r
217 * trailing part (the malloc area passed in is freed).
\r
220 png_decompress_chunk(png_structp png_ptr, int comp_type,
\r
221 png_size_t chunklength,
\r
222 png_size_t prefix_size, png_size_t *newlength)
\r
224 static PNG_CONST char msg[] = "Error decoding compressed text";
\r
226 png_size_t text_size;
\r
228 if (comp_type == PNG_COMPRESSION_TYPE_BASE)
\r
231 png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size);
\r
232 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
\r
233 png_ptr->zstream.next_out = png_ptr->zbuf;
\r
234 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
\r
239 while (png_ptr->zstream.avail_in)
\r
241 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
\r
242 if (ret != Z_OK && ret != Z_STREAM_END)
\r
244 if (png_ptr->zstream.msg != NULL)
\r
245 png_warning(png_ptr, png_ptr->zstream.msg);
\r
247 png_warning(png_ptr, msg);
\r
248 inflateReset(&png_ptr->zstream);
\r
249 png_ptr->zstream.avail_in = 0;
\r
253 text_size = prefix_size + png_sizeof(msg) + 1;
\r
254 text = (png_charp)png_malloc_warn(png_ptr, text_size);
\r
257 png_free(png_ptr, png_ptr->chunkdata);
\r
258 png_ptr->chunkdata = NULL;
\r
259 png_error(png_ptr, "Not enough memory to decompress chunk");
\r
261 png_memcpy(text, png_ptr->chunkdata, prefix_size);
\r
264 text[text_size - 1] = 0x00;
\r
266 /* Copy what we can of the error message into the text chunk */
\r
267 text_size = (png_size_t)(chunklength -
\r
268 (text - png_ptr->chunkdata) - 1);
\r
269 if (text_size > png_sizeof(msg))
\r
270 text_size = png_sizeof(msg);
\r
271 png_memcpy(text + prefix_size, msg, text_size);
\r
274 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
\r
278 text_size = prefix_size +
\r
279 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
\r
280 text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
\r
283 png_free(png_ptr, png_ptr->chunkdata);
\r
284 png_ptr->chunkdata = NULL;
\r
286 "Not enough memory to decompress chunk.");
\r
288 png_memcpy(text + prefix_size, png_ptr->zbuf,
\r
289 text_size - prefix_size);
\r
290 png_memcpy(text, png_ptr->chunkdata, prefix_size);
\r
291 *(text + text_size) = 0x00;
\r
298 text = (png_charp)png_malloc_warn(png_ptr,
\r
299 (png_uint_32)(text_size +
\r
300 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
\r
303 png_free(png_ptr, tmp);
\r
304 png_free(png_ptr, png_ptr->chunkdata);
\r
305 png_ptr->chunkdata = NULL;
\r
307 "Not enough memory to decompress chunk..");
\r
309 png_memcpy(text, tmp, text_size);
\r
310 png_free(png_ptr, tmp);
\r
311 png_memcpy(text + text_size, png_ptr->zbuf,
\r
312 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
\r
313 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
\r
314 *(text + text_size) = 0x00;
\r
316 if (ret == Z_STREAM_END)
\r
320 png_ptr->zstream.next_out = png_ptr->zbuf;
\r
321 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
\r
325 if (ret != Z_STREAM_END)
\r
327 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
\r
330 if (ret == Z_BUF_ERROR)
\r
331 png_snprintf(umsg, 52,
\r
332 "Buffer error in compressed datastream in %s chunk",
\r
333 png_ptr->chunk_name);
\r
334 else if (ret == Z_DATA_ERROR)
\r
335 png_snprintf(umsg, 52,
\r
336 "Data error in compressed datastream in %s chunk",
\r
337 png_ptr->chunk_name);
\r
339 png_snprintf(umsg, 52,
\r
340 "Incomplete compressed datastream in %s chunk",
\r
341 png_ptr->chunk_name);
\r
342 png_warning(png_ptr, umsg);
\r
344 png_warning(png_ptr,
\r
345 "Incomplete compressed datastream in chunk other than IDAT");
\r
347 text_size = prefix_size;
\r
350 text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
\r
353 png_free(png_ptr, png_ptr->chunkdata);
\r
354 png_ptr->chunkdata = NULL;
\r
355 png_error(png_ptr, "Not enough memory for text.");
\r
357 png_memcpy(text, png_ptr->chunkdata, prefix_size);
\r
359 *(text + text_size) = 0x00;
\r
362 inflateReset(&png_ptr->zstream);
\r
363 png_ptr->zstream.avail_in = 0;
\r
365 png_free(png_ptr, png_ptr->chunkdata);
\r
366 png_ptr->chunkdata = text;
\r
367 *newlength=text_size;
\r
369 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
\r
371 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
\r
374 png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type);
\r
375 png_warning(png_ptr, umsg);
\r
377 png_warning(png_ptr, "Unknown zTXt compression type");
\r
380 *(png_ptr->chunkdata + prefix_size) = 0x00;
\r
381 *newlength = prefix_size;
\r
386 /* read and check the IDHR chunk */
\r
388 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
391 png_uint_32 width, height;
\r
392 int bit_depth, color_type, compression_type, filter_type;
\r
393 int interlace_type;
\r
395 png_debug(1, "in png_handle_IHDR\n");
\r
397 if (png_ptr->mode & PNG_HAVE_IHDR)
\r
398 png_error(png_ptr, "Out of place IHDR");
\r
400 /* check the length */
\r
402 png_error(png_ptr, "Invalid IHDR chunk");
\r
404 png_ptr->mode |= PNG_HAVE_IHDR;
\r
406 png_crc_read(png_ptr, buf, 13);
\r
407 png_crc_finish(png_ptr, 0);
\r
409 width = png_get_uint_31(png_ptr, buf);
\r
410 height = png_get_uint_31(png_ptr, buf + 4);
\r
411 bit_depth = buf[8];
\r
412 color_type = buf[9];
\r
413 compression_type = buf[10];
\r
414 filter_type = buf[11];
\r
415 interlace_type = buf[12];
\r
417 /* set internal variables */
\r
418 png_ptr->width = width;
\r
419 png_ptr->height = height;
\r
420 png_ptr->bit_depth = (png_byte)bit_depth;
\r
421 png_ptr->interlaced = (png_byte)interlace_type;
\r
422 png_ptr->color_type = (png_byte)color_type;
\r
423 #if defined(PNG_MNG_FEATURES_SUPPORTED)
\r
424 png_ptr->filter_type = (png_byte)filter_type;
\r
426 png_ptr->compression_type = (png_byte)compression_type;
\r
428 /* find number of channels */
\r
429 switch (png_ptr->color_type)
\r
431 case PNG_COLOR_TYPE_GRAY:
\r
432 case PNG_COLOR_TYPE_PALETTE:
\r
433 png_ptr->channels = 1;
\r
435 case PNG_COLOR_TYPE_RGB:
\r
436 png_ptr->channels = 3;
\r
438 case PNG_COLOR_TYPE_GRAY_ALPHA:
\r
439 png_ptr->channels = 2;
\r
441 case PNG_COLOR_TYPE_RGB_ALPHA:
\r
442 png_ptr->channels = 4;
\r
446 /* set up other useful info */
\r
447 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
\r
448 png_ptr->channels);
\r
449 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
\r
450 png_debug1(3, "bit_depth = %d\n", png_ptr->bit_depth);
\r
451 png_debug1(3, "channels = %d\n", png_ptr->channels);
\r
452 png_debug1(3, "rowbytes = %lu\n", png_ptr->rowbytes);
\r
453 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
\r
454 color_type, interlace_type, compression_type, filter_type);
\r
457 /* read and check the palette */
\r
459 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
461 png_color palette[PNG_MAX_PALETTE_LENGTH];
\r
463 #ifndef PNG_NO_POINTER_INDEXING
\r
464 png_colorp pal_ptr;
\r
467 png_debug(1, "in png_handle_PLTE\n");
\r
469 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
470 png_error(png_ptr, "Missing IHDR before PLTE");
\r
471 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
473 png_warning(png_ptr, "Invalid PLTE after IDAT");
\r
474 png_crc_finish(png_ptr, length);
\r
477 else if (png_ptr->mode & PNG_HAVE_PLTE)
\r
478 png_error(png_ptr, "Duplicate PLTE chunk");
\r
480 png_ptr->mode |= PNG_HAVE_PLTE;
\r
482 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
\r
484 png_warning(png_ptr,
\r
485 "Ignoring PLTE chunk in grayscale PNG");
\r
486 png_crc_finish(png_ptr, length);
\r
489 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
\r
490 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
\r
492 png_crc_finish(png_ptr, length);
\r
497 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
\r
499 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
\r
501 png_warning(png_ptr, "Invalid palette chunk");
\r
502 png_crc_finish(png_ptr, length);
\r
507 png_error(png_ptr, "Invalid palette chunk");
\r
511 num = (int)length / 3;
\r
513 #ifndef PNG_NO_POINTER_INDEXING
\r
514 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
\r
518 png_crc_read(png_ptr, buf, 3);
\r
519 pal_ptr->red = buf[0];
\r
520 pal_ptr->green = buf[1];
\r
521 pal_ptr->blue = buf[2];
\r
524 for (i = 0; i < num; i++)
\r
528 png_crc_read(png_ptr, buf, 3);
\r
529 /* don't depend upon png_color being any order */
\r
530 palette[i].red = buf[0];
\r
531 palette[i].green = buf[1];
\r
532 palette[i].blue = buf[2];
\r
536 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
\r
537 whatever the normal CRC configuration tells us. However, if we
\r
538 have an RGB image, the PLTE can be considered ancillary, so
\r
539 we will act as though it is. */
\r
540 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
\r
541 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
544 png_crc_finish(png_ptr, 0);
\r
546 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
\r
547 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
\r
549 /* If we don't want to use the data from an ancillary chunk,
\r
550 we have two options: an error abort, or a warning and we
\r
551 ignore the data in this chunk (which should be OK, since
\r
552 it's considered ancillary for a RGB or RGBA image). */
\r
553 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
\r
555 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
\r
557 png_chunk_error(png_ptr, "CRC error");
\r
561 png_chunk_warning(png_ptr, "CRC error");
\r
565 /* Otherwise, we (optionally) emit a warning and use the chunk. */
\r
566 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
\r
568 png_chunk_warning(png_ptr, "CRC error");
\r
573 png_set_PLTE(png_ptr, info_ptr, palette, num);
\r
575 #if defined(PNG_READ_tRNS_SUPPORTED)
\r
576 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
578 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
\r
580 if (png_ptr->num_trans > (png_uint_16)num)
\r
582 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
\r
583 png_ptr->num_trans = (png_uint_16)num;
\r
585 if (info_ptr->num_trans > (png_uint_16)num)
\r
587 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
\r
588 info_ptr->num_trans = (png_uint_16)num;
\r
597 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
599 png_debug(1, "in png_handle_IEND\n");
\r
601 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
\r
603 png_error(png_ptr, "No image in file");
\r
606 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
\r
610 png_warning(png_ptr, "Incorrect IEND chunk length");
\r
612 png_crc_finish(png_ptr, length);
\r
614 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
\r
617 #if defined(PNG_READ_gAMA_SUPPORTED)
\r
619 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
621 png_fixed_point igamma;
\r
622 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
627 png_debug(1, "in png_handle_gAMA\n");
\r
629 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
630 png_error(png_ptr, "Missing IHDR before gAMA");
\r
631 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
633 png_warning(png_ptr, "Invalid gAMA after IDAT");
\r
634 png_crc_finish(png_ptr, length);
\r
637 else if (png_ptr->mode & PNG_HAVE_PLTE)
\r
638 /* Should be an error, but we can cope with it */
\r
639 png_warning(png_ptr, "Out of place gAMA chunk");
\r
641 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
\r
642 #if defined(PNG_READ_sRGB_SUPPORTED)
\r
643 && !(info_ptr->valid & PNG_INFO_sRGB)
\r
647 png_warning(png_ptr, "Duplicate gAMA chunk");
\r
648 png_crc_finish(png_ptr, length);
\r
654 png_warning(png_ptr, "Incorrect gAMA chunk length");
\r
655 png_crc_finish(png_ptr, length);
\r
659 png_crc_read(png_ptr, buf, 4);
\r
660 if (png_crc_finish(png_ptr, 0))
\r
663 igamma = (png_fixed_point)png_get_uint_32(buf);
\r
664 /* check for zero gamma */
\r
667 png_warning(png_ptr,
\r
668 "Ignoring gAMA chunk with gamma=0");
\r
672 #if defined(PNG_READ_sRGB_SUPPORTED)
\r
673 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
\r
674 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
\r
676 png_warning(png_ptr,
\r
677 "Ignoring incorrect gAMA value when sRGB is also present");
\r
678 #ifndef PNG_NO_CONSOLE_IO
\r
679 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
\r
683 #endif /* PNG_READ_sRGB_SUPPORTED */
\r
685 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
686 file_gamma = (float)igamma / (float)100000.0;
\r
687 # ifdef PNG_READ_GAMMA_SUPPORTED
\r
688 png_ptr->gamma = file_gamma;
\r
690 png_set_gAMA(png_ptr, info_ptr, file_gamma);
\r
692 #ifdef PNG_FIXED_POINT_SUPPORTED
\r
693 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
\r
698 #if defined(PNG_READ_sBIT_SUPPORTED)
\r
700 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
702 png_size_t truelen;
\r
705 png_debug(1, "in png_handle_sBIT\n");
\r
707 buf[0] = buf[1] = buf[2] = buf[3] = 0;
\r
709 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
710 png_error(png_ptr, "Missing IHDR before sBIT");
\r
711 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
713 png_warning(png_ptr, "Invalid sBIT after IDAT");
\r
714 png_crc_finish(png_ptr, length);
\r
717 else if (png_ptr->mode & PNG_HAVE_PLTE)
\r
719 /* Should be an error, but we can cope with it */
\r
720 png_warning(png_ptr, "Out of place sBIT chunk");
\r
722 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
\r
724 png_warning(png_ptr, "Duplicate sBIT chunk");
\r
725 png_crc_finish(png_ptr, length);
\r
729 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
732 truelen = (png_size_t)png_ptr->channels;
\r
734 if (length != truelen || length > 4)
\r
736 png_warning(png_ptr, "Incorrect sBIT chunk length");
\r
737 png_crc_finish(png_ptr, length);
\r
741 png_crc_read(png_ptr, buf, truelen);
\r
742 if (png_crc_finish(png_ptr, 0))
\r
745 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
\r
747 png_ptr->sig_bit.red = buf[0];
\r
748 png_ptr->sig_bit.green = buf[1];
\r
749 png_ptr->sig_bit.blue = buf[2];
\r
750 png_ptr->sig_bit.alpha = buf[3];
\r
754 png_ptr->sig_bit.gray = buf[0];
\r
755 png_ptr->sig_bit.red = buf[0];
\r
756 png_ptr->sig_bit.green = buf[0];
\r
757 png_ptr->sig_bit.blue = buf[0];
\r
758 png_ptr->sig_bit.alpha = buf[1];
\r
760 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
\r
764 #if defined(PNG_READ_cHRM_SUPPORTED)
\r
766 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
769 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
770 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
\r
772 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
\r
773 int_y_green, int_x_blue, int_y_blue;
\r
775 png_uint_32 uint_x, uint_y;
\r
777 png_debug(1, "in png_handle_cHRM\n");
\r
779 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
780 png_error(png_ptr, "Missing IHDR before cHRM");
\r
781 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
783 png_warning(png_ptr, "Invalid cHRM after IDAT");
\r
784 png_crc_finish(png_ptr, length);
\r
787 else if (png_ptr->mode & PNG_HAVE_PLTE)
\r
788 /* Should be an error, but we can cope with it */
\r
789 png_warning(png_ptr, "Missing PLTE before cHRM");
\r
791 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
\r
792 #if defined(PNG_READ_sRGB_SUPPORTED)
\r
793 && !(info_ptr->valid & PNG_INFO_sRGB)
\r
797 png_warning(png_ptr, "Duplicate cHRM chunk");
\r
798 png_crc_finish(png_ptr, length);
\r
804 png_warning(png_ptr, "Incorrect cHRM chunk length");
\r
805 png_crc_finish(png_ptr, length);
\r
809 png_crc_read(png_ptr, buf, 32);
\r
810 if (png_crc_finish(png_ptr, 0))
\r
813 uint_x = png_get_uint_32(buf);
\r
814 uint_y = png_get_uint_32(buf + 4);
\r
815 if (uint_x > 80000L || uint_y > 80000L ||
\r
816 uint_x + uint_y > 100000L)
\r
818 png_warning(png_ptr, "Invalid cHRM white point");
\r
821 int_x_white = (png_fixed_point)uint_x;
\r
822 int_y_white = (png_fixed_point)uint_y;
\r
824 uint_x = png_get_uint_32(buf + 8);
\r
825 uint_y = png_get_uint_32(buf + 12);
\r
826 if (uint_x + uint_y > 100000L)
\r
828 png_warning(png_ptr, "Invalid cHRM red point");
\r
831 int_x_red = (png_fixed_point)uint_x;
\r
832 int_y_red = (png_fixed_point)uint_y;
\r
834 uint_x = png_get_uint_32(buf + 16);
\r
835 uint_y = png_get_uint_32(buf + 20);
\r
836 if (uint_x + uint_y > 100000L)
\r
838 png_warning(png_ptr, "Invalid cHRM green point");
\r
841 int_x_green = (png_fixed_point)uint_x;
\r
842 int_y_green = (png_fixed_point)uint_y;
\r
844 uint_x = png_get_uint_32(buf + 24);
\r
845 uint_y = png_get_uint_32(buf + 28);
\r
846 if (uint_x + uint_y > 100000L)
\r
848 png_warning(png_ptr, "Invalid cHRM blue point");
\r
851 int_x_blue = (png_fixed_point)uint_x;
\r
852 int_y_blue = (png_fixed_point)uint_y;
\r
854 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
855 white_x = (float)int_x_white / (float)100000.0;
\r
856 white_y = (float)int_y_white / (float)100000.0;
\r
857 red_x = (float)int_x_red / (float)100000.0;
\r
858 red_y = (float)int_y_red / (float)100000.0;
\r
859 green_x = (float)int_x_green / (float)100000.0;
\r
860 green_y = (float)int_y_green / (float)100000.0;
\r
861 blue_x = (float)int_x_blue / (float)100000.0;
\r
862 blue_y = (float)int_y_blue / (float)100000.0;
\r
865 #if defined(PNG_READ_sRGB_SUPPORTED)
\r
866 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
\r
868 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
\r
869 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
\r
870 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
\r
871 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
\r
872 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
\r
873 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
\r
874 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
\r
875 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
\r
877 png_warning(png_ptr,
\r
878 "Ignoring incorrect cHRM value when sRGB is also present");
\r
879 #ifndef PNG_NO_CONSOLE_IO
\r
880 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
881 fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
\r
882 white_x, white_y, red_x, red_y);
\r
883 fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
\r
884 green_x, green_y, blue_x, blue_y);
\r
886 fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
\r
887 int_x_white, int_y_white, int_x_red, int_y_red);
\r
888 fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
\r
889 int_x_green, int_y_green, int_x_blue, int_y_blue);
\r
891 #endif /* PNG_NO_CONSOLE_IO */
\r
895 #endif /* PNG_READ_sRGB_SUPPORTED */
\r
897 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
898 png_set_cHRM(png_ptr, info_ptr,
\r
899 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
\r
901 #ifdef PNG_FIXED_POINT_SUPPORTED
\r
902 png_set_cHRM_fixed(png_ptr, info_ptr,
\r
903 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
\r
904 int_y_green, int_x_blue, int_y_blue);
\r
909 #if defined(PNG_READ_sRGB_SUPPORTED)
\r
911 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
916 png_debug(1, "in png_handle_sRGB\n");
\r
918 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
919 png_error(png_ptr, "Missing IHDR before sRGB");
\r
920 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
922 png_warning(png_ptr, "Invalid sRGB after IDAT");
\r
923 png_crc_finish(png_ptr, length);
\r
926 else if (png_ptr->mode & PNG_HAVE_PLTE)
\r
927 /* Should be an error, but we can cope with it */
\r
928 png_warning(png_ptr, "Out of place sRGB chunk");
\r
930 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
\r
932 png_warning(png_ptr, "Duplicate sRGB chunk");
\r
933 png_crc_finish(png_ptr, length);
\r
939 png_warning(png_ptr, "Incorrect sRGB chunk length");
\r
940 png_crc_finish(png_ptr, length);
\r
944 png_crc_read(png_ptr, buf, 1);
\r
945 if (png_crc_finish(png_ptr, 0))
\r
949 /* check for bad intent */
\r
950 if (intent >= PNG_sRGB_INTENT_LAST)
\r
952 png_warning(png_ptr, "Unknown sRGB intent");
\r
956 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
\r
957 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
\r
959 png_fixed_point igamma;
\r
960 #ifdef PNG_FIXED_POINT_SUPPORTED
\r
961 igamma=info_ptr->int_gamma;
\r
963 # ifdef PNG_FLOATING_POINT_SUPPORTED
\r
964 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
\r
967 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
\r
969 png_warning(png_ptr,
\r
970 "Ignoring incorrect gAMA value when sRGB is also present");
\r
971 #ifndef PNG_NO_CONSOLE_IO
\r
972 # ifdef PNG_FIXED_POINT_SUPPORTED
\r
973 fprintf(stderr, "incorrect gamma=(%d/100000)\n",
\r
974 (int)png_ptr->int_gamma);
\r
976 # ifdef PNG_FLOATING_POINT_SUPPORTED
\r
977 fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
\r
983 #endif /* PNG_READ_gAMA_SUPPORTED */
\r
985 #ifdef PNG_READ_cHRM_SUPPORTED
\r
986 #ifdef PNG_FIXED_POINT_SUPPORTED
\r
987 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
\r
988 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
\r
989 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
\r
990 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
\r
991 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
\r
992 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
\r
993 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
\r
994 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
\r
995 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
\r
997 png_warning(png_ptr,
\r
998 "Ignoring incorrect cHRM value when sRGB is also present");
\r
1000 #endif /* PNG_FIXED_POINT_SUPPORTED */
\r
1001 #endif /* PNG_READ_cHRM_SUPPORTED */
\r
1003 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
\r
1005 #endif /* PNG_READ_sRGB_SUPPORTED */
\r
1007 #if defined(PNG_READ_iCCP_SUPPORTED)
\r
1008 void /* PRIVATE */
\r
1009 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
1010 /* Note: this does not properly handle chunks that are > 64K under DOS */
\r
1012 png_byte compression_type;
\r
1014 png_charp profile;
\r
1015 png_uint_32 skip = 0;
\r
1016 png_uint_32 profile_size, profile_length;
\r
1017 png_size_t slength, prefix_length, data_length;
\r
1019 png_debug(1, "in png_handle_iCCP\n");
\r
1021 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
1022 png_error(png_ptr, "Missing IHDR before iCCP");
\r
1023 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
1025 png_warning(png_ptr, "Invalid iCCP after IDAT");
\r
1026 png_crc_finish(png_ptr, length);
\r
1029 else if (png_ptr->mode & PNG_HAVE_PLTE)
\r
1030 /* Should be an error, but we can cope with it */
\r
1031 png_warning(png_ptr, "Out of place iCCP chunk");
\r
1033 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
\r
1035 png_warning(png_ptr, "Duplicate iCCP chunk");
\r
1036 png_crc_finish(png_ptr, length);
\r
1040 #ifdef PNG_MAX_MALLOC_64K
\r
1041 if (length > (png_uint_32)65535L)
\r
1043 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
\r
1044 skip = length - (png_uint_32)65535L;
\r
1045 length = (png_uint_32)65535L;
\r
1049 png_free(png_ptr, png_ptr->chunkdata);
\r
1050 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
\r
1051 slength = (png_size_t)length;
\r
1052 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
\r
1054 if (png_crc_finish(png_ptr, skip))
\r
1056 png_free(png_ptr, png_ptr->chunkdata);
\r
1057 png_ptr->chunkdata = NULL;
\r
1061 png_ptr->chunkdata[slength] = 0x00;
\r
1063 for (profile = png_ptr->chunkdata; *profile; profile++)
\r
1064 /* empty loop to find end of name */ ;
\r
1068 /* there should be at least one zero (the compression type byte)
\r
1069 following the separator, and we should be on it */
\r
1070 if ( profile >= png_ptr->chunkdata + slength - 1)
\r
1072 png_free(png_ptr, png_ptr->chunkdata);
\r
1073 png_ptr->chunkdata = NULL;
\r
1074 png_warning(png_ptr, "Malformed iCCP chunk");
\r
1078 /* compression_type should always be zero */
\r
1079 compression_type = *profile++;
\r
1080 if (compression_type)
\r
1082 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
\r
1083 compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
\r
1087 prefix_length = profile - png_ptr->chunkdata;
\r
1088 png_decompress_chunk(png_ptr, compression_type,
\r
1089 slength, prefix_length, &data_length);
\r
1091 profile_length = data_length - prefix_length;
\r
1093 if ( prefix_length > data_length || profile_length < 4)
\r
1095 png_free(png_ptr, png_ptr->chunkdata);
\r
1096 png_ptr->chunkdata = NULL;
\r
1097 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
\r
1101 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
\r
1102 pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
\r
1103 profile_size = ((*(pC ))<<24) |
\r
1104 ((*(pC + 1))<<16) |
\r
1105 ((*(pC + 2))<< 8) |
\r
1108 if (profile_size < profile_length)
\r
1109 profile_length = profile_size;
\r
1111 if (profile_size > profile_length)
\r
1113 png_free(png_ptr, png_ptr->chunkdata);
\r
1114 png_ptr->chunkdata = NULL;
\r
1115 png_warning(png_ptr, "Ignoring truncated iCCP profile.");
\r
1119 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
\r
1120 compression_type, png_ptr->chunkdata + prefix_length, profile_length);
\r
1121 png_free(png_ptr, png_ptr->chunkdata);
\r
1122 png_ptr->chunkdata = NULL;
\r
1124 #endif /* PNG_READ_iCCP_SUPPORTED */
\r
1126 #if defined(PNG_READ_sPLT_SUPPORTED)
\r
1127 void /* PRIVATE */
\r
1128 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
1129 /* Note: this does not properly handle chunks that are > 64K under DOS */
\r
1131 png_bytep entry_start;
\r
1132 png_sPLT_t new_palette;
\r
1133 #ifdef PNG_NO_POINTER_INDEXING
\r
1134 png_sPLT_entryp pp;
\r
1136 int data_length, entry_size, i;
\r
1137 png_uint_32 skip = 0;
\r
1138 png_size_t slength;
\r
1140 png_debug(1, "in png_handle_sPLT\n");
\r
1142 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
1143 png_error(png_ptr, "Missing IHDR before sPLT");
\r
1144 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
1146 png_warning(png_ptr, "Invalid sPLT after IDAT");
\r
1147 png_crc_finish(png_ptr, length);
\r
1151 #ifdef PNG_MAX_MALLOC_64K
\r
1152 if (length > (png_uint_32)65535L)
\r
1154 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
\r
1155 skip = length - (png_uint_32)65535L;
\r
1156 length = (png_uint_32)65535L;
\r
1160 png_free(png_ptr, png_ptr->chunkdata);
\r
1161 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
\r
1162 slength = (png_size_t)length;
\r
1163 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
\r
1165 if (png_crc_finish(png_ptr, skip))
\r
1167 png_free(png_ptr, png_ptr->chunkdata);
\r
1168 png_ptr->chunkdata = NULL;
\r
1172 png_ptr->chunkdata[slength] = 0x00;
\r
1174 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; entry_start++)
\r
1175 /* empty loop to find end of name */ ;
\r
1178 /* a sample depth should follow the separator, and we should be on it */
\r
1179 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
\r
1181 png_free(png_ptr, png_ptr->chunkdata);
\r
1182 png_ptr->chunkdata = NULL;
\r
1183 png_warning(png_ptr, "malformed sPLT chunk");
\r
1187 new_palette.depth = *entry_start++;
\r
1188 entry_size = (new_palette.depth == 8 ? 6 : 10);
\r
1189 data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
\r
1191 /* integrity-check the data length */
\r
1192 if (data_length % entry_size)
\r
1194 png_free(png_ptr, png_ptr->chunkdata);
\r
1195 png_ptr->chunkdata = NULL;
\r
1196 png_warning(png_ptr, "sPLT chunk has bad length");
\r
1200 new_palette.nentries = (png_int_32) ( data_length / entry_size);
\r
1201 if ((png_uint_32) new_palette.nentries >
\r
1202 (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
\r
1204 png_warning(png_ptr, "sPLT chunk too long");
\r
1207 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
\r
1208 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
\r
1209 if (new_palette.entries == NULL)
\r
1211 png_warning(png_ptr, "sPLT chunk requires too much memory");
\r
1215 #ifndef PNG_NO_POINTER_INDEXING
\r
1216 for (i = 0; i < new_palette.nentries; i++)
\r
1218 png_sPLT_entryp pp = new_palette.entries + i;
\r
1220 if (new_palette.depth == 8)
\r
1222 pp->red = *entry_start++;
\r
1223 pp->green = *entry_start++;
\r
1224 pp->blue = *entry_start++;
\r
1225 pp->alpha = *entry_start++;
\r
1229 pp->red = png_get_uint_16(entry_start); entry_start += 2;
\r
1230 pp->green = png_get_uint_16(entry_start); entry_start += 2;
\r
1231 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
\r
1232 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
\r
1234 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
\r
1237 pp = new_palette.entries;
\r
1238 for (i = 0; i < new_palette.nentries; i++)
\r
1241 if (new_palette.depth == 8)
\r
1243 pp[i].red = *entry_start++;
\r
1244 pp[i].green = *entry_start++;
\r
1245 pp[i].blue = *entry_start++;
\r
1246 pp[i].alpha = *entry_start++;
\r
1250 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
\r
1251 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
\r
1252 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
\r
1253 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
\r
1255 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
\r
1259 /* discard all chunk data except the name and stash that */
\r
1260 new_palette.name = png_ptr->chunkdata;
\r
1262 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
\r
1264 png_free(png_ptr, png_ptr->chunkdata);
\r
1265 png_ptr->chunkdata = NULL;
\r
1266 png_free(png_ptr, new_palette.entries);
\r
1268 #endif /* PNG_READ_sPLT_SUPPORTED */
\r
1270 #if defined(PNG_READ_tRNS_SUPPORTED)
\r
1271 void /* PRIVATE */
\r
1272 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
1274 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
\r
1276 png_debug(1, "in png_handle_tRNS\n");
\r
1278 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
1279 png_error(png_ptr, "Missing IHDR before tRNS");
\r
1280 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
1282 png_warning(png_ptr, "Invalid tRNS after IDAT");
\r
1283 png_crc_finish(png_ptr, length);
\r
1286 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
\r
1288 png_warning(png_ptr, "Duplicate tRNS chunk");
\r
1289 png_crc_finish(png_ptr, length);
\r
1293 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
\r
1299 png_warning(png_ptr, "Incorrect tRNS chunk length");
\r
1300 png_crc_finish(png_ptr, length);
\r
1304 png_crc_read(png_ptr, buf, 2);
\r
1305 png_ptr->num_trans = 1;
\r
1306 png_ptr->trans_values.gray = png_get_uint_16(buf);
\r
1308 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
\r
1314 png_warning(png_ptr, "Incorrect tRNS chunk length");
\r
1315 png_crc_finish(png_ptr, length);
\r
1318 png_crc_read(png_ptr, buf, (png_size_t)length);
\r
1319 png_ptr->num_trans = 1;
\r
1320 png_ptr->trans_values.red = png_get_uint_16(buf);
\r
1321 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
\r
1322 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
\r
1324 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
1326 if (!(png_ptr->mode & PNG_HAVE_PLTE))
\r
1328 /* Should be an error, but we can cope with it. */
\r
1329 png_warning(png_ptr, "Missing PLTE before tRNS");
\r
1331 if (length > (png_uint_32)png_ptr->num_palette ||
\r
1332 length > PNG_MAX_PALETTE_LENGTH)
\r
1334 png_warning(png_ptr, "Incorrect tRNS chunk length");
\r
1335 png_crc_finish(png_ptr, length);
\r
1340 png_warning(png_ptr, "Zero length tRNS chunk");
\r
1341 png_crc_finish(png_ptr, length);
\r
1344 png_crc_read(png_ptr, readbuf, (png_size_t)length);
\r
1345 png_ptr->num_trans = (png_uint_16)length;
\r
1349 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
\r
1350 png_crc_finish(png_ptr, length);
\r
1354 if (png_crc_finish(png_ptr, 0))
\r
1356 png_ptr->num_trans = 0;
\r
1360 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
\r
1361 &(png_ptr->trans_values));
\r
1365 #if defined(PNG_READ_bKGD_SUPPORTED)
\r
1366 void /* PRIVATE */
\r
1367 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
1369 png_size_t truelen;
\r
1372 png_debug(1, "in png_handle_bKGD\n");
\r
1374 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
1375 png_error(png_ptr, "Missing IHDR before bKGD");
\r
1376 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
1378 png_warning(png_ptr, "Invalid bKGD after IDAT");
\r
1379 png_crc_finish(png_ptr, length);
\r
1382 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
\r
1383 !(png_ptr->mode & PNG_HAVE_PLTE))
\r
1385 png_warning(png_ptr, "Missing PLTE before bKGD");
\r
1386 png_crc_finish(png_ptr, length);
\r
1389 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
\r
1391 png_warning(png_ptr, "Duplicate bKGD chunk");
\r
1392 png_crc_finish(png_ptr, length);
\r
1396 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
1398 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
\r
1403 if (length != truelen)
\r
1405 png_warning(png_ptr, "Incorrect bKGD chunk length");
\r
1406 png_crc_finish(png_ptr, length);
\r
1410 png_crc_read(png_ptr, buf, truelen);
\r
1411 if (png_crc_finish(png_ptr, 0))
\r
1414 /* We convert the index value into RGB components so that we can allow
\r
1415 * arbitrary RGB values for background when we have transparency, and
\r
1416 * so it is easy to determine the RGB values of the background color
\r
1417 * from the info_ptr struct. */
\r
1418 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
1420 png_ptr->background.index = buf[0];
\r
1421 if (info_ptr && info_ptr->num_palette)
\r
1423 if (buf[0] > info_ptr->num_palette)
\r
1425 png_warning(png_ptr, "Incorrect bKGD chunk index value");
\r
1428 png_ptr->background.red =
\r
1429 (png_uint_16)png_ptr->palette[buf[0]].red;
\r
1430 png_ptr->background.green =
\r
1431 (png_uint_16)png_ptr->palette[buf[0]].green;
\r
1432 png_ptr->background.blue =
\r
1433 (png_uint_16)png_ptr->palette[buf[0]].blue;
\r
1436 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
\r
1438 png_ptr->background.red =
\r
1439 png_ptr->background.green =
\r
1440 png_ptr->background.blue =
\r
1441 png_ptr->background.gray = png_get_uint_16(buf);
\r
1445 png_ptr->background.red = png_get_uint_16(buf);
\r
1446 png_ptr->background.green = png_get_uint_16(buf + 2);
\r
1447 png_ptr->background.blue = png_get_uint_16(buf + 4);
\r
1450 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
\r
1454 #if defined(PNG_READ_hIST_SUPPORTED)
\r
1455 void /* PRIVATE */
\r
1456 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
1458 unsigned int num, i;
\r
1459 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
\r
1461 png_debug(1, "in png_handle_hIST\n");
\r
1463 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
1464 png_error(png_ptr, "Missing IHDR before hIST");
\r
1465 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
1467 png_warning(png_ptr, "Invalid hIST after IDAT");
\r
1468 png_crc_finish(png_ptr, length);
\r
1471 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
\r
1473 png_warning(png_ptr, "Missing PLTE before hIST");
\r
1474 png_crc_finish(png_ptr, length);
\r
1477 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
\r
1479 png_warning(png_ptr, "Duplicate hIST chunk");
\r
1480 png_crc_finish(png_ptr, length);
\r
1484 num = length / 2 ;
\r
1485 if (num != (unsigned int) png_ptr->num_palette || num >
\r
1486 (unsigned int) PNG_MAX_PALETTE_LENGTH)
\r
1488 png_warning(png_ptr, "Incorrect hIST chunk length");
\r
1489 png_crc_finish(png_ptr, length);
\r
1493 for (i = 0; i < num; i++)
\r
1497 png_crc_read(png_ptr, buf, 2);
\r
1498 readbuf[i] = png_get_uint_16(buf);
\r
1501 if (png_crc_finish(png_ptr, 0))
\r
1504 png_set_hIST(png_ptr, info_ptr, readbuf);
\r
1508 #if defined(PNG_READ_pHYs_SUPPORTED)
\r
1509 void /* PRIVATE */
\r
1510 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
1513 png_uint_32 res_x, res_y;
\r
1516 png_debug(1, "in png_handle_pHYs\n");
\r
1518 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
1519 png_error(png_ptr, "Missing IHDR before pHYs");
\r
1520 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
1522 png_warning(png_ptr, "Invalid pHYs after IDAT");
\r
1523 png_crc_finish(png_ptr, length);
\r
1526 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
\r
1528 png_warning(png_ptr, "Duplicate pHYs chunk");
\r
1529 png_crc_finish(png_ptr, length);
\r
1535 png_warning(png_ptr, "Incorrect pHYs chunk length");
\r
1536 png_crc_finish(png_ptr, length);
\r
1540 png_crc_read(png_ptr, buf, 9);
\r
1541 if (png_crc_finish(png_ptr, 0))
\r
1544 res_x = png_get_uint_32(buf);
\r
1545 res_y = png_get_uint_32(buf + 4);
\r
1546 unit_type = buf[8];
\r
1547 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
\r
1551 #if defined(PNG_READ_oFFs_SUPPORTED)
\r
1552 void /* PRIVATE */
\r
1553 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
1556 png_int_32 offset_x, offset_y;
\r
1559 png_debug(1, "in png_handle_oFFs\n");
\r
1561 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
1562 png_error(png_ptr, "Missing IHDR before oFFs");
\r
1563 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
1565 png_warning(png_ptr, "Invalid oFFs after IDAT");
\r
1566 png_crc_finish(png_ptr, length);
\r
1569 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
\r
1571 png_warning(png_ptr, "Duplicate oFFs chunk");
\r
1572 png_crc_finish(png_ptr, length);
\r
1578 png_warning(png_ptr, "Incorrect oFFs chunk length");
\r
1579 png_crc_finish(png_ptr, length);
\r
1583 png_crc_read(png_ptr, buf, 9);
\r
1584 if (png_crc_finish(png_ptr, 0))
\r
1587 offset_x = png_get_int_32(buf);
\r
1588 offset_y = png_get_int_32(buf + 4);
\r
1589 unit_type = buf[8];
\r
1590 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
\r
1594 #if defined(PNG_READ_pCAL_SUPPORTED)
\r
1595 /* read the pCAL chunk (described in the PNG Extensions document) */
\r
1596 void /* PRIVATE */
\r
1597 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
1599 png_int_32 X0, X1;
\r
1600 png_byte type, nparams;
\r
1601 png_charp buf, units, endptr;
\r
1602 png_charpp params;
\r
1603 png_size_t slength;
\r
1606 png_debug(1, "in png_handle_pCAL\n");
\r
1608 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
1609 png_error(png_ptr, "Missing IHDR before pCAL");
\r
1610 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
1612 png_warning(png_ptr, "Invalid pCAL after IDAT");
\r
1613 png_crc_finish(png_ptr, length);
\r
1616 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
\r
1618 png_warning(png_ptr, "Duplicate pCAL chunk");
\r
1619 png_crc_finish(png_ptr, length);
\r
1623 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
\r
1625 png_free(png_ptr, png_ptr->chunkdata);
\r
1626 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
\r
1627 if (png_ptr->chunkdata == NULL)
\r
1629 png_warning(png_ptr, "No memory for pCAL purpose.");
\r
1632 slength = (png_size_t)length;
\r
1633 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
\r
1635 if (png_crc_finish(png_ptr, 0))
\r
1637 png_free(png_ptr, png_ptr->chunkdata);
\r
1638 png_ptr->chunkdata = NULL;
\r
1642 png_ptr->chunkdata[slength] = 0x00; /* null terminate the last string */
\r
1644 png_debug(3, "Finding end of pCAL purpose string\n");
\r
1645 for (buf = png_ptr->chunkdata; *buf; buf++)
\r
1646 /* empty loop */ ;
\r
1648 endptr = png_ptr->chunkdata + slength;
\r
1650 /* We need to have at least 12 bytes after the purpose string
\r
1651 in order to get the parameter information. */
\r
1652 if (endptr <= buf + 12)
\r
1654 png_warning(png_ptr, "Invalid pCAL data");
\r
1655 png_free(png_ptr, png_ptr->chunkdata);
\r
1656 png_ptr->chunkdata = NULL;
\r
1660 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
\r
1661 X0 = png_get_int_32((png_bytep)buf+1);
\r
1662 X1 = png_get_int_32((png_bytep)buf+5);
\r
1664 nparams = buf[10];
\r
1667 png_debug(3, "Checking pCAL equation type and number of parameters\n");
\r
1668 /* Check that we have the right number of parameters for known
\r
1669 equation types. */
\r
1670 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
\r
1671 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
\r
1672 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
\r
1673 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
\r
1675 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
\r
1676 png_free(png_ptr, png_ptr->chunkdata);
\r
1677 png_ptr->chunkdata = NULL;
\r
1680 else if (type >= PNG_EQUATION_LAST)
\r
1682 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
\r
1685 for (buf = units; *buf; buf++)
\r
1686 /* Empty loop to move past the units string. */ ;
\r
1688 png_debug(3, "Allocating pCAL parameters array\n");
\r
1689 params = (png_charpp)png_malloc_warn(png_ptr,
\r
1690 (png_uint_32)(nparams * png_sizeof(png_charp))) ;
\r
1691 if (params == NULL)
\r
1693 png_free(png_ptr, png_ptr->chunkdata);
\r
1694 png_ptr->chunkdata = NULL;
\r
1695 png_warning(png_ptr, "No memory for pCAL params.");
\r
1699 /* Get pointers to the start of each parameter string. */
\r
1700 for (i = 0; i < (int)nparams; i++)
\r
1702 buf++; /* Skip the null string terminator from previous parameter. */
\r
1704 png_debug1(3, "Reading pCAL parameter %d\n", i);
\r
1705 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
\r
1706 /* Empty loop to move past each parameter string */ ;
\r
1708 /* Make sure we haven't run out of data yet */
\r
1711 png_warning(png_ptr, "Invalid pCAL data");
\r
1712 png_free(png_ptr, png_ptr->chunkdata);
\r
1713 png_ptr->chunkdata = NULL;
\r
1714 png_free(png_ptr, params);
\r
1719 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
\r
1722 png_free(png_ptr, png_ptr->chunkdata);
\r
1723 png_ptr->chunkdata = NULL;
\r
1724 png_free(png_ptr, params);
\r
1728 #if defined(PNG_READ_sCAL_SUPPORTED)
\r
1729 /* read the sCAL chunk */
\r
1730 void /* PRIVATE */
\r
1731 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
1734 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
1735 double width, height;
\r
1738 #ifdef PNG_FIXED_POINT_SUPPORTED
\r
1739 png_charp swidth, sheight;
\r
1742 png_size_t slength;
\r
1744 png_debug(1, "in png_handle_sCAL\n");
\r
1746 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
1747 png_error(png_ptr, "Missing IHDR before sCAL");
\r
1748 else if (png_ptr->mode & PNG_HAVE_IDAT)
\r
1750 png_warning(png_ptr, "Invalid sCAL after IDAT");
\r
1751 png_crc_finish(png_ptr, length);
\r
1754 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
\r
1756 png_warning(png_ptr, "Duplicate sCAL chunk");
\r
1757 png_crc_finish(png_ptr, length);
\r
1761 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
\r
1763 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
\r
1764 if (png_ptr->chunkdata == NULL)
\r
1766 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
\r
1769 slength = (png_size_t)length;
\r
1770 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
\r
1772 if (png_crc_finish(png_ptr, 0))
\r
1774 png_free(png_ptr, png_ptr->chunkdata);
\r
1775 png_ptr->chunkdata = NULL;
\r
1779 png_ptr->chunkdata[slength] = 0x00; /* null terminate the last string */
\r
1781 ep = png_ptr->chunkdata + 1; /* skip unit byte */
\r
1783 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
1784 width = png_strtod(png_ptr, ep, &vp);
\r
1787 png_warning(png_ptr, "malformed width string in sCAL chunk");
\r
1791 #ifdef PNG_FIXED_POINT_SUPPORTED
\r
1792 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
\r
1793 if (swidth == NULL)
\r
1795 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
\r
1798 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
\r
1802 for (ep = png_ptr->chunkdata; *ep; ep++)
\r
1803 /* empty loop */ ;
\r
1806 if (png_ptr->chunkdata + slength < ep)
\r
1808 png_warning(png_ptr, "Truncated sCAL chunk");
\r
1809 #if defined(PNG_FIXED_POINT_SUPPORTED) && \
\r
1810 !defined(PNG_FLOATING_POINT_SUPPORTED)
\r
1811 png_free(png_ptr, swidth);
\r
1813 png_free(png_ptr, png_ptr->chunkdata);
\r
1814 png_ptr->chunkdata = NULL;
\r
1818 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
1819 height = png_strtod(png_ptr, ep, &vp);
\r
1822 png_warning(png_ptr, "malformed height string in sCAL chunk");
\r
1826 #ifdef PNG_FIXED_POINT_SUPPORTED
\r
1827 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
\r
1828 if (sheight == NULL)
\r
1830 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
\r
1833 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
\r
1837 if (png_ptr->chunkdata + slength < ep
\r
1838 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
1839 || width <= 0. || height <= 0.
\r
1843 png_warning(png_ptr, "Invalid sCAL data");
\r
1844 png_free(png_ptr, png_ptr->chunkdata);
\r
1845 png_ptr->chunkdata = NULL;
\r
1846 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
\r
1847 png_free(png_ptr, swidth);
\r
1848 png_free(png_ptr, sheight);
\r
1854 #ifdef PNG_FLOATING_POINT_SUPPORTED
\r
1855 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
\r
1857 #ifdef PNG_FIXED_POINT_SUPPORTED
\r
1858 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
\r
1862 png_free(png_ptr, png_ptr->chunkdata);
\r
1863 png_ptr->chunkdata = NULL;
\r
1864 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
\r
1865 png_free(png_ptr, swidth);
\r
1866 png_free(png_ptr, sheight);
\r
1871 #if defined(PNG_READ_tIME_SUPPORTED)
\r
1872 void /* PRIVATE */
\r
1873 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
1876 png_time mod_time;
\r
1878 png_debug(1, "in png_handle_tIME\n");
\r
1880 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
1881 png_error(png_ptr, "Out of place tIME chunk");
\r
1882 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
\r
1884 png_warning(png_ptr, "Duplicate tIME chunk");
\r
1885 png_crc_finish(png_ptr, length);
\r
1889 if (png_ptr->mode & PNG_HAVE_IDAT)
\r
1890 png_ptr->mode |= PNG_AFTER_IDAT;
\r
1894 png_warning(png_ptr, "Incorrect tIME chunk length");
\r
1895 png_crc_finish(png_ptr, length);
\r
1899 png_crc_read(png_ptr, buf, 7);
\r
1900 if (png_crc_finish(png_ptr, 0))
\r
1903 mod_time.second = buf[6];
\r
1904 mod_time.minute = buf[5];
\r
1905 mod_time.hour = buf[4];
\r
1906 mod_time.day = buf[3];
\r
1907 mod_time.month = buf[2];
\r
1908 mod_time.year = png_get_uint_16(buf);
\r
1910 png_set_tIME(png_ptr, info_ptr, &mod_time);
\r
1914 #if defined(PNG_READ_tEXt_SUPPORTED)
\r
1915 /* Note: this does not properly handle chunks that are > 64K under DOS */
\r
1916 void /* PRIVATE */
\r
1917 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
1919 png_textp text_ptr;
\r
1922 png_uint_32 skip = 0;
\r
1923 png_size_t slength;
\r
1926 png_debug(1, "in png_handle_tEXt\n");
\r
1928 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
1929 png_error(png_ptr, "Missing IHDR before tEXt");
\r
1931 if (png_ptr->mode & PNG_HAVE_IDAT)
\r
1932 png_ptr->mode |= PNG_AFTER_IDAT;
\r
1934 #ifdef PNG_MAX_MALLOC_64K
\r
1935 if (length > (png_uint_32)65535L)
\r
1937 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
\r
1938 skip = length - (png_uint_32)65535L;
\r
1939 length = (png_uint_32)65535L;
\r
1943 png_free(png_ptr, png_ptr->chunkdata);
\r
1944 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
\r
1945 if (png_ptr->chunkdata == NULL)
\r
1947 png_warning(png_ptr, "No memory to process text chunk.");
\r
1950 slength = (png_size_t)length;
\r
1951 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
\r
1953 if (png_crc_finish(png_ptr, skip))
\r
1955 png_free(png_ptr, png_ptr->chunkdata);
\r
1956 png_ptr->chunkdata = NULL;
\r
1960 key = png_ptr->chunkdata;
\r
1961 key[slength] = 0x00;
\r
1963 for (text = key; *text; text++)
\r
1964 /* empty loop to find end of key */ ;
\r
1966 if (text != key + slength)
\r
1969 text_ptr = (png_textp)png_malloc_warn(png_ptr,
\r
1970 (png_uint_32)png_sizeof(png_text));
\r
1971 if (text_ptr == NULL)
\r
1973 png_warning(png_ptr, "Not enough memory to process text chunk.");
\r
1974 png_free(png_ptr, png_ptr->chunkdata);
\r
1975 png_ptr->chunkdata = NULL;
\r
1978 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
\r
1979 text_ptr->key = key;
\r
1980 #ifdef PNG_iTXt_SUPPORTED
\r
1981 text_ptr->lang = NULL;
\r
1982 text_ptr->lang_key = NULL;
\r
1983 text_ptr->itxt_length = 0;
\r
1985 text_ptr->text = text;
\r
1986 text_ptr->text_length = png_strlen(text);
\r
1988 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
\r
1990 png_free(png_ptr, png_ptr->chunkdata);
\r
1991 png_ptr->chunkdata = NULL;
\r
1992 png_free(png_ptr, text_ptr);
\r
1994 png_warning(png_ptr, "Insufficient memory to process text chunk.");
\r
1998 #if defined(PNG_READ_zTXt_SUPPORTED)
\r
1999 /* note: this does not correctly handle chunks that are > 64K under DOS */
\r
2000 void /* PRIVATE */
\r
2001 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
2003 png_textp text_ptr;
\r
2007 png_size_t slength, prefix_len, data_len;
\r
2009 png_debug(1, "in png_handle_zTXt\n");
\r
2010 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
2011 png_error(png_ptr, "Missing IHDR before zTXt");
\r
2013 if (png_ptr->mode & PNG_HAVE_IDAT)
\r
2014 png_ptr->mode |= PNG_AFTER_IDAT;
\r
2016 #ifdef PNG_MAX_MALLOC_64K
\r
2017 /* We will no doubt have problems with chunks even half this size, but
\r
2018 there is no hard and fast rule to tell us where to stop. */
\r
2019 if (length > (png_uint_32)65535L)
\r
2021 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
\r
2022 png_crc_finish(png_ptr, length);
\r
2027 png_free(png_ptr, png_ptr->chunkdata);
\r
2028 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
\r
2029 if (png_ptr->chunkdata == NULL)
\r
2031 png_warning(png_ptr, "Out of memory processing zTXt chunk.");
\r
2034 slength = (png_size_t)length;
\r
2035 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
\r
2036 if (png_crc_finish(png_ptr, 0))
\r
2038 png_free(png_ptr, png_ptr->chunkdata);
\r
2039 png_ptr->chunkdata = NULL;
\r
2043 png_ptr->chunkdata[slength] = 0x00;
\r
2045 for (text = png_ptr->chunkdata; *text; text++)
\r
2046 /* empty loop */ ;
\r
2048 /* zTXt must have some text after the chunkdataword */
\r
2049 if (text >= png_ptr->chunkdata + slength - 2)
\r
2051 png_warning(png_ptr, "Truncated zTXt chunk");
\r
2052 png_free(png_ptr, png_ptr->chunkdata);
\r
2053 png_ptr->chunkdata = NULL;
\r
2058 comp_type = *(++text);
\r
2059 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
\r
2061 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
\r
2062 comp_type = PNG_TEXT_COMPRESSION_zTXt;
\r
2064 text++; /* skip the compression_method byte */
\r
2066 prefix_len = text - png_ptr->chunkdata;
\r
2068 png_decompress_chunk(png_ptr, comp_type,
\r
2069 (png_size_t)length, prefix_len, &data_len);
\r
2071 text_ptr = (png_textp)png_malloc_warn(png_ptr,
\r
2072 (png_uint_32)png_sizeof(png_text));
\r
2073 if (text_ptr == NULL)
\r
2075 png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
\r
2076 png_free(png_ptr, png_ptr->chunkdata);
\r
2077 png_ptr->chunkdata = NULL;
\r
2080 text_ptr->compression = comp_type;
\r
2081 text_ptr->key = png_ptr->chunkdata;
\r
2082 #ifdef PNG_iTXt_SUPPORTED
\r
2083 text_ptr->lang = NULL;
\r
2084 text_ptr->lang_key = NULL;
\r
2085 text_ptr->itxt_length = 0;
\r
2087 text_ptr->text = png_ptr->chunkdata + prefix_len;
\r
2088 text_ptr->text_length = data_len;
\r
2090 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
\r
2092 png_free(png_ptr, text_ptr);
\r
2093 png_free(png_ptr, png_ptr->chunkdata);
\r
2094 png_ptr->chunkdata = NULL;
\r
2096 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
\r
2100 #if defined(PNG_READ_iTXt_SUPPORTED)
\r
2101 /* note: this does not correctly handle chunks that are > 64K under DOS */
\r
2102 void /* PRIVATE */
\r
2103 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
2105 png_textp text_ptr;
\r
2106 png_charp key, lang, text, lang_key;
\r
2108 int comp_type = 0;
\r
2110 png_size_t slength, prefix_len, data_len;
\r
2112 png_debug(1, "in png_handle_iTXt\n");
\r
2114 if (!(png_ptr->mode & PNG_HAVE_IHDR))
\r
2115 png_error(png_ptr, "Missing IHDR before iTXt");
\r
2117 if (png_ptr->mode & PNG_HAVE_IDAT)
\r
2118 png_ptr->mode |= PNG_AFTER_IDAT;
\r
2120 #ifdef PNG_MAX_MALLOC_64K
\r
2121 /* We will no doubt have problems with chunks even half this size, but
\r
2122 there is no hard and fast rule to tell us where to stop. */
\r
2123 if (length > (png_uint_32)65535L)
\r
2125 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
\r
2126 png_crc_finish(png_ptr, length);
\r
2131 png_free(png_ptr, png_ptr->chunkdata);
\r
2132 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
\r
2133 if (png_ptr->chunkdata == NULL)
\r
2135 png_warning(png_ptr, "No memory to process iTXt chunk.");
\r
2138 slength = (png_size_t)length;
\r
2139 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
\r
2140 if (png_crc_finish(png_ptr, 0))
\r
2142 png_free(png_ptr, png_ptr->chunkdata);
\r
2143 png_ptr->chunkdata = NULL;
\r
2147 png_ptr->chunkdata[slength] = 0x00;
\r
2149 for (lang = png_ptr->chunkdata; *lang; lang++)
\r
2150 /* empty loop */ ;
\r
2151 lang++; /* skip NUL separator */
\r
2153 /* iTXt must have a language tag (possibly empty), two compression bytes,
\r
2154 translated keyword (possibly empty), and possibly some text after the
\r
2157 if (lang >= png_ptr->chunkdata + slength - 3)
\r
2159 png_warning(png_ptr, "Truncated iTXt chunk");
\r
2160 png_free(png_ptr, png_ptr->chunkdata);
\r
2161 png_ptr->chunkdata = NULL;
\r
2166 comp_flag = *lang++;
\r
2167 comp_type = *lang++;
\r
2170 for (lang_key = lang; *lang_key; lang_key++)
\r
2171 /* empty loop */ ;
\r
2172 lang_key++; /* skip NUL separator */
\r
2174 if (lang_key >= png_ptr->chunkdata + slength)
\r
2176 png_warning(png_ptr, "Truncated iTXt chunk");
\r
2177 png_free(png_ptr, png_ptr->chunkdata);
\r
2178 png_ptr->chunkdata = NULL;
\r
2182 for (text = lang_key; *text; text++)
\r
2183 /* empty loop */ ;
\r
2184 text++; /* skip NUL separator */
\r
2185 if (text >= png_ptr->chunkdata + slength)
\r
2187 png_warning(png_ptr, "Malformed iTXt chunk");
\r
2188 png_free(png_ptr, png_ptr->chunkdata);
\r
2189 png_ptr->chunkdata = NULL;
\r
2193 prefix_len = text - png_ptr->chunkdata;
\r
2195 key=png_ptr->chunkdata;
\r
2197 png_decompress_chunk(png_ptr, comp_type,
\r
2198 (size_t)length, prefix_len, &data_len);
\r
2200 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
\r
2201 text_ptr = (png_textp)png_malloc_warn(png_ptr,
\r
2202 (png_uint_32)png_sizeof(png_text));
\r
2203 if (text_ptr == NULL)
\r
2205 png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
\r
2206 png_free(png_ptr, png_ptr->chunkdata);
\r
2207 png_ptr->chunkdata = NULL;
\r
2210 text_ptr->compression = (int)comp_flag + 1;
\r
2211 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
\r
2212 text_ptr->lang = png_ptr->chunkdata + (lang - key);
\r
2213 text_ptr->itxt_length = data_len;
\r
2214 text_ptr->text_length = 0;
\r
2215 text_ptr->key = png_ptr->chunkdata;
\r
2216 text_ptr->text = png_ptr->chunkdata + prefix_len;
\r
2218 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
\r
2220 png_free(png_ptr, text_ptr);
\r
2221 png_free(png_ptr, png_ptr->chunkdata);
\r
2222 png_ptr->chunkdata = NULL;
\r
2224 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
\r
2228 /* This function is called when we haven't found a handler for a
\r
2229 chunk. If there isn't a problem with the chunk itself (ie bad
\r
2230 chunk name, CRC, or a critical chunk), the chunk is silently ignored
\r
2231 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
\r
2232 case it will be saved away to be written out later. */
\r
2233 void /* PRIVATE */
\r
2234 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
\r
2236 png_uint_32 skip = 0;
\r
2238 png_debug(1, "in png_handle_unknown\n");
\r
2240 if (png_ptr->mode & PNG_HAVE_IDAT)
\r
2242 #ifdef PNG_USE_LOCAL_ARRAYS
\r
2243 PNG_CONST PNG_IDAT;
\r
2245 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
\r
2246 png_ptr->mode |= PNG_AFTER_IDAT;
\r
2249 if (!(png_ptr->chunk_name[0] & 0x20))
\r
2251 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
\r
2252 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
\r
2253 PNG_HANDLE_CHUNK_ALWAYS
\r
2254 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
\r
2255 && png_ptr->read_user_chunk_fn == NULL
\r
2259 png_chunk_error(png_ptr, "unknown critical chunk");
\r
2262 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
\r
2263 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
\r
2264 (png_ptr->read_user_chunk_fn != NULL))
\r
2266 #ifdef PNG_MAX_MALLOC_64K
\r
2267 if (length > (png_uint_32)65535L)
\r
2269 png_warning(png_ptr, "unknown chunk too large to fit in memory");
\r
2270 skip = length - (png_uint_32)65535L;
\r
2271 length = (png_uint_32)65535L;
\r
2274 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
\r
2275 (png_charp)png_ptr->chunk_name,
\r
2276 png_sizeof(png_ptr->unknown_chunk.name));
\r
2277 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0';
\r
2278 png_ptr->unknown_chunk.size = (png_size_t)length;
\r
2280 png_ptr->unknown_chunk.data = NULL;
\r
2283 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
\r
2284 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
\r
2286 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
\r
2287 if (png_ptr->read_user_chunk_fn != NULL)
\r
2289 /* callback to user unknown chunk handler */
\r
2291 ret = (*(png_ptr->read_user_chunk_fn))
\r
2292 (png_ptr, &png_ptr->unknown_chunk);
\r
2294 png_chunk_error(png_ptr, "error in user chunk");
\r
2297 if (!(png_ptr->chunk_name[0] & 0x20))
\r
2298 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
\r
2299 PNG_HANDLE_CHUNK_ALWAYS)
\r
2300 png_chunk_error(png_ptr, "unknown critical chunk");
\r
2301 png_set_unknown_chunks(png_ptr, info_ptr,
\r
2302 &png_ptr->unknown_chunk, 1);
\r
2307 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
\r
2308 png_free(png_ptr, png_ptr->unknown_chunk.data);
\r
2309 png_ptr->unknown_chunk.data = NULL;
\r
2315 png_crc_finish(png_ptr, skip);
\r
2317 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
\r
2318 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
\r
2322 /* This function is called to verify that a chunk name is valid.
\r
2323 This function can't have the "critical chunk check" incorporated
\r
2324 into it, since in the future we will need to be able to call user
\r
2325 functions to handle unknown critical chunks after we check that
\r
2326 the chunk name itself is valid. */
\r
2328 #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
\r
2330 void /* PRIVATE */
\r
2331 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
\r
2333 png_debug(1, "in png_check_chunk_name\n");
\r
2334 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
\r
2335 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
\r
2337 png_chunk_error(png_ptr, "invalid chunk type");
\r
2341 /* Combines the row recently read in with the existing pixels in the
\r
2342 row. This routine takes care of alpha and transparency if requested.
\r
2343 This routine also handles the two methods of progressive display
\r
2344 of interlaced images, depending on the mask value.
\r
2345 The mask value describes which pixels are to be combined with
\r
2346 the row. The pattern always repeats every 8 pixels, so just 8
\r
2347 bits are needed. A one indicates the pixel is to be combined,
\r
2348 a zero indicates the pixel is to be skipped. This is in addition
\r
2349 to any alpha or transparency value associated with the pixel. If
\r
2350 you want all pixels to be combined, pass 0xff (255) in mask. */
\r
2352 void /* PRIVATE */
\r
2353 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
\r
2355 png_debug(1, "in png_combine_row\n");
\r
2358 png_memcpy(row, png_ptr->row_buf + 1,
\r
2359 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
\r
2363 switch (png_ptr->row_info.pixel_depth)
\r
2367 png_bytep sp = png_ptr->row_buf + 1;
\r
2368 png_bytep dp = row;
\r
2369 int s_inc, s_start, s_end;
\r
2373 png_uint_32 row_width = png_ptr->width;
\r
2375 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
\r
2376 if (png_ptr->transformations & PNG_PACKSWAP)
\r
2392 for (i = 0; i < row_width; i++)
\r
2398 value = (*sp >> shift) & 0x01;
\r
2399 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
\r
2400 *dp |= (png_byte)(value << shift);
\r
2403 if (shift == s_end)
\r
2421 png_bytep sp = png_ptr->row_buf + 1;
\r
2422 png_bytep dp = row;
\r
2423 int s_start, s_end, s_inc;
\r
2427 png_uint_32 row_width = png_ptr->width;
\r
2430 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
\r
2431 if (png_ptr->transformations & PNG_PACKSWAP)
\r
2447 for (i = 0; i < row_width; i++)
\r
2451 value = (*sp >> shift) & 0x03;
\r
2452 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
\r
2453 *dp |= (png_byte)(value << shift);
\r
2456 if (shift == s_end)
\r
2473 png_bytep sp = png_ptr->row_buf + 1;
\r
2474 png_bytep dp = row;
\r
2475 int s_start, s_end, s_inc;
\r
2479 png_uint_32 row_width = png_ptr->width;
\r
2482 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
\r
2483 if (png_ptr->transformations & PNG_PACKSWAP)
\r
2498 for (i = 0; i < row_width; i++)
\r
2502 value = (*sp >> shift) & 0xf;
\r
2503 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
\r
2504 *dp |= (png_byte)(value << shift);
\r
2507 if (shift == s_end)
\r
2524 png_bytep sp = png_ptr->row_buf + 1;
\r
2525 png_bytep dp = row;
\r
2526 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
\r
2528 png_uint_32 row_width = png_ptr->width;
\r
2529 png_byte m = 0x80;
\r
2532 for (i = 0; i < row_width; i++)
\r
2536 png_memcpy(dp, sp, pixel_bytes);
\r
2539 sp += pixel_bytes;
\r
2540 dp += pixel_bytes;
\r
2553 #ifdef PNG_READ_INTERLACING_SUPPORTED
\r
2554 /* OLD pre-1.0.9 interface:
\r
2555 void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
\r
2556 png_uint_32 transformations)
\r
2558 void /* PRIVATE */
\r
2559 png_do_read_interlace(png_structp png_ptr)
\r
2561 png_row_infop row_info = &(png_ptr->row_info);
\r
2562 png_bytep row = png_ptr->row_buf + 1;
\r
2563 int pass = png_ptr->pass;
\r
2564 png_uint_32 transformations = png_ptr->transformations;
\r
2565 #ifdef PNG_USE_LOCAL_ARRAYS
\r
2566 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
\r
2567 /* offset to next interlace block */
\r
2568 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
\r
2571 png_debug(1, "in png_do_read_interlace\n");
\r
2572 if (row != NULL && row_info != NULL)
\r
2574 png_uint_32 final_width;
\r
2576 final_width = row_info->width * png_pass_inc[pass];
\r
2578 switch (row_info->pixel_depth)
\r
2582 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
\r
2583 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
\r
2584 int sshift, dshift;
\r
2585 int s_start, s_end, s_inc;
\r
2586 int jstop = png_pass_inc[pass];
\r
2591 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
\r
2592 if (transformations & PNG_PACKSWAP)
\r
2594 sshift = (int)((row_info->width + 7) & 0x07);
\r
2595 dshift = (int)((final_width + 7) & 0x07);
\r
2603 sshift = 7 - (int)((row_info->width + 7) & 0x07);
\r
2604 dshift = 7 - (int)((final_width + 7) & 0x07);
\r
2610 for (i = 0; i < row_info->width; i++)
\r
2612 v = (png_byte)((*sp >> sshift) & 0x01);
\r
2613 for (j = 0; j < jstop; j++)
\r
2615 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
\r
2616 *dp |= (png_byte)(v << dshift);
\r
2617 if (dshift == s_end)
\r
2625 if (sshift == s_end)
\r
2637 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
\r
2638 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
\r
2639 int sshift, dshift;
\r
2640 int s_start, s_end, s_inc;
\r
2641 int jstop = png_pass_inc[pass];
\r
2644 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
\r
2645 if (transformations & PNG_PACKSWAP)
\r
2647 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
\r
2648 dshift = (int)(((final_width + 3) & 0x03) << 1);
\r
2656 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
\r
2657 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
\r
2663 for (i = 0; i < row_info->width; i++)
\r
2668 v = (png_byte)((*sp >> sshift) & 0x03);
\r
2669 for (j = 0; j < jstop; j++)
\r
2671 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
\r
2672 *dp |= (png_byte)(v << dshift);
\r
2673 if (dshift == s_end)
\r
2681 if (sshift == s_end)
\r
2693 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
\r
2694 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
\r
2695 int sshift, dshift;
\r
2696 int s_start, s_end, s_inc;
\r
2698 int jstop = png_pass_inc[pass];
\r
2700 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
\r
2701 if (transformations & PNG_PACKSWAP)
\r
2703 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
\r
2704 dshift = (int)(((final_width + 1) & 0x01) << 2);
\r
2712 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
\r
2713 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
\r
2719 for (i = 0; i < row_info->width; i++)
\r
2721 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
\r
2724 for (j = 0; j < jstop; j++)
\r
2726 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
\r
2727 *dp |= (png_byte)(v << dshift);
\r
2728 if (dshift == s_end)
\r
2736 if (sshift == s_end)
\r
2748 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
\r
2749 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
\r
2750 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
\r
2752 int jstop = png_pass_inc[pass];
\r
2755 for (i = 0; i < row_info->width; i++)
\r
2760 png_memcpy(v, sp, pixel_bytes);
\r
2761 for (j = 0; j < jstop; j++)
\r
2763 png_memcpy(dp, v, pixel_bytes);
\r
2764 dp -= pixel_bytes;
\r
2766 sp -= pixel_bytes;
\r
2771 row_info->width = final_width;
\r
2772 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
\r
2774 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
\r
2775 transformations = transformations; /* silence compiler warning */
\r
2778 #endif /* PNG_READ_INTERLACING_SUPPORTED */
\r
2780 void /* PRIVATE */
\r
2781 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
\r
2782 png_bytep prev_row, int filter)
\r
2784 png_debug(1, "in png_read_filter_row\n");
\r
2785 png_debug2(2, "row = %lu, filter = %d\n", png_ptr->row_number, filter);
\r
2788 case PNG_FILTER_VALUE_NONE:
\r
2790 case PNG_FILTER_VALUE_SUB:
\r
2793 png_uint_32 istop = row_info->rowbytes;
\r
2794 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
\r
2795 png_bytep rp = row + bpp;
\r
2796 png_bytep lp = row;
\r
2798 for (i = bpp; i < istop; i++)
\r
2800 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
\r
2805 case PNG_FILTER_VALUE_UP:
\r
2808 png_uint_32 istop = row_info->rowbytes;
\r
2809 png_bytep rp = row;
\r
2810 png_bytep pp = prev_row;
\r
2812 for (i = 0; i < istop; i++)
\r
2814 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
\r
2819 case PNG_FILTER_VALUE_AVG:
\r
2822 png_bytep rp = row;
\r
2823 png_bytep pp = prev_row;
\r
2824 png_bytep lp = row;
\r
2825 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
\r
2826 png_uint_32 istop = row_info->rowbytes - bpp;
\r
2828 for (i = 0; i < bpp; i++)
\r
2830 *rp = (png_byte)(((int)(*rp) +
\r
2831 ((int)(*pp++) / 2 )) & 0xff);
\r
2835 for (i = 0; i < istop; i++)
\r
2837 *rp = (png_byte)(((int)(*rp) +
\r
2838 (int)(*pp++ + *lp++) / 2 ) & 0xff);
\r
2843 case PNG_FILTER_VALUE_PAETH:
\r
2846 png_bytep rp = row;
\r
2847 png_bytep pp = prev_row;
\r
2848 png_bytep lp = row;
\r
2849 png_bytep cp = prev_row;
\r
2850 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
\r
2851 png_uint_32 istop=row_info->rowbytes - bpp;
\r
2853 for (i = 0; i < bpp; i++)
\r
2855 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
\r
2859 for (i = 0; i < istop; i++) /* use leftover rp,pp */
\r
2861 int a, b, c, pa, pb, pc, p;
\r
2870 #ifdef PNG_USE_ABS
\r
2875 pa = p < 0 ? -p : p;
\r
2876 pb = pc < 0 ? -pc : pc;
\r
2877 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
\r
2881 if (pa <= pb && pa <= pc)
\r
2883 else if (pb <= pc)
\r
2889 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
\r
2891 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
\r
2897 png_warning(png_ptr, "Ignoring bad adaptive filter type");
\r
2903 void /* PRIVATE */
\r
2904 png_read_finish_row(png_structp png_ptr)
\r
2906 #ifdef PNG_USE_LOCAL_ARRAYS
\r
2907 #ifdef PNG_READ_INTERLACING_SUPPORTED
\r
2908 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
\r
2910 /* start of interlace block */
\r
2911 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
\r
2913 /* offset to next interlace block */
\r
2914 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
\r
2916 /* start of interlace block in the y direction */
\r
2917 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
\r
2919 /* offset to next interlace block in the y direction */
\r
2920 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
\r
2921 #endif /* PNG_READ_INTERLACING_SUPPORTED */
\r
2924 png_debug(1, "in png_read_finish_row\n");
\r
2925 png_ptr->row_number++;
\r
2926 if (png_ptr->row_number < png_ptr->num_rows)
\r
2929 #ifdef PNG_READ_INTERLACING_SUPPORTED
\r
2930 if (png_ptr->interlaced)
\r
2932 png_ptr->row_number = 0;
\r
2933 png_memset_check(png_ptr, png_ptr->prev_row, 0,
\r
2934 png_ptr->rowbytes + 1);
\r
2938 if (png_ptr->pass >= 7)
\r
2940 png_ptr->iwidth = (png_ptr->width +
\r
2941 png_pass_inc[png_ptr->pass] - 1 -
\r
2942 png_pass_start[png_ptr->pass]) /
\r
2943 png_pass_inc[png_ptr->pass];
\r
2945 png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
\r
2946 png_ptr->iwidth) + 1;
\r
2948 if (!(png_ptr->transformations & PNG_INTERLACE))
\r
2950 png_ptr->num_rows = (png_ptr->height +
\r
2951 png_pass_yinc[png_ptr->pass] - 1 -
\r
2952 png_pass_ystart[png_ptr->pass]) /
\r
2953 png_pass_yinc[png_ptr->pass];
\r
2954 if (!(png_ptr->num_rows))
\r
2957 else /* if (png_ptr->transformations & PNG_INTERLACE) */
\r
2959 } while (png_ptr->iwidth == 0);
\r
2961 if (png_ptr->pass < 7)
\r
2964 #endif /* PNG_READ_INTERLACING_SUPPORTED */
\r
2966 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
\r
2968 #ifdef PNG_USE_LOCAL_ARRAYS
\r
2969 PNG_CONST PNG_IDAT;
\r
2974 png_ptr->zstream.next_out = (Byte *)&extra;
\r
2975 png_ptr->zstream.avail_out = (uInt)1;
\r
2978 if (!(png_ptr->zstream.avail_in))
\r
2980 while (!png_ptr->idat_size)
\r
2982 png_byte chunk_length[4];
\r
2984 png_crc_finish(png_ptr, 0);
\r
2986 png_read_data(png_ptr, chunk_length, 4);
\r
2987 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
\r
2988 png_reset_crc(png_ptr);
\r
2989 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
\r
2990 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
\r
2991 png_error(png_ptr, "Not enough image data");
\r
2994 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
\r
2995 png_ptr->zstream.next_in = png_ptr->zbuf;
\r
2996 if (png_ptr->zbuf_size > png_ptr->idat_size)
\r
2997 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
\r
2998 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
\r
2999 png_ptr->idat_size -= png_ptr->zstream.avail_in;
\r
3001 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
\r
3002 if (ret == Z_STREAM_END)
\r
3004 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
\r
3005 png_ptr->idat_size)
\r
3006 png_warning(png_ptr, "Extra compressed data");
\r
3007 png_ptr->mode |= PNG_AFTER_IDAT;
\r
3008 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
\r
3012 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
\r
3013 "Decompression Error");
\r
3015 if (!(png_ptr->zstream.avail_out))
\r
3017 png_warning(png_ptr, "Extra compressed data.");
\r
3018 png_ptr->mode |= PNG_AFTER_IDAT;
\r
3019 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
\r
3024 png_ptr->zstream.avail_out = 0;
\r
3027 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
\r
3028 png_warning(png_ptr, "Extra compression data");
\r
3030 inflateReset(&png_ptr->zstream);
\r
3032 png_ptr->mode |= PNG_AFTER_IDAT;
\r
3035 void /* PRIVATE */
\r
3036 png_read_start_row(png_structp png_ptr)
\r
3038 #ifdef PNG_USE_LOCAL_ARRAYS
\r
3039 #ifdef PNG_READ_INTERLACING_SUPPORTED
\r
3040 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
\r
3042 /* start of interlace block */
\r
3043 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
\r
3045 /* offset to next interlace block */
\r
3046 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
\r
3048 /* start of interlace block in the y direction */
\r
3049 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
\r
3051 /* offset to next interlace block in the y direction */
\r
3052 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
\r
3056 int max_pixel_depth;
\r
3057 png_size_t row_bytes;
\r
3059 png_debug(1, "in png_read_start_row\n");
\r
3060 png_ptr->zstream.avail_in = 0;
\r
3061 png_init_read_transformations(png_ptr);
\r
3062 #ifdef PNG_READ_INTERLACING_SUPPORTED
\r
3063 if (png_ptr->interlaced)
\r
3065 if (!(png_ptr->transformations & PNG_INTERLACE))
\r
3066 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
\r
3067 png_pass_ystart[0]) / png_pass_yinc[0];
\r
3069 png_ptr->num_rows = png_ptr->height;
\r
3071 png_ptr->iwidth = (png_ptr->width +
\r
3072 png_pass_inc[png_ptr->pass] - 1 -
\r
3073 png_pass_start[png_ptr->pass]) /
\r
3074 png_pass_inc[png_ptr->pass];
\r
3076 png_ptr->irowbytes =
\r
3077 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1;
\r
3080 #endif /* PNG_READ_INTERLACING_SUPPORTED */
\r
3082 png_ptr->num_rows = png_ptr->height;
\r
3083 png_ptr->iwidth = png_ptr->width;
\r
3084 png_ptr->irowbytes = png_ptr->rowbytes + 1;
\r
3086 max_pixel_depth = png_ptr->pixel_depth;
\r
3088 #if defined(PNG_READ_PACK_SUPPORTED)
\r
3089 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
\r
3090 max_pixel_depth = 8;
\r
3093 #if defined(PNG_READ_EXPAND_SUPPORTED)
\r
3094 if (png_ptr->transformations & PNG_EXPAND)
\r
3096 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
3098 if (png_ptr->num_trans)
\r
3099 max_pixel_depth = 32;
\r
3101 max_pixel_depth = 24;
\r
3103 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
\r
3105 if (max_pixel_depth < 8)
\r
3106 max_pixel_depth = 8;
\r
3107 if (png_ptr->num_trans)
\r
3108 max_pixel_depth *= 2;
\r
3110 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
\r
3112 if (png_ptr->num_trans)
\r
3114 max_pixel_depth *= 4;
\r
3115 max_pixel_depth /= 3;
\r
3121 #if defined(PNG_READ_FILLER_SUPPORTED)
\r
3122 if (png_ptr->transformations & (PNG_FILLER))
\r
3124 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
\r
3125 max_pixel_depth = 32;
\r
3126 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
\r
3128 if (max_pixel_depth <= 8)
\r
3129 max_pixel_depth = 16;
\r
3131 max_pixel_depth = 32;
\r
3133 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
\r
3135 if (max_pixel_depth <= 32)
\r
3136 max_pixel_depth = 32;
\r
3138 max_pixel_depth = 64;
\r
3143 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
\r
3144 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
\r
3147 #if defined(PNG_READ_EXPAND_SUPPORTED)
\r
3148 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
\r
3150 #if defined(PNG_READ_FILLER_SUPPORTED)
\r
3151 (png_ptr->transformations & (PNG_FILLER)) ||
\r
3153 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
\r
3155 if (max_pixel_depth <= 16)
\r
3156 max_pixel_depth = 32;
\r
3158 max_pixel_depth = 64;
\r
3162 if (max_pixel_depth <= 8)
\r
3164 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
\r
3165 max_pixel_depth = 32;
\r
3167 max_pixel_depth = 24;
\r
3169 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
\r
3170 max_pixel_depth = 64;
\r
3172 max_pixel_depth = 48;
\r
3177 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
\r
3178 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
\r
3179 if (png_ptr->transformations & PNG_USER_TRANSFORM)
\r
3181 int user_pixel_depth = png_ptr->user_transform_depth*
\r
3182 png_ptr->user_transform_channels;
\r
3183 if (user_pixel_depth > max_pixel_depth)
\r
3184 max_pixel_depth=user_pixel_depth;
\r
3188 /* align the width on the next larger 8 pixels. Mainly used
\r
3189 for interlacing */
\r
3190 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
\r
3191 /* calculate the maximum bytes needed, adding a byte and a pixel
\r
3192 for safety's sake */
\r
3193 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
\r
3194 1 + ((max_pixel_depth + 7) >> 3);
\r
3195 #ifdef PNG_MAX_MALLOC_64K
\r
3196 if (row_bytes > (png_uint_32)65536L)
\r
3197 png_error(png_ptr, "This image requires a row greater than 64KB");
\r
3200 if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
\r
3202 png_free(png_ptr, png_ptr->big_row_buf);
\r
3203 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
\r
3204 png_ptr->row_buf = png_ptr->big_row_buf+32;
\r
3205 png_ptr->old_big_row_buf_size = row_bytes+64;
\r
3208 #ifdef PNG_MAX_MALLOC_64K
\r
3209 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
\r
3210 png_error(png_ptr, "This image requires a row greater than 64KB");
\r
3212 if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
\r
3213 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
\r
3215 if (png_ptr->rowbytes+1 > png_ptr->old_prev_row_size)
\r
3217 png_free(png_ptr, png_ptr->prev_row);
\r
3218 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
\r
3219 png_ptr->rowbytes + 1));
\r
3220 png_ptr->old_prev_row_size = png_ptr->rowbytes+1;
\r
3223 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
\r
3225 png_debug1(3, "width = %lu,\n", png_ptr->width);
\r
3226 png_debug1(3, "height = %lu,\n", png_ptr->height);
\r
3227 png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
\r
3228 png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
\r
3229 png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
\r
3230 png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
\r
3232 png_ptr->flags |= PNG_FLAG_ROW_INIT;
\r
3234 #endif /* PNG_READ_SUPPORTED */
\r