2 /* pngrutil.c - utilities to read a PNG file
3 *
4 * libpng 1.2.0 - September 1, 2001
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2001 Glenn Randers-Pehrson
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9 *
10 * This file contains routines that are only called from within
11 * libpng itself during the course of reading an image.
12 */
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)
21 {
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 )
29 {
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);
35 }
36 return result;
37 }
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)
45 {
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);
52 }
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)
60 {
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);
67 }
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)
73 {
74 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
75 (png_uint_16)(*(buf + 1)));
77 return (i);
78 }
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)
84 {
85 png_read_data(png_ptr, buf, length);
86 png_calculate_crc(png_ptr, buf, length);
87 }
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)
95 {
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)
100 {
101 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
102 }
103 if (i)
104 {
105 png_crc_read(png_ptr, png_ptr->zbuf, i);
106 }
108 if (png_crc_error(png_ptr))
109 {
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)))
114 {
115 png_chunk_warning(png_ptr, "CRC error");
116 }
117 else
118 {
119 png_chunk_error(png_ptr, "CRC error");
120 }
121 return (1);
122 }
124 return (0);
125 }
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)
131 {
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 */
137 {
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;
141 }
142 else /* critical */
143 {
144 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
145 need_crc = 0;
146 }
148 png_read_data(png_ptr, crc_bytes, 4);
150 if (need_crc)
151 {
152 crc = png_get_uint_32(crc_bytes);
153 return ((int)(crc != png_ptr->crc));
154 }
155 else
156 return (0);
157 }
159 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
160 defined(PNG_READ_iCCP_SUPPORTED)
161 /*
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).
167 */
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)
172 {
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)
178 {
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)
189 {
190 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
191 if (ret != Z_OK && ret != Z_STREAM_END)
192 {
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)
201 {
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);
205 }
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;
214 }
215 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
216 {
217 if (text == NULL)
218 {
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;
226 }
227 else
228 {
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;
240 }
241 if (ret == Z_STREAM_END)
242 break;
243 else
244 {
245 png_ptr->zstream.next_out = png_ptr->zbuf;
246 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
247 }
248 }
249 }
250 if (ret != Z_STREAM_END)
251 {
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)
271 {
272 text = (png_charp)png_malloc(png_ptr, text_size+1);
273 png_memcpy(text, chunkdata, prefix_size);
274 }
275 *(text + text_size) = 0x00;
276 }
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;
284 }
285 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
286 {
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;
298 }
300 return chunkdata;
301 }
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)
307 {
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 #if defined(PNG_MNG_FEATURES_SUPPORTED)
343 png_ptr->filter_type = (png_byte)filter_type;
344 #endif
346 /* find number of channels */
347 switch (png_ptr->color_type)
348 {
349 case PNG_COLOR_TYPE_GRAY:
350 case PNG_COLOR_TYPE_PALETTE:
351 png_ptr->channels = 1;
352 break;
353 case PNG_COLOR_TYPE_RGB:
354 png_ptr->channels = 3;
355 break;
356 case PNG_COLOR_TYPE_GRAY_ALPHA:
357 png_ptr->channels = 2;
358 break;
359 case PNG_COLOR_TYPE_RGB_ALPHA:
360 png_ptr->channels = 4;
361 break;
362 }
364 /* set up other useful info */
365 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
366 png_ptr->channels);
367 png_ptr->rowbytes = ((png_ptr->width *
368 (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
369 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
370 png_debug1(3,"channels = %d\n", png_ptr->channels);
371 png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
372 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
373 color_type, interlace_type, compression_type, filter_type);
374 }
376 /* read and check the palette */
377 void /* PRIVATE */
378 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
379 {
380 png_color palette[PNG_MAX_PALETTE_LENGTH];
381 int num, i;
382 #ifndef PNG_NO_POINTER_INDEXING
383 png_colorp pal_ptr;
384 #endif
386 png_debug(1, "in png_handle_PLTE\n");
388 if (!(png_ptr->mode & PNG_HAVE_IHDR))
389 png_error(png_ptr, "Missing IHDR before PLTE");
390 else if (png_ptr->mode & PNG_HAVE_IDAT)
391 {
392 png_warning(png_ptr, "Invalid PLTE after IDAT");
393 png_crc_finish(png_ptr, length);
394 return;
395 }
396 else if (png_ptr->mode & PNG_HAVE_PLTE)
397 png_error(png_ptr, "Duplicate PLTE chunk");
399 png_ptr->mode |= PNG_HAVE_PLTE;
401 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
402 {
403 png_warning(png_ptr,
404 "Ignoring PLTE chunk in grayscale PNG");
405 png_crc_finish(png_ptr, length);
406 return;
407 }
408 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
409 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
410 {
411 png_crc_finish(png_ptr, length);
412 return;
413 }
414 #endif
416 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
417 {
418 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
419 {
420 png_warning(png_ptr, "Invalid palette chunk");
421 png_crc_finish(png_ptr, length);
422 return;
423 }
424 else
425 {
426 png_error(png_ptr, "Invalid palette chunk");
427 }
428 }
430 num = (int)length / 3;
432 #ifndef PNG_NO_POINTER_INDEXING
433 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
434 {
435 png_byte buf[3];
437 png_crc_read(png_ptr, buf, 3);
438 pal_ptr->red = buf[0];
439 pal_ptr->green = buf[1];
440 pal_ptr->blue = buf[2];
441 }
442 #else
443 for (i = 0; i < num; i++)
444 {
445 png_byte buf[3];
447 png_crc_read(png_ptr, buf, 3);
448 /* don't depend upon png_color being any order */
449 palette[i].red = buf[0];
450 palette[i].green = buf[1];
451 palette[i].blue = buf[2];
452 }
453 #endif
455 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
456 whatever the normal CRC configuration tells us. However, if we
457 have an RGB image, the PLTE can be considered ancillary, so
458 we will act as though it is. */
459 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
460 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
461 #endif
462 {
463 png_crc_finish(png_ptr, 0);
464 }
465 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
466 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
467 {
468 /* If we don't want to use the data from an ancillary chunk,
469 we have two options: an error abort, or a warning and we
470 ignore the data in this chunk (which should be OK, since
471 it's considered ancillary for a RGB or RGBA image). */
472 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
473 {
474 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
475 {
476 png_chunk_error(png_ptr, "CRC error");
477 }
478 else
479 {
480 png_chunk_warning(png_ptr, "CRC error");
481 return;
482 }
483 }
484 /* Otherwise, we (optionally) emit a warning and use the chunk. */
485 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
486 {
487 png_chunk_warning(png_ptr, "CRC error");
488 }
489 }
490 #endif
492 png_set_PLTE(png_ptr, info_ptr, palette, num);
494 #if defined(PNG_READ_tRNS_SUPPORTED)
495 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
496 {
497 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
498 {
499 if (png_ptr->num_trans > (png_uint_16)num)
500 {
501 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
502 png_ptr->num_trans = (png_uint_16)num;
503 }
504 if (info_ptr->num_trans > (png_uint_16)num)
505 {
506 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
507 info_ptr->num_trans = (png_uint_16)num;
508 }
509 }
510 }
511 #endif
513 }
515 void /* PRIVATE */
516 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
517 {
518 png_debug(1, "in png_handle_IEND\n");
520 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
521 {
522 png_error(png_ptr, "No image in file");
524 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
525 }
527 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
529 if (length != 0)
530 {
531 png_warning(png_ptr, "Incorrect IEND chunk length");
532 }
533 png_crc_finish(png_ptr, length);
534 }
536 #if defined(PNG_READ_gAMA_SUPPORTED)
537 void /* PRIVATE */
538 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
539 {
540 png_fixed_point igamma;
541 #ifdef PNG_FLOATING_POINT_SUPPORTED
542 float file_gamma;
543 #endif
544 png_byte buf[4];
546 png_debug(1, "in png_handle_gAMA\n");
548 if (!(png_ptr->mode & PNG_HAVE_IHDR))
549 png_error(png_ptr, "Missing IHDR before gAMA");
550 else if (png_ptr->mode & PNG_HAVE_IDAT)
551 {
552 png_warning(png_ptr, "Invalid gAMA after IDAT");
553 png_crc_finish(png_ptr, length);
554 return;
555 }
556 else if (png_ptr->mode & PNG_HAVE_PLTE)
557 /* Should be an error, but we can cope with it */
558 png_warning(png_ptr, "Out of place gAMA chunk");
560 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
561 #if defined(PNG_READ_sRGB_SUPPORTED)
562 && !(info_ptr->valid & PNG_INFO_sRGB)
563 #endif
564 )
565 {
566 png_warning(png_ptr, "Duplicate gAMA chunk");
567 png_crc_finish(png_ptr, length);
568 return;
569 }
571 if (length != 4)
572 {
573 png_warning(png_ptr, "Incorrect gAMA chunk length");
574 png_crc_finish(png_ptr, length);
575 return;
576 }
578 png_crc_read(png_ptr, buf, 4);
579 if (png_crc_finish(png_ptr, 0))
580 return;
582 igamma = (png_fixed_point)png_get_uint_32(buf);
583 /* check for zero gamma */
584 if (igamma == 0)
585 {
586 png_warning(png_ptr,
587 "Ignoring gAMA chunk with gamma=0");
588 return;
589 }
591 #if defined(PNG_READ_sRGB_SUPPORTED)
592 if (info_ptr->valid & PNG_INFO_sRGB)
593 if(igamma < 45000L || igamma > 46000L)
594 {
595 png_warning(png_ptr,
596 "Ignoring incorrect gAMA value when sRGB is also present");
597 #ifndef PNG_NO_CONSOLE_IO
598 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
599 #endif
600 return;
601 }
602 #endif /* PNG_READ_sRGB_SUPPORTED */
604 #ifdef PNG_FLOATING_POINT_SUPPORTED
605 file_gamma = (float)igamma / (float)100000.0;
606 # ifdef PNG_READ_GAMMA_SUPPORTED
607 png_ptr->gamma = file_gamma;
608 # endif
609 png_set_gAMA(png_ptr, info_ptr, file_gamma);
610 #endif
611 #ifdef PNG_FIXED_POINT_SUPPORTED
612 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
613 #endif
614 }
615 #endif
617 #if defined(PNG_READ_sBIT_SUPPORTED)
618 void /* PRIVATE */
619 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
620 {
621 png_size_t truelen;
622 png_byte buf[4];
624 png_debug(1, "in png_handle_sBIT\n");
626 buf[0] = buf[1] = buf[2] = buf[3] = 0;
628 if (!(png_ptr->mode & PNG_HAVE_IHDR))
629 png_error(png_ptr, "Missing IHDR before sBIT");
630 else if (png_ptr->mode & PNG_HAVE_IDAT)
631 {
632 png_warning(png_ptr, "Invalid sBIT after IDAT");
633 png_crc_finish(png_ptr, length);
634 return;
635 }
636 else if (png_ptr->mode & PNG_HAVE_PLTE)
637 {
638 /* Should be an error, but we can cope with it */
639 png_warning(png_ptr, "Out of place sBIT chunk");
640 }
641 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
642 {
643 png_warning(png_ptr, "Duplicate sBIT chunk");
644 png_crc_finish(png_ptr, length);
645 return;
646 }
648 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
649 truelen = 3;
650 else
651 truelen = (png_size_t)png_ptr->channels;
653 if (length != truelen)
654 {
655 png_warning(png_ptr, "Incorrect sBIT chunk length");
656 png_crc_finish(png_ptr, length);
657 return;
658 }
660 png_crc_read(png_ptr, buf, truelen);
661 if (png_crc_finish(png_ptr, 0))
662 return;
664 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
665 {
666 png_ptr->sig_bit.red = buf[0];
667 png_ptr->sig_bit.green = buf[1];
668 png_ptr->sig_bit.blue = buf[2];
669 png_ptr->sig_bit.alpha = buf[3];
670 }
671 else
672 {
673 png_ptr->sig_bit.gray = buf[0];
674 png_ptr->sig_bit.red = buf[0];
675 png_ptr->sig_bit.green = buf[0];
676 png_ptr->sig_bit.blue = buf[0];
677 png_ptr->sig_bit.alpha = buf[1];
678 }
679 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
680 }
681 #endif
683 #if defined(PNG_READ_cHRM_SUPPORTED)
684 void /* PRIVATE */
685 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
686 {
687 png_byte buf[4];
688 #ifdef PNG_FLOATING_POINT_SUPPORTED
689 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
690 #endif
691 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
692 int_y_green, int_x_blue, int_y_blue;
694 png_debug(1, "in png_handle_cHRM\n");
696 if (!(png_ptr->mode & PNG_HAVE_IHDR))
697 png_error(png_ptr, "Missing IHDR before cHRM");
698 else if (png_ptr->mode & PNG_HAVE_IDAT)
699 {
700 png_warning(png_ptr, "Invalid cHRM after IDAT");
701 png_crc_finish(png_ptr, length);
702 return;
703 }
704 else if (png_ptr->mode & PNG_HAVE_PLTE)
705 /* Should be an error, but we can cope with it */
706 png_warning(png_ptr, "Missing PLTE before cHRM");
708 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
709 #if defined(PNG_READ_sRGB_SUPPORTED)
710 && !(info_ptr->valid & PNG_INFO_sRGB)
711 #endif
712 )
713 {
714 png_warning(png_ptr, "Duplicate cHRM chunk");
715 png_crc_finish(png_ptr, length);
716 return;
717 }
719 if (length != 32)
720 {
721 png_warning(png_ptr, "Incorrect cHRM chunk length");
722 png_crc_finish(png_ptr, length);
723 return;
724 }
726 png_crc_read(png_ptr, buf, 4);
727 int_x_white = (png_fixed_point)png_get_uint_32(buf);
729 png_crc_read(png_ptr, buf, 4);
730 int_y_white = (png_fixed_point)png_get_uint_32(buf);
732 if (int_x_white > 80000L || int_y_white > 80000L ||
733 int_x_white + int_y_white > 100000L)
734 {
735 png_warning(png_ptr, "Invalid cHRM white point");
736 png_crc_finish(png_ptr, 24);
737 return;
738 }
740 png_crc_read(png_ptr, buf, 4);
741 int_x_red = (png_fixed_point)png_get_uint_32(buf);
743 png_crc_read(png_ptr, buf, 4);
744 int_y_red = (png_fixed_point)png_get_uint_32(buf);
746 if (int_x_red > 80000L || int_y_red > 80000L ||
747 int_x_red + int_y_red > 100000L)
748 {
749 png_warning(png_ptr, "Invalid cHRM red point");
750 png_crc_finish(png_ptr, 16);
751 return;
752 }
754 png_crc_read(png_ptr, buf, 4);
755 int_x_green = (png_fixed_point)png_get_uint_32(buf);
757 png_crc_read(png_ptr, buf, 4);
758 int_y_green = (png_fixed_point)png_get_uint_32(buf);
760 if (int_x_green > 80000L || int_y_green > 80000L ||
761 int_x_green + int_y_green > 100000L)
762 {
763 png_warning(png_ptr, "Invalid cHRM green point");
764 png_crc_finish(png_ptr, 8);
765 return;
766 }
768 png_crc_read(png_ptr, buf, 4);
769 int_x_blue = (png_fixed_point)png_get_uint_32(buf);
771 png_crc_read(png_ptr, buf, 4);
772 int_y_blue = (png_fixed_point)png_get_uint_32(buf);
774 if (int_x_blue > 80000L || int_y_blue > 80000L ||
775 int_x_blue + int_y_blue > 100000L)
776 {
777 png_warning(png_ptr, "Invalid cHRM blue point");
778 png_crc_finish(png_ptr, 0);
779 return;
780 }
781 #ifdef PNG_FLOATING_POINT_SUPPORTED
782 white_x = (float)int_x_white / (float)100000.0;
783 white_y = (float)int_y_white / (float)100000.0;
784 red_x = (float)int_x_red / (float)100000.0;
785 red_y = (float)int_y_red / (float)100000.0;
786 green_x = (float)int_x_green / (float)100000.0;
787 green_y = (float)int_y_green / (float)100000.0;
788 blue_x = (float)int_x_blue / (float)100000.0;
789 blue_y = (float)int_y_blue / (float)100000.0;
790 #endif
792 #if defined(PNG_READ_sRGB_SUPPORTED)
793 if (info_ptr->valid & PNG_INFO_sRGB)
794 {
795 if (abs(int_x_white - 31270L) > 1000 ||
796 abs(int_y_white - 32900L) > 1000 ||
797 abs(int_x_red - 64000L) > 1000 ||
798 abs(int_y_red - 33000L) > 1000 ||
799 abs(int_x_green - 30000L) > 1000 ||
800 abs(int_y_green - 60000L) > 1000 ||
801 abs(int_x_blue - 15000L) > 1000 ||
802 abs(int_y_blue - 6000L) > 1000)
803 {
805 png_warning(png_ptr,
806 "Ignoring incorrect cHRM value when sRGB is also present");
807 #ifndef PNG_NO_CONSOLE_IO
808 #ifdef PNG_FLOATING_POINT_SUPPORTED
809 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
810 white_x, white_y, red_x, red_y);
811 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
812 green_x, green_y, blue_x, blue_y);
813 #else
814 fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
815 int_x_white, int_y_white, int_x_red, int_y_red);
816 fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
817 int_x_green, int_y_green, int_x_blue, int_y_blue);
818 #endif
819 #endif /* PNG_NO_CONSOLE_IO */
820 }
821 png_crc_finish(png_ptr, 0);
822 return;
823 }
824 #endif /* PNG_READ_sRGB_SUPPORTED */
826 #ifdef PNG_FLOATING_POINT_SUPPORTED
827 png_set_cHRM(png_ptr, info_ptr,
828 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
829 #endif
830 #ifdef PNG_FIXED_POINT_SUPPORTED
831 png_set_cHRM_fixed(png_ptr, info_ptr,
832 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
833 int_y_green, int_x_blue, int_y_blue);
834 #endif
835 if (png_crc_finish(png_ptr, 0))
836 return;
837 }
838 #endif
840 #if defined(PNG_READ_sRGB_SUPPORTED)
841 void /* PRIVATE */
842 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
843 {
844 int intent;
845 png_byte buf[1];
847 png_debug(1, "in png_handle_sRGB\n");
849 if (!(png_ptr->mode & PNG_HAVE_IHDR))
850 png_error(png_ptr, "Missing IHDR before sRGB");
851 else if (png_ptr->mode & PNG_HAVE_IDAT)
852 {
853 png_warning(png_ptr, "Invalid sRGB after IDAT");
854 png_crc_finish(png_ptr, length);
855 return;
856 }
857 else if (png_ptr->mode & PNG_HAVE_PLTE)
858 /* Should be an error, but we can cope with it */
859 png_warning(png_ptr, "Out of place sRGB chunk");
861 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
862 {
863 png_warning(png_ptr, "Duplicate sRGB chunk");
864 png_crc_finish(png_ptr, length);
865 return;
866 }
868 if (length != 1)
869 {
870 png_warning(png_ptr, "Incorrect sRGB chunk length");
871 png_crc_finish(png_ptr, length);
872 return;
873 }
875 png_crc_read(png_ptr, buf, 1);
876 if (png_crc_finish(png_ptr, 0))
877 return;
879 intent = buf[0];
880 /* check for bad intent */
881 if (intent >= PNG_sRGB_INTENT_LAST)
882 {
883 png_warning(png_ptr, "Unknown sRGB intent");
884 return;
885 }
887 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
888 if ((info_ptr->valid & PNG_INFO_gAMA))
889 {
890 int igamma;
891 #ifdef PNG_FIXED_POINT_SUPPORTED
892 igamma=(int)info_ptr->int_gamma;
893 #else
894 # ifdef PNG_FLOATING_POINT_SUPPORTED
895 igamma=(int)(info_ptr->gamma * 100000.);
896 # endif
897 #endif
898 #if 0 && defined(PNG_cHRM_SUPPORTED) && !defined(PNG_FIXED_POINT_SUPPORTED)
899 /* We need to define these here because they aren't in png.h */
900 png_fixed_point int_x_white;
901 png_fixed_point int_y_white;
902 png_fixed_point int_x_red;
903 png_fixed_point int_y_red;
904 png_fixed_point int_x_green;
905 png_fixed_point int_y_green;
906 png_fixed_point int_x_blue;
907 png_fixed_point int_y_blue;
908 #endif
909 if(igamma < 45000L || igamma > 46000L)
910 {
911 png_warning(png_ptr,
912 "Ignoring incorrect gAMA value when sRGB is also present");
913 #ifndef PNG_NO_CONSOLE_IO
914 # ifdef PNG_FIXED_POINT_SUPPORTED
915 fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
916 # else
917 # ifdef PNG_FLOATING_POINT_SUPPORTED
918 fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
919 # endif
920 # endif
921 #endif
922 }
923 }
924 #endif /* PNG_READ_gAMA_SUPPORTED */
926 #ifdef PNG_READ_cHRM_SUPPORTED
927 #ifdef PNG_FIXED_POINT_SUPPORTED
928 if (info_ptr->valid & PNG_INFO_cHRM)
929 if (abs(info_ptr->int_x_white - 31270L) > 1000 ||
930 abs(info_ptr->int_y_white - 32900L) > 1000 ||
931 abs(info_ptr->int_x_red - 64000L) > 1000 ||
932 abs(info_ptr->int_y_red - 33000L) > 1000 ||
933 abs(info_ptr->int_x_green - 30000L) > 1000 ||
934 abs(info_ptr->int_y_green - 60000L) > 1000 ||
935 abs(info_ptr->int_x_blue - 15000L) > 1000 ||
936 abs(info_ptr->int_y_blue - 6000L) > 1000)
937 {
938 png_warning(png_ptr,
939 "Ignoring incorrect cHRM value when sRGB is also present");
940 }
941 #endif /* PNG_FIXED_POINT_SUPPORTED */
942 #endif /* PNG_READ_cHRM_SUPPORTED */
944 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
945 }
946 #endif /* PNG_READ_sRGB_SUPPORTED */
948 #if defined(PNG_READ_iCCP_SUPPORTED)
949 void /* PRIVATE */
950 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
951 /* Note: this does not properly handle chunks that are > 64K under DOS */
952 {
953 png_charp chunkdata;
954 png_byte compression_type;
955 png_charp profile;
956 png_uint_32 skip = 0;
957 png_uint_32 profile_size = 0;
958 png_uint_32 profile_length = 0;
959 png_size_t slength, prefix_length, data_length;
961 png_debug(1, "in png_handle_iCCP\n");
963 if (!(png_ptr->mode & PNG_HAVE_IHDR))
964 png_error(png_ptr, "Missing IHDR before iCCP");
965 else if (png_ptr->mode & PNG_HAVE_IDAT)
966 {
967 png_warning(png_ptr, "Invalid iCCP after IDAT");
968 png_crc_finish(png_ptr, length);
969 return;
970 }
971 else if (png_ptr->mode & PNG_HAVE_PLTE)
972 /* Should be an error, but we can cope with it */
973 png_warning(png_ptr, "Out of place iCCP chunk");
975 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
976 {
977 png_warning(png_ptr, "Duplicate iCCP chunk");
978 png_crc_finish(png_ptr, length);
979 return;
980 }
982 #ifdef PNG_MAX_MALLOC_64K
983 if (length > (png_uint_32)65535L)
984 {
985 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
986 skip = length - (png_uint_32)65535L;
987 length = (png_uint_32)65535L;
988 }
989 #endif
991 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
992 slength = (png_size_t)length;
993 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
995 if (png_crc_finish(png_ptr, skip))
996 {
997 png_free(png_ptr, chunkdata);
998 return;
999 }
1001 chunkdata[slength] = 0x00;
1003 for (profile = chunkdata; *profile; profile++)
1004 /* empty loop to find end of name */ ;
1006 ++profile;
1008 /* there should be at least one zero (the compression type byte)
1009 following the separator, and we should be on it */
1010 if ( profile >= chunkdata + slength)
1011 {
1012 png_free(png_ptr, chunkdata);
1013 png_warning(png_ptr, "Malformed iCCP chunk");
1014 return;
1015 }
1017 /* compression_type should always be zero */
1018 compression_type = *profile++;
1019 if (compression_type)
1020 {
1021 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1022 compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1023 wrote nonzero) */
1024 }
1026 prefix_length = profile - chunkdata;
1027 chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
1028 slength, prefix_length, &data_length);
1030 profile_length = data_length - prefix_length;
1032 if ( profile_length < 4)
1033 {
1034 png_free(png_ptr, chunkdata);
1035 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1036 return;
1037 }
1039 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1040 profile_size = ((*(chunkdata+prefix_length))<<24) |
1041 ((*(chunkdata+prefix_length+1))<<16) |
1042 ((*(chunkdata+prefix_length+2))<< 8) |
1043 ((*(chunkdata+prefix_length+3)) );
1045 if(profile_size < profile_length)
1046 profile_length = profile_size;
1048 if(profile_size > profile_length)
1049 {
1050 png_free(png_ptr, chunkdata);
1051 png_warning(png_ptr, "Ignoring truncated iCCP profile.\n");
1052 return;
1053 }
1055 png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
1056 chunkdata + prefix_length, profile_length);
1057 png_free(png_ptr, chunkdata);
1058 }
1059 #endif /* PNG_READ_iCCP_SUPPORTED */
1061 #if defined(PNG_READ_sPLT_SUPPORTED)
1062 void /* PRIVATE */
1063 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1064 /* Note: this does not properly handle chunks that are > 64K under DOS */
1065 {
1066 png_bytep chunkdata;
1067 png_bytep entry_start;
1068 png_sPLT_t new_palette;
1069 #ifdef PNG_NO_POINTER_INDEXING
1070 png_sPLT_entryp pp;
1071 #endif
1072 int data_length, entry_size, i;
1073 png_uint_32 skip = 0;
1074 png_size_t slength;
1076 png_debug(1, "in png_handle_sPLT\n");
1078 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1079 png_error(png_ptr, "Missing IHDR before sPLT");
1080 else if (png_ptr->mode & PNG_HAVE_IDAT)
1081 {
1082 png_warning(png_ptr, "Invalid sPLT after IDAT");
1083 png_crc_finish(png_ptr, length);
1084 return;
1085 }
1087 #ifdef PNG_MAX_MALLOC_64K
1088 if (length > (png_uint_32)65535L)
1089 {
1090 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1091 skip = length - (png_uint_32)65535L;
1092 length = (png_uint_32)65535L;
1093 }
1094 #endif
1096 chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
1097 slength = (png_size_t)length;
1098 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1100 if (png_crc_finish(png_ptr, skip))
1101 {
1102 png_free(png_ptr, chunkdata);
1103 return;
1104 }
1106 chunkdata[slength] = 0x00;
1108 for (entry_start = chunkdata; *entry_start; entry_start++)
1109 /* empty loop to find end of name */ ;
1110 ++entry_start;
1112 /* a sample depth should follow the separator, and we should be on it */
1113 if (entry_start > chunkdata + slength)
1114 {
1115 png_free(png_ptr, chunkdata);
1116 png_warning(png_ptr, "malformed sPLT chunk");
1117 return;
1118 }
1120 new_palette.depth = *entry_start++;
1121 entry_size = (new_palette.depth == 8 ? 6 : 10);
1122 data_length = (slength - (entry_start - chunkdata));
1124 /* integrity-check the data length */
1125 if (data_length % entry_size)
1126 {
1127 png_free(png_ptr, chunkdata);
1128 png_warning(png_ptr, "sPLT chunk has bad length");
1129 return;
1130 }
1132 new_palette.nentries = data_length / entry_size;
1133 new_palette.entries = (png_sPLT_entryp)png_malloc(
1134 png_ptr, new_palette.nentries * sizeof(png_sPLT_entry));
1136 #ifndef PNG_NO_POINTER_INDEXING
1137 for (i = 0; i < new_palette.nentries; i++)
1138 {
1139 png_sPLT_entryp pp = new_palette.entries + i;
1141 if (new_palette.depth == 8)
1142 {
1143 pp->red = *entry_start++;
1144 pp->green = *entry_start++;
1145 pp->blue = *entry_start++;
1146 pp->alpha = *entry_start++;
1147 }
1148 else
1149 {
1150 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1151 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1152 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1153 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1154 }
1155 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1156 }
1157 #else
1158 pp = new_palette.entries;
1159 for (i = 0; i < new_palette.nentries; i++)
1160 {
1162 if (new_palette.depth == 8)
1163 {
1164 pp[i].red = *entry_start++;
1165 pp[i].green = *entry_start++;
1166 pp[i].blue = *entry_start++;
1167 pp[i].alpha = *entry_start++;
1168 }
1169 else
1170 {
1171 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1172 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1173 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1174 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1175 }
1176 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1177 }
1178 #endif
1180 /* discard all chunk data except the name and stash that */
1181 new_palette.name = (png_charp)chunkdata;
1183 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1185 png_free(png_ptr, chunkdata);
1186 png_free(png_ptr, new_palette.entries);
1187 }
1188 #endif /* PNG_READ_sPLT_SUPPORTED */
1190 #if defined(PNG_READ_tRNS_SUPPORTED)
1191 void /* PRIVATE */
1192 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1193 {
1194 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1196 png_debug(1, "in png_handle_tRNS\n");
1198 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1199 png_error(png_ptr, "Missing IHDR before tRNS");
1200 else if (png_ptr->mode & PNG_HAVE_IDAT)
1201 {
1202 png_warning(png_ptr, "Invalid tRNS after IDAT");
1203 png_crc_finish(png_ptr, length);
1204 return;
1205 }
1206 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1207 {
1208 png_warning(png_ptr, "Duplicate tRNS chunk");
1209 png_crc_finish(png_ptr, length);
1210 return;
1211 }
1213 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1214 {
1215 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1216 {
1217 /* Should be an error, but we can cope with it */
1218 png_warning(png_ptr, "Missing PLTE before tRNS");
1219 }
1220 else if (length > (png_uint_32)png_ptr->num_palette)
1221 {
1222 png_warning(png_ptr, "Incorrect tRNS chunk length");
1223 png_crc_finish(png_ptr, length);
1224 return;
1225 }
1226 if (length == 0)
1227 {
1228 png_warning(png_ptr, "Zero length tRNS chunk");
1229 png_crc_finish(png_ptr, length);
1230 return;
1231 }
1233 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1234 png_ptr->num_trans = (png_uint_16)length;
1235 }
1236 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1237 {
1238 png_byte buf[6];
1240 if (length != 6)
1241 {
1242 png_warning(png_ptr, "Incorrect tRNS chunk length");
1243 png_crc_finish(png_ptr, length);
1244 return;
1245 }
1247 png_crc_read(png_ptr, buf, (png_size_t)length);
1248 png_ptr->num_trans = 1;
1249 png_ptr->trans_values.red = png_get_uint_16(buf);
1250 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1251 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1252 }
1253 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1254 {
1255 png_byte buf[6];
1257 if (length != 2)
1258 {
1259 png_warning(png_ptr, "Incorrect tRNS chunk length");
1260 png_crc_finish(png_ptr, length);
1261 return;
1262 }
1264 png_crc_read(png_ptr, buf, 2);
1265 png_ptr->num_trans = 1;
1266 png_ptr->trans_values.gray = png_get_uint_16(buf);
1267 }
1268 else
1269 {
1270 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1271 png_crc_finish(png_ptr, length);
1272 return;
1273 }
1275 if (png_crc_finish(png_ptr, 0))
1276 return;
1278 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1279 &(png_ptr->trans_values));
1280 }
1281 #endif
1283 #if defined(PNG_READ_bKGD_SUPPORTED)
1284 void /* PRIVATE */
1285 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1286 {
1287 png_size_t truelen;
1288 png_byte buf[6];
1290 png_debug(1, "in png_handle_bKGD\n");
1292 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1293 png_error(png_ptr, "Missing IHDR before bKGD");
1294 else if (png_ptr->mode & PNG_HAVE_IDAT)
1295 {
1296 png_warning(png_ptr, "Invalid bKGD after IDAT");
1297 png_crc_finish(png_ptr, length);
1298 return;
1299 }
1300 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1301 !(png_ptr->mode & PNG_HAVE_PLTE))
1302 {
1303 png_warning(png_ptr, "Missing PLTE before bKGD");
1304 png_crc_finish(png_ptr, length);
1305 return;
1306 }
1307 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1308 {
1309 png_warning(png_ptr, "Duplicate bKGD chunk");
1310 png_crc_finish(png_ptr, length);
1311 return;
1312 }
1314 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1315 truelen = 1;
1316 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1317 truelen = 6;
1318 else
1319 truelen = 2;
1321 if (length != truelen)
1322 {
1323 png_warning(png_ptr, "Incorrect bKGD chunk length");
1324 png_crc_finish(png_ptr, length);
1325 return;
1326 }
1328 png_crc_read(png_ptr, buf, truelen);
1329 if (png_crc_finish(png_ptr, 0))
1330 return;
1332 /* We convert the index value into RGB components so that we can allow
1333 * arbitrary RGB values for background when we have transparency, and
1334 * so it is easy to determine the RGB values of the background color
1335 * from the info_ptr struct. */
1336 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1337 {
1338 png_ptr->background.index = buf[0];
1339 if(info_ptr->num_palette)
1340 {
1341 if(buf[0] > info_ptr->num_palette)
1342 {
1343 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1344 return;
1345 }
1346 png_ptr->background.red =
1347 (png_uint_16)png_ptr->palette[buf[0]].red;
1348 png_ptr->background.green =
1349 (png_uint_16)png_ptr->palette[buf[0]].green;
1350 png_ptr->background.blue =
1351 (png_uint_16)png_ptr->palette[buf[0]].blue;
1352 }
1353 }
1354 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1355 {
1356 png_ptr->background.red =
1357 png_ptr->background.green =
1358 png_ptr->background.blue =
1359 png_ptr->background.gray = png_get_uint_16(buf);
1360 }
1361 else
1362 {
1363 png_ptr->background.red = png_get_uint_16(buf);
1364 png_ptr->background.green = png_get_uint_16(buf + 2);
1365 png_ptr->background.blue = png_get_uint_16(buf + 4);
1366 }
1368 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1369 }
1370 #endif
1372 #if defined(PNG_READ_hIST_SUPPORTED)
1373 void /* PRIVATE */
1374 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1375 {
1376 int num, i;
1377 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1379 png_debug(1, "in png_handle_hIST\n");
1381 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1382 png_error(png_ptr, "Missing IHDR before hIST");
1383 else if (png_ptr->mode & PNG_HAVE_IDAT)
1384 {
1385 png_warning(png_ptr, "Invalid hIST after IDAT");
1386 png_crc_finish(png_ptr, length);
1387 return;
1388 }
1389 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1390 {
1391 png_warning(png_ptr, "Missing PLTE before hIST");
1392 png_crc_finish(png_ptr, length);
1393 return;
1394 }
1395 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1396 {
1397 png_warning(png_ptr, "Duplicate hIST chunk");
1398 png_crc_finish(png_ptr, length);
1399 return;
1400 }
1402 num = (int)length / 2 ;
1403 if (num != png_ptr->num_palette)
1404 {
1405 png_warning(png_ptr, "Incorrect hIST chunk length");
1406 png_crc_finish(png_ptr, length);
1407 return;
1408 }
1410 for (i = 0; i < num; i++)
1411 {
1412 png_byte buf[2];
1414 png_crc_read(png_ptr, buf, 2);
1415 readbuf[i] = png_get_uint_16(buf);
1416 }
1418 if (png_crc_finish(png_ptr, 0))
1419 return;
1421 png_set_hIST(png_ptr, info_ptr, readbuf);
1422 }
1423 #endif
1425 #if defined(PNG_READ_pHYs_SUPPORTED)
1426 void /* PRIVATE */
1427 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1428 {
1429 png_byte buf[9];
1430 png_uint_32 res_x, res_y;
1431 int unit_type;
1433 png_debug(1, "in png_handle_pHYs\n");
1435 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1436 png_error(png_ptr, "Missing IHDR before pHYs");
1437 else if (png_ptr->mode & PNG_HAVE_IDAT)
1438 {
1439 png_warning(png_ptr, "Invalid pHYs after IDAT");
1440 png_crc_finish(png_ptr, length);
1441 return;
1442 }
1443 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1444 {
1445 png_warning(png_ptr, "Duplicate pHYs chunk");
1446 png_crc_finish(png_ptr, length);
1447 return;
1448 }
1450 if (length != 9)
1451 {
1452 png_warning(png_ptr, "Incorrect pHYs chunk length");
1453 png_crc_finish(png_ptr, length);
1454 return;
1455 }
1457 png_crc_read(png_ptr, buf, 9);
1458 if (png_crc_finish(png_ptr, 0))
1459 return;
1461 res_x = png_get_uint_32(buf);
1462 res_y = png_get_uint_32(buf + 4);
1463 unit_type = buf[8];
1464 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1465 }
1466 #endif
1468 #if defined(PNG_READ_oFFs_SUPPORTED)
1469 void /* PRIVATE */
1470 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1471 {
1472 png_byte buf[9];
1473 png_int_32 offset_x, offset_y;
1474 int unit_type;
1476 png_debug(1, "in png_handle_oFFs\n");
1478 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1479 png_error(png_ptr, "Missing IHDR before oFFs");
1480 else if (png_ptr->mode & PNG_HAVE_IDAT)
1481 {
1482 png_warning(png_ptr, "Invalid oFFs after IDAT");
1483 png_crc_finish(png_ptr, length);
1484 return;
1485 }
1486 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1487 {
1488 png_warning(png_ptr, "Duplicate oFFs chunk");
1489 png_crc_finish(png_ptr, length);
1490 return;
1491 }
1493 if (length != 9)
1494 {
1495 png_warning(png_ptr, "Incorrect oFFs chunk length");
1496 png_crc_finish(png_ptr, length);
1497 return;
1498 }
1500 png_crc_read(png_ptr, buf, 9);
1501 if (png_crc_finish(png_ptr, 0))
1502 return;
1504 offset_x = png_get_int_32(buf);
1505 offset_y = png_get_int_32(buf + 4);
1506 unit_type = buf[8];
1507 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1508 }
1509 #endif
1511 #if defined(PNG_READ_pCAL_SUPPORTED)
1512 /* read the pCAL chunk (described in the PNG Extensions document) */
1513 void /* PRIVATE */
1514 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1515 {
1516 png_charp purpose;
1517 png_int_32 X0, X1;
1518 png_byte type, nparams;
1519 png_charp buf, units, endptr;
1520 png_charpp params;
1521 png_size_t slength;
1522 int i;
1524 png_debug(1, "in png_handle_pCAL\n");
1526 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1527 png_error(png_ptr, "Missing IHDR before pCAL");
1528 else if (png_ptr->mode & PNG_HAVE_IDAT)
1529 {
1530 png_warning(png_ptr, "Invalid pCAL after IDAT");
1531 png_crc_finish(png_ptr, length);
1532 return;
1533 }
1534 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1535 {
1536 png_warning(png_ptr, "Duplicate pCAL chunk");
1537 png_crc_finish(png_ptr, length);
1538 return;
1539 }
1541 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
1542 length + 1);
1543 purpose = (png_charp)png_malloc(png_ptr, length + 1);
1544 slength = (png_size_t)length;
1545 png_crc_read(png_ptr, (png_bytep)purpose, slength);
1547 if (png_crc_finish(png_ptr, 0))
1548 {
1549 png_free(png_ptr, purpose);
1550 return;
1551 }
1553 purpose[slength] = 0x00; /* null terminate the last string */
1555 png_debug(3, "Finding end of pCAL purpose string\n");
1556 for (buf = purpose; *buf; buf++)
1557 /* empty loop */ ;
1559 endptr = purpose + slength;
1561 /* We need to have at least 12 bytes after the purpose string
1562 in order to get the parameter information. */
1563 if (endptr <= buf + 12)
1564 {
1565 png_warning(png_ptr, "Invalid pCAL data");
1566 png_free(png_ptr, purpose);
1567 return;
1568 }
1570 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1571 X0 = png_get_int_32((png_bytep)buf+1);
1572 X1 = png_get_int_32((png_bytep)buf+5);
1573 type = buf[9];
1574 nparams = buf[10];
1575 units = buf + 11;
1577 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1578 /* Check that we have the right number of parameters for known
1579 equation types. */
1580 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1581 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1582 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1583 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1584 {
1585 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1586 png_free(png_ptr, purpose);
1587 return;
1588 }
1589 else if (type >= PNG_EQUATION_LAST)
1590 {
1591 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1592 }
1594 for (buf = units; *buf; buf++)
1595 /* Empty loop to move past the units string. */ ;
1597 png_debug(3, "Allocating pCAL parameters array\n");
1598 params = (png_charpp)png_malloc(png_ptr, (png_uint_32)(nparams
1599 *sizeof(png_charp))) ;
1601 /* Get pointers to the start of each parameter string. */
1602 for (i = 0; i < (int)nparams; i++)
1603 {
1604 buf++; /* Skip the null string terminator from previous parameter. */
1606 png_debug1(3, "Reading pCAL parameter %d\n", i);
1607 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
1608 /* Empty loop to move past each parameter string */ ;
1610 /* Make sure we haven't run out of data yet */
1611 if (buf > endptr)
1612 {
1613 png_warning(png_ptr, "Invalid pCAL data");
1614 png_free(png_ptr, purpose);
1615 png_free(png_ptr, params);
1616 return;
1617 }
1618 }
1620 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1621 units, params);
1623 png_free(png_ptr, purpose);
1624 png_free(png_ptr, params);
1625 }
1626 #endif
1628 #if defined(PNG_READ_sCAL_SUPPORTED)
1629 /* read the sCAL chunk */
1630 void /* PRIVATE */
1631 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1632 {
1633 png_charp buffer, ep;
1634 #ifdef PNG_FLOATING_POINT_SUPPORTED
1635 double width, height;
1636 png_charp vp;
1637 #else
1638 #ifdef PNG_FIXED_POINT_SUPPORTED
1639 png_charp swidth, sheight;
1640 #endif
1641 #endif
1642 png_size_t slength;
1644 png_debug(1, "in png_handle_sCAL\n");
1646 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1647 png_error(png_ptr, "Missing IHDR before sCAL");
1648 else if (png_ptr->mode & PNG_HAVE_IDAT)
1649 {
1650 png_warning(png_ptr, "Invalid sCAL after IDAT");
1651 png_crc_finish(png_ptr, length);
1652 return;
1653 }
1654 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1655 {
1656 png_warning(png_ptr, "Duplicate sCAL chunk");
1657 png_crc_finish(png_ptr, length);
1658 return;
1659 }
1661 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1662 length + 1);
1663 buffer = (png_charp)png_malloc(png_ptr, length + 1);
1664 slength = (png_size_t)length;
1665 png_crc_read(png_ptr, (png_bytep)buffer, slength);
1667 if (png_crc_finish(png_ptr, 0))
1668 {
1669 png_free(png_ptr, buffer);
1670 return;
1671 }
1673 buffer[slength] = 0x00; /* null terminate the last string */
1675 ep = buffer + 1; /* skip unit byte */
1677 #ifdef PNG_FLOATING_POINT_SUPPORTED
1678 width = strtod(ep, &vp);
1679 if (*vp)
1680 {
1681 png_warning(png_ptr, "malformed width string in sCAL chunk");
1682 return;
1683 }
1684 #else
1685 #ifdef PNG_FIXED_POINT_SUPPORTED
1686 swidth = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1);
1687 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1688 #endif
1689 #endif
1691 for (ep = buffer; *ep; ep++)
1692 /* empty loop */ ;
1693 ep++;
1695 #ifdef PNG_FLOATING_POINT_SUPPORTED
1696 height = strtod(ep, &vp);
1697 if (*vp)
1698 {
1699 png_warning(png_ptr, "malformed height string in sCAL chunk");
1700 return;
1701 }
1702 #else
1703 #ifdef PNG_FIXED_POINT_SUPPORTED
1704 sheight = (png_charp)png_malloc(png_ptr, png_strlen(ep) + 1);
1705 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1706 #endif
1707 #endif
1709 if (buffer + slength < ep
1710 #ifdef PNG_FLOATING_POINT_SUPPORTED
1711 || width <= 0. || height <= 0.
1712 #endif
1713 )
1714 {
1715 png_warning(png_ptr, "Invalid sCAL data");
1716 png_free(png_ptr, buffer);
1717 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1718 png_free(png_ptr, swidth);
1719 png_free(png_ptr, sheight);
1720 #endif
1721 return;
1722 }
1725 #ifdef PNG_FLOATING_POINT_SUPPORTED
1726 png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1727 #else
1728 #ifdef PNG_FIXED_POINT_SUPPORTED
1729 png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1730 #endif
1731 #endif
1733 png_free(png_ptr, buffer);
1734 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1735 png_free(png_ptr, swidth);
1736 png_free(png_ptr, sheight);
1737 #endif
1738 }
1739 #endif
1741 #if defined(PNG_READ_tIME_SUPPORTED)
1742 void /* PRIVATE */
1743 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1744 {
1745 png_byte buf[7];
1746 png_time mod_time;
1748 png_debug(1, "in png_handle_tIME\n");
1750 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1751 png_error(png_ptr, "Out of place tIME chunk");
1752 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1753 {
1754 png_warning(png_ptr, "Duplicate tIME chunk");
1755 png_crc_finish(png_ptr, length);
1756 return;
1757 }
1759 if (png_ptr->mode & PNG_HAVE_IDAT)
1760 png_ptr->mode |= PNG_AFTER_IDAT;
1762 if (length != 7)
1763 {
1764 png_warning(png_ptr, "Incorrect tIME chunk length");
1765 png_crc_finish(png_ptr, length);
1766 return;
1767 }
1769 png_crc_read(png_ptr, buf, 7);
1770 if (png_crc_finish(png_ptr, 0))
1771 return;
1773 mod_time.second = buf[6];
1774 mod_time.minute = buf[5];
1775 mod_time.hour = buf[4];
1776 mod_time.day = buf[3];
1777 mod_time.month = buf[2];
1778 mod_time.year = png_get_uint_16(buf);
1780 png_set_tIME(png_ptr, info_ptr, &mod_time);
1781 }
1782 #endif
1784 #if defined(PNG_READ_tEXt_SUPPORTED)
1785 /* Note: this does not properly handle chunks that are > 64K under DOS */
1786 void /* PRIVATE */
1787 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1788 {
1789 png_textp text_ptr;
1790 png_charp key;
1791 png_charp text;
1792 png_uint_32 skip = 0;
1793 png_size_t slength;
1795 png_debug(1, "in png_handle_tEXt\n");
1797 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1798 png_error(png_ptr, "Missing IHDR before tEXt");
1800 if (png_ptr->mode & PNG_HAVE_IDAT)
1801 png_ptr->mode |= PNG_AFTER_IDAT;
1803 #ifdef PNG_MAX_MALLOC_64K
1804 if (length > (png_uint_32)65535L)
1805 {
1806 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1807 skip = length - (png_uint_32)65535L;
1808 length = (png_uint_32)65535L;
1809 }
1810 #endif
1812 key = (png_charp)png_malloc(png_ptr, length + 1);
1813 slength = (png_size_t)length;
1814 png_crc_read(png_ptr, (png_bytep)key, slength);
1816 if (png_crc_finish(png_ptr, skip))
1817 {
1818 png_free(png_ptr, key);
1819 return;
1820 }
1822 key[slength] = 0x00;
1824 for (text = key; *text; text++)
1825 /* empty loop to find end of key */ ;
1827 if (text != key + slength)
1828 text++;
1830 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1831 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1832 text_ptr->key = key;
1833 #ifdef PNG_iTXt_SUPPORTED
1834 text_ptr->lang = NULL;
1835 text_ptr->lang_key = NULL;
1836 text_ptr->itxt_length = 0;
1837 #endif
1838 text_ptr->text = text;
1839 text_ptr->text_length = png_strlen(text);
1841 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1843 png_free(png_ptr, key);
1844 png_free(png_ptr, text_ptr);
1845 }
1846 #endif
1848 #if defined(PNG_READ_zTXt_SUPPORTED)
1849 /* note: this does not correctly handle chunks that are > 64K under DOS */
1850 void /* PRIVATE */
1851 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1852 {
1853 png_textp text_ptr;
1854 png_charp chunkdata;
1855 png_charp text;
1856 int comp_type;
1857 png_size_t slength, prefix_len, data_len;
1859 png_debug(1, "in png_handle_zTXt\n");
1860 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1861 png_error(png_ptr, "Missing IHDR before zTXt");
1863 if (png_ptr->mode & PNG_HAVE_IDAT)
1864 png_ptr->mode |= PNG_AFTER_IDAT;
1866 #ifdef PNG_MAX_MALLOC_64K
1867 /* We will no doubt have problems with chunks even half this size, but
1868 there is no hard and fast rule to tell us where to stop. */
1869 if (length > (png_uint_32)65535L)
1870 {
1871 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1872 png_crc_finish(png_ptr, length);
1873 return;
1874 }
1875 #endif
1877 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1878 slength = (png_size_t)length;
1879 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1880 if (png_crc_finish(png_ptr, 0))
1881 {
1882 png_free(png_ptr, chunkdata);
1883 return;
1884 }
1886 chunkdata[slength] = 0x00;
1888 for (text = chunkdata; *text; text++)
1889 /* empty loop */ ;
1891 /* zTXt must have some text after the chunkdataword */
1892 if (text == chunkdata + slength)
1893 {
1894 comp_type = PNG_TEXT_COMPRESSION_NONE;
1895 png_warning(png_ptr, "Zero length zTXt chunk");
1896 }
1897 else
1898 {
1899 comp_type = *(++text);
1900 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
1901 {
1902 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
1903 comp_type = PNG_TEXT_COMPRESSION_zTXt;
1904 }
1905 text++; /* skip the compression_method byte */
1906 }
1907 prefix_len = text - chunkdata;
1909 chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
1910 (png_size_t)length, prefix_len, &data_len);
1912 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1913 text_ptr->compression = comp_type;
1914 text_ptr->key = chunkdata;
1915 #ifdef PNG_iTXt_SUPPORTED
1916 text_ptr->lang = NULL;
1917 text_ptr->lang_key = NULL;
1918 text_ptr->itxt_length = 0;
1919 #endif
1920 text_ptr->text = chunkdata + prefix_len;
1921 text_ptr->text_length = data_len;
1923 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1925 png_free(png_ptr, text_ptr);
1926 png_free(png_ptr, chunkdata);
1927 }
1928 #endif
1930 #if defined(PNG_READ_iTXt_SUPPORTED)
1931 /* note: this does not correctly handle chunks that are > 64K under DOS */
1932 void /* PRIVATE */
1933 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1934 {
1935 png_textp text_ptr;
1936 png_charp chunkdata;
1937 png_charp key, lang, text, lang_key;
1938 int comp_flag;
1939 int comp_type = 0;
1940 png_size_t slength, prefix_len, data_len;
1942 png_debug(1, "in png_handle_iTXt\n");
1944 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1945 png_error(png_ptr, "Missing IHDR before iTXt");
1947 if (png_ptr->mode & PNG_HAVE_IDAT)
1948 png_ptr->mode |= PNG_AFTER_IDAT;
1950 #ifdef PNG_MAX_MALLOC_64K
1951 /* We will no doubt have problems with chunks even half this size, but
1952 there is no hard and fast rule to tell us where to stop. */
1953 if (length > (png_uint_32)65535L)
1954 {
1955 png_warning(png_ptr,"iTXt chunk too large to fit in memory");
1956 png_crc_finish(png_ptr, length);
1957 return;
1958 }
1959 #endif
1961 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1962 slength = (png_size_t)length;
1963 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1964 if (png_crc_finish(png_ptr, 0))
1965 {
1966 png_free(png_ptr, chunkdata);
1967 return;
1968 }
1970 chunkdata[slength] = 0x00;
1972 for (lang = chunkdata; *lang; lang++)
1973 /* empty loop */ ;
1974 lang++; /* skip NUL separator */
1976 /* iTXt must have a language tag (possibly empty), two compression bytes,
1977 translated keyword (possibly empty), and possibly some text after the
1978 keyword */
1980 if (lang >= chunkdata + slength)
1981 {
1982 comp_flag = PNG_TEXT_COMPRESSION_NONE;
1983 png_warning(png_ptr, "Zero length iTXt chunk");
1984 }
1985 else
1986 {
1987 comp_flag = *lang++;
1988 comp_type = *lang++;
1989 }
1991 for (lang_key = lang; *lang_key; lang_key++)
1992 /* empty loop */ ;
1993 lang_key++; /* skip NUL separator */
1995 for (text = lang_key; *text; text++)
1996 /* empty loop */ ;
1997 text++; /* skip NUL separator */
1999 prefix_len = text - chunkdata;
2001 key=chunkdata;
2002 if (comp_flag)
2003 chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
2004 (size_t)length, prefix_len, &data_len);
2005 else
2006 data_len=png_strlen(chunkdata + prefix_len);
2007 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
2008 text_ptr->compression = (int)comp_flag + 1;
2009 text_ptr->lang_key = chunkdata+(lang_key-key);
2010 text_ptr->lang = chunkdata+(lang-key);
2011 text_ptr->itxt_length = data_len;
2012 text_ptr->text_length = 0;
2013 text_ptr->key = chunkdata;
2014 text_ptr->text = chunkdata + prefix_len;
2016 png_set_text(png_ptr, info_ptr, text_ptr, 1);
2018 png_free(png_ptr, text_ptr);
2019 png_free(png_ptr, chunkdata);
2020 }
2021 #endif
2023 /* This function is called when we haven't found a handler for a
2024 chunk. If there isn't a problem with the chunk itself (ie bad
2025 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2026 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2027 case it will be saved away to be written out later. */
2028 void /* PRIVATE */
2029 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2030 {
2031 png_uint_32 skip = 0;
2033 png_debug(1, "in png_handle_unknown\n");
2035 if (png_ptr->mode & PNG_HAVE_IDAT)
2036 {
2037 #ifdef PNG_USE_LOCAL_ARRAYS
2038 PNG_IDAT;
2039 #endif
2040 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2041 png_ptr->mode |= PNG_AFTER_IDAT;
2042 }
2044 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
2046 if (!(png_ptr->chunk_name[0] & 0x20))
2047 {
2048 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2049 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2050 HANDLE_CHUNK_ALWAYS
2051 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2052 && png_ptr->read_user_chunk_fn == NULL
2053 #endif
2054 )
2055 #endif
2056 png_chunk_error(png_ptr, "unknown critical chunk");
2057 }
2059 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2060 if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
2061 {
2062 png_unknown_chunk chunk;
2064 #ifdef PNG_MAX_MALLOC_64K
2065 if (length > (png_uint_32)65535L)
2066 {
2067 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2068 skip = length - (png_uint_32)65535L;
2069 length = (png_uint_32)65535L;
2070 }
2071 #endif
2072 png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
2073 chunk.data = (png_bytep)png_malloc(png_ptr, length);
2074 chunk.size = (png_size_t)length;
2075 png_crc_read(png_ptr, (png_bytep)chunk.data, length);
2076 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2077 if(png_ptr->read_user_chunk_fn != NULL)
2078 {
2079 /* callback to user unknown chunk handler */
2080 if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
2081 {
2082 if (!(png_ptr->chunk_name[0] & 0x20))
2083 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2084 HANDLE_CHUNK_ALWAYS)
2085 png_chunk_error(png_ptr, "unknown critical chunk");
2086 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2087 }
2088 }
2089 else
2090 #endif
2091 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2092 png_free(png_ptr, chunk.data);
2093 }
2094 else
2095 #endif
2096 skip = length;
2098 png_crc_finish(png_ptr, skip);
2100 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2101 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
2102 #endif
2103 }
2105 /* This function is called to verify that a chunk name is valid.
2106 This function can't have the "critical chunk check" incorporated
2107 into it, since in the future we will need to be able to call user
2108 functions to handle unknown critical chunks after we check that
2109 the chunk name itself is valid. */
2111 #define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
2113 void /* PRIVATE */
2114 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2115 {
2116 png_debug(1, "in png_check_chunk_name\n");
2117 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2118 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2119 {
2120 png_chunk_error(png_ptr, "invalid chunk type");
2121 }
2122 }
2124 /* Combines the row recently read in with the existing pixels in the
2125 row. This routine takes care of alpha and transparency if requested.
2126 This routine also handles the two methods of progressive display
2127 of interlaced images, depending on the mask value.
2128 The mask value describes which pixels are to be combined with
2129 the row. The pattern always repeats every 8 pixels, so just 8
2130 bits are needed. A one indicates the pixel is to be combined,
2131 a zero indicates the pixel is to be skipped. This is in addition
2132 to any alpha or transparency value associated with the pixel. If
2133 you want all pixels to be combined, pass 0xff (255) in mask. */
2134 #ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
2135 void /* PRIVATE */
2136 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2137 {
2138 png_debug(1,"in png_combine_row\n");
2139 if (mask == 0xff)
2140 {
2141 png_memcpy(row, png_ptr->row_buf + 1,
2142 (png_size_t)((png_ptr->width *
2143 png_ptr->row_info.pixel_depth + 7) >> 3));
2144 }
2145 else
2146 {
2147 switch (png_ptr->row_info.pixel_depth)
2148 {
2149 case 1:
2150 {
2151 png_bytep sp = png_ptr->row_buf + 1;
2152 png_bytep dp = row;
2153 int s_inc, s_start, s_end;
2154 int m = 0x80;
2155 int shift;
2156 png_uint_32 i;
2157 png_uint_32 row_width = png_ptr->width;
2159 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2160 if (png_ptr->transformations & PNG_PACKSWAP)
2161 {
2162 s_start = 0;
2163 s_end = 7;
2164 s_inc = 1;
2165 }
2166 else
2167 #endif
2168 {
2169 s_start = 7;
2170 s_end = 0;
2171 s_inc = -1;
2172 }
2174 shift = s_start;
2176 for (i = 0; i < row_width; i++)
2177 {
2178 if (m & mask)
2179 {
2180 int value;
2182 value = (*sp >> shift) & 0x01;
2183 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2184 *dp |= (png_byte)(value << shift);
2185 }
2187 if (shift == s_end)
2188 {
2189 shift = s_start;
2190 sp++;
2191 dp++;
2192 }
2193 else
2194 shift += s_inc;
2196 if (m == 1)
2197 m = 0x80;
2198 else
2199 m >>= 1;
2200 }
2201 break;
2202 }
2203 case 2:
2204 {
2205 png_bytep sp = png_ptr->row_buf + 1;
2206 png_bytep dp = row;
2207 int s_start, s_end, s_inc;
2208 int m = 0x80;
2209 int shift;
2210 png_uint_32 i;
2211 png_uint_32 row_width = png_ptr->width;
2212 int value;
2214 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2215 if (png_ptr->transformations & PNG_PACKSWAP)
2216 {
2217 s_start = 0;
2218 s_end = 6;
2219 s_inc = 2;
2220 }
2221 else
2222 #endif
2223 {
2224 s_start = 6;
2225 s_end = 0;
2226 s_inc = -2;
2227 }
2229 shift = s_start;
2231 for (i = 0; i < row_width; i++)
2232 {
2233 if (m & mask)
2234 {
2235 value = (*sp >> shift) & 0x03;
2236 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2237 *dp |= (png_byte)(value << shift);
2238 }
2240 if (shift == s_end)
2241 {
2242 shift = s_start;
2243 sp++;
2244 dp++;
2245 }
2246 else
2247 shift += s_inc;
2248 if (m == 1)
2249 m = 0x80;
2250 else
2251 m >>= 1;
2252 }
2253 break;
2254 }
2255 case 4:
2256 {
2257 png_bytep sp = png_ptr->row_buf + 1;
2258 png_bytep dp = row;
2259 int s_start, s_end, s_inc;
2260 int m = 0x80;
2261 int shift;
2262 png_uint_32 i;
2263 png_uint_32 row_width = png_ptr->width;
2264 int value;
2266 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2267 if (png_ptr->transformations & PNG_PACKSWAP)
2268 {
2269 s_start = 0;
2270 s_end = 4;
2271 s_inc = 4;
2272 }
2273 else
2274 #endif
2275 {
2276 s_start = 4;
2277 s_end = 0;
2278 s_inc = -4;
2279 }
2280 shift = s_start;
2282 for (i = 0; i < row_width; i++)
2283 {
2284 if (m & mask)
2285 {
2286 value = (*sp >> shift) & 0xf;
2287 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2288 *dp |= (png_byte)(value << shift);
2289 }
2291 if (shift == s_end)
2292 {
2293 shift = s_start;
2294 sp++;
2295 dp++;
2296 }
2297 else
2298 shift += s_inc;
2299 if (m == 1)
2300 m = 0x80;
2301 else
2302 m >>= 1;
2303 }
2304 break;
2305 }
2306 default:
2307 {
2308 png_bytep sp = png_ptr->row_buf + 1;
2309 png_bytep dp = row;
2310 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2311 png_uint_32 i;
2312 png_uint_32 row_width = png_ptr->width;
2313 png_byte m = 0x80;
2316 for (i = 0; i < row_width; i++)
2317 {
2318 if (m & mask)
2319 {
2320 png_memcpy(dp, sp, pixel_bytes);
2321 }
2323 sp += pixel_bytes;
2324 dp += pixel_bytes;
2326 if (m == 1)
2327 m = 0x80;
2328 else
2329 m >>= 1;
2330 }
2331 break;
2332 }
2333 }
2334 }
2335 }
2336 #endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
2338 #ifdef PNG_READ_INTERLACING_SUPPORTED
2339 #ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */
2340 /* OLD pre-1.0.9 interface:
2341 void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2342 png_uint_32 transformations)
2343 */
2344 void /* PRIVATE */
2345 png_do_read_interlace(png_structp png_ptr)
2346 {
2347 png_row_infop row_info = &(png_ptr->row_info);
2348 png_bytep row = png_ptr->row_buf + 1;
2349 int pass = png_ptr->pass;
2350 png_uint_32 transformations = png_ptr->transformations;
2351 #ifdef PNG_USE_LOCAL_ARRAYS
2352 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2353 /* offset to next interlace block */
2354 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2355 #endif
2357 png_debug(1,"in png_do_read_interlace (stock C version)\n");
2358 if (row != NULL && row_info != NULL)
2359 {
2360 png_uint_32 final_width;
2362 final_width = row_info->width * png_pass_inc[pass];
2364 switch (row_info->pixel_depth)
2365 {
2366 case 1:
2367 {
2368 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2369 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2370 int sshift, dshift;
2371 int s_start, s_end, s_inc;
2372 int jstop = png_pass_inc[pass];
2373 png_byte v;
2374 png_uint_32 i;
2375 int j;
2377 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2378 if (transformations & PNG_PACKSWAP)
2379 {
2380 sshift = (int)((row_info->width + 7) & 0x07);
2381 dshift = (int)((final_width + 7) & 0x07);
2382 s_start = 7;
2383 s_end = 0;
2384 s_inc = -1;
2385 }
2386 else
2387 #endif
2388 {
2389 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2390 dshift = 7 - (int)((final_width + 7) & 0x07);
2391 s_start = 0;
2392 s_end = 7;
2393 s_inc = 1;
2394 }
2396 for (i = 0; i < row_info->width; i++)
2397 {
2398 v = (png_byte)((*sp >> sshift) & 0x01);
2399 for (j = 0; j < jstop; j++)
2400 {
2401 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2402 *dp |= (png_byte)(v << dshift);
2403 if (dshift == s_end)
2404 {
2405 dshift = s_start;
2406 dp--;
2407 }
2408 else
2409 dshift += s_inc;
2410 }
2411 if (sshift == s_end)
2412 {
2413 sshift = s_start;
2414 sp--;
2415 }
2416 else
2417 sshift += s_inc;
2418 }
2419 break;
2420 }
2421 case 2:
2422 {
2423 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2424 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2425 int sshift, dshift;
2426 int s_start, s_end, s_inc;
2427 int jstop = png_pass_inc[pass];
2428 png_uint_32 i;
2430 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2431 if (transformations & PNG_PACKSWAP)
2432 {
2433 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2434 dshift = (int)(((final_width + 3) & 0x03) << 1);
2435 s_start = 6;
2436 s_end = 0;
2437 s_inc = -2;
2438 }
2439 else
2440 #endif
2441 {
2442 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2443 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2444 s_start = 0;
2445 s_end = 6;
2446 s_inc = 2;
2447 }
2449 for (i = 0; i < row_info->width; i++)
2450 {
2451 png_byte v;
2452 int j;
2454 v = (png_byte)((*sp >> sshift) & 0x03);
2455 for (j = 0; j < jstop; j++)
2456 {
2457 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2458 *dp |= (png_byte)(v << dshift);
2459 if (dshift == s_end)
2460 {
2461 dshift = s_start;
2462 dp--;
2463 }
2464 else
2465 dshift += s_inc;
2466 }
2467 if (sshift == s_end)
2468 {
2469 sshift = s_start;
2470 sp--;
2471 }
2472 else
2473 sshift += s_inc;
2474 }
2475 break;
2476 }
2477 case 4:
2478 {
2479 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2480 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2481 int sshift, dshift;
2482 int s_start, s_end, s_inc;
2483 png_uint_32 i;
2484 int jstop = png_pass_inc[pass];
2486 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2487 if (transformations & PNG_PACKSWAP)
2488 {
2489 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2490 dshift = (int)(((final_width + 1) & 0x01) << 2);
2491 s_start = 4;
2492 s_end = 0;
2493 s_inc = -4;
2494 }
2495 else
2496 #endif
2497 {
2498 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2499 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2500 s_start = 0;
2501 s_end = 4;
2502 s_inc = 4;
2503 }
2505 for (i = 0; i < row_info->width; i++)
2506 {
2507 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2508 int j;
2510 for (j = 0; j < jstop; j++)
2511 {
2512 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2513 *dp |= (png_byte)(v << dshift);
2514 if (dshift == s_end)
2515 {
2516 dshift = s_start;
2517 dp--;
2518 }
2519 else
2520 dshift += s_inc;
2521 }
2522 if (sshift == s_end)
2523 {
2524 sshift = s_start;
2525 sp--;
2526 }
2527 else
2528 sshift += s_inc;
2529 }
2530 break;
2531 }
2532 default:
2533 {
2534 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2535 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2536 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2538 int jstop = png_pass_inc[pass];
2539 png_uint_32 i;
2541 for (i = 0; i < row_info->width; i++)
2542 {
2543 png_byte v[8];
2544 int j;
2546 png_memcpy(v, sp, pixel_bytes);
2547 for (j = 0; j < jstop; j++)
2548 {
2549 png_memcpy(dp, v, pixel_bytes);
2550 dp -= pixel_bytes;
2551 }
2552 sp -= pixel_bytes;
2553 }
2554 break;
2555 }
2556 }
2557 row_info->width = final_width;
2558 row_info->rowbytes = ((final_width *
2559 (png_uint_32)row_info->pixel_depth + 7) >> 3);
2560 }
2561 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2562 transformations = transformations; /* silence compiler warning */
2563 #endif
2564 }
2565 #endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
2566 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2568 #ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
2569 void /* PRIVATE */
2570 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2571 png_bytep prev_row, int filter)
2572 {
2573 png_debug(1, "in png_read_filter_row\n");
2574 png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
2575 switch (filter)
2576 {
2577 case PNG_FILTER_VALUE_NONE:
2578 break;
2579 case PNG_FILTER_VALUE_SUB:
2580 {
2581 png_uint_32 i;
2582 png_uint_32 istop = row_info->rowbytes;
2583 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2584 png_bytep rp = row + bpp;
2585 png_bytep lp = row;
2587 for (i = bpp; i < istop; i++)
2588 {
2589 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2590 rp++;
2591 }
2592 break;
2593 }
2594 case PNG_FILTER_VALUE_UP:
2595 {
2596 png_uint_32 i;
2597 png_uint_32 istop = row_info->rowbytes;
2598 png_bytep rp = row;
2599 png_bytep pp = prev_row;
2601 for (i = 0; i < istop; i++)
2602 {
2603 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2604 rp++;
2605 }
2606 break;
2607 }
2608 case PNG_FILTER_VALUE_AVG:
2609 {
2610 png_uint_32 i;
2611 png_bytep rp = row;
2612 png_bytep pp = prev_row;
2613 png_bytep lp = row;
2614 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2615 png_uint_32 istop = row_info->rowbytes - bpp;
2617 for (i = 0; i < bpp; i++)
2618 {
2619 *rp = (png_byte)(((int)(*rp) +
2620 ((int)(*pp++) / 2 )) & 0xff);
2621 rp++;
2622 }
2624 for (i = 0; i < istop; i++)
2625 {
2626 *rp = (png_byte)(((int)(*rp) +
2627 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2628 rp++;
2629 }
2630 break;
2631 }
2632 case PNG_FILTER_VALUE_PAETH:
2633 {
2634 png_uint_32 i;
2635 png_bytep rp = row;
2636 png_bytep pp = prev_row;
2637 png_bytep lp = row;
2638 png_bytep cp = prev_row;
2639 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2640 png_uint_32 istop=row_info->rowbytes - bpp;
2642 for (i = 0; i < bpp; i++)
2643 {
2644 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2645 rp++;
2646 }
2648 for (i = 0; i < istop; i++) /* use leftover rp,pp */
2649 {
2650 int a, b, c, pa, pb, pc, p;
2652 a = *lp++;
2653 b = *pp++;
2654 c = *cp++;
2656 p = b - c;
2657 pc = a - c;
2659 #ifdef PNG_USE_ABS
2660 pa = abs(p);
2661 pb = abs(pc);
2662 pc = abs(p + pc);
2663 #else
2664 pa = p < 0 ? -p : p;
2665 pb = pc < 0 ? -pc : pc;
2666 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2667 #endif
2669 /*
2670 if (pa <= pb && pa <= pc)
2671 p = a;
2672 else if (pb <= pc)
2673 p = b;
2674 else
2675 p = c;
2676 */
2678 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2680 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2681 rp++;
2682 }
2683 break;
2684 }
2685 default:
2686 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2687 *row=0;
2688 break;
2689 }
2690 }
2691 #endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
2693 void /* PRIVATE */
2694 png_read_finish_row(png_structp png_ptr)
2695 {
2696 #ifdef PNG_USE_LOCAL_ARRAYS
2697 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2699 /* start of interlace block */
2700 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2702 /* offset to next interlace block */
2703 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2705 /* start of interlace block in the y direction */
2706 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2708 /* offset to next interlace block in the y direction */
2709 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2710 #endif
2712 png_debug(1, "in png_read_finish_row\n");
2713 png_ptr->row_number++;
2714 if (png_ptr->row_number < png_ptr->num_rows)
2715 return;
2717 if (png_ptr->interlaced)
2718 {
2719 png_ptr->row_number = 0;
2720 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
2721 do
2722 {
2723 png_ptr->pass++;
2724 if (png_ptr->pass >= 7)
2725 break;
2726 png_ptr->iwidth = (png_ptr->width +
2727 png_pass_inc[png_ptr->pass] - 1 -
2728 png_pass_start[png_ptr->pass]) /
2729 png_pass_inc[png_ptr->pass];
2730 png_ptr->irowbytes = ((png_ptr->iwidth *
2731 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2733 if (!(png_ptr->transformations & PNG_INTERLACE))
2734 {
2735 png_ptr->num_rows = (png_ptr->height +
2736 png_pass_yinc[png_ptr->pass] - 1 -
2737 png_pass_ystart[png_ptr->pass]) /
2738 png_pass_yinc[png_ptr->pass];
2739 if (!(png_ptr->num_rows))
2740 continue;
2741 }
2742 else /* if (png_ptr->transformations & PNG_INTERLACE) */
2743 break;
2744 } while (png_ptr->iwidth == 0);
2746 if (png_ptr->pass < 7)
2747 return;
2748 }
2750 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
2751 {
2752 #ifdef PNG_USE_LOCAL_ARRAYS
2753 PNG_IDAT;
2754 #endif
2755 char extra;
2756 int ret;
2758 png_ptr->zstream.next_out = (Byte *)&extra;
2759 png_ptr->zstream.avail_out = (uInt)1;
2760 for(;;)
2761 {
2762 if (!(png_ptr->zstream.avail_in))
2763 {
2764 while (!png_ptr->idat_size)
2765 {
2766 png_byte chunk_length[4];
2768 png_crc_finish(png_ptr, 0);
2770 png_read_data(png_ptr, chunk_length, 4);
2771 png_ptr->idat_size = png_get_uint_32(chunk_length);
2773 png_reset_crc(png_ptr);
2774 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2775 if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
2776 png_error(png_ptr, "Not enough image data");
2778 }
2779 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2780 png_ptr->zstream.next_in = png_ptr->zbuf;
2781 if (png_ptr->zbuf_size > png_ptr->idat_size)
2782 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2783 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2784 png_ptr->idat_size -= png_ptr->zstream.avail_in;
2785 }
2786 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
2787 if (ret == Z_STREAM_END)
2788 {
2789 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
2790 png_ptr->idat_size)
2791 png_error(png_ptr, "Extra compressed data");
2792 png_ptr->mode |= PNG_AFTER_IDAT;
2793 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2794 break;
2795 }
2796 if (ret != Z_OK)
2797 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
2798 "Decompression Error");
2800 if (!(png_ptr->zstream.avail_out))
2801 png_error(png_ptr, "Extra compressed data");
2803 }
2804 png_ptr->zstream.avail_out = 0;
2805 }
2807 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
2808 png_error(png_ptr, "Extra compression data");
2810 inflateReset(&png_ptr->zstream);
2812 png_ptr->mode |= PNG_AFTER_IDAT;
2813 }
2815 void /* PRIVATE */
2816 png_read_start_row(png_structp png_ptr)
2817 {
2818 #ifdef PNG_USE_LOCAL_ARRAYS
2819 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2821 /* start of interlace block */
2822 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2824 /* offset to next interlace block */
2825 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2827 /* start of interlace block in the y direction */
2828 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2830 /* offset to next interlace block in the y direction */
2831 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2832 #endif
2834 int max_pixel_depth;
2835 png_uint_32 row_bytes;
2837 png_debug(1, "in png_read_start_row\n");
2838 png_ptr->zstream.avail_in = 0;
2839 png_init_read_transformations(png_ptr);
2840 if (png_ptr->interlaced)
2841 {
2842 if (!(png_ptr->transformations & PNG_INTERLACE))
2843 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2844 png_pass_ystart[0]) / png_pass_yinc[0];
2845 else
2846 png_ptr->num_rows = png_ptr->height;
2848 png_ptr->iwidth = (png_ptr->width +
2849 png_pass_inc[png_ptr->pass] - 1 -
2850 png_pass_start[png_ptr->pass]) /
2851 png_pass_inc[png_ptr->pass];
2853 row_bytes = ((png_ptr->iwidth *
2854 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2855 png_ptr->irowbytes = (png_size_t)row_bytes;
2856 if((png_uint_32)png_ptr->irowbytes != row_bytes)
2857 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
2858 }
2859 else
2860 {
2861 png_ptr->num_rows = png_ptr->height;
2862 png_ptr->iwidth = png_ptr->width;
2863 png_ptr->irowbytes = png_ptr->rowbytes + 1;
2864 }
2865 max_pixel_depth = png_ptr->pixel_depth;
2867 #if defined(PNG_READ_PACK_SUPPORTED)
2868 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
2869 max_pixel_depth = 8;
2870 #endif
2872 #if defined(PNG_READ_EXPAND_SUPPORTED)
2873 if (png_ptr->transformations & PNG_EXPAND)
2874 {
2875 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2876 {
2877 if (png_ptr->num_trans)
2878 max_pixel_depth = 32;
2879 else
2880 max_pixel_depth = 24;
2881 }
2882 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2883 {
2884 if (max_pixel_depth < 8)
2885 max_pixel_depth = 8;
2886 if (png_ptr->num_trans)
2887 max_pixel_depth *= 2;
2888 }
2889 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2890 {
2891 if (png_ptr->num_trans)
2892 {
2893 max_pixel_depth *= 4;
2894 max_pixel_depth /= 3;
2895 }
2896 }
2897 }
2898 #endif
2900 #if defined(PNG_READ_FILLER_SUPPORTED)
2901 if (png_ptr->transformations & (PNG_FILLER))
2902 {
2903 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2904 max_pixel_depth = 32;
2905 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2906 {
2907 if (max_pixel_depth <= 8)
2908 max_pixel_depth = 16;
2909 else
2910 max_pixel_depth = 32;
2911 }
2912 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2913 {
2914 if (max_pixel_depth <= 32)
2915 max_pixel_depth = 32;
2916 else
2917 max_pixel_depth = 64;
2918 }
2919 }
2920 #endif
2922 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2923 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
2924 {
2925 if (
2926 #if defined(PNG_READ_EXPAND_SUPPORTED)
2927 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
2928 #endif
2929 #if defined(PNG_READ_FILLER_SUPPORTED)
2930 (png_ptr->transformations & (PNG_FILLER)) ||
2931 #endif
2932 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2933 {
2934 if (max_pixel_depth <= 16)
2935 max_pixel_depth = 32;
2936 else
2937 max_pixel_depth = 64;
2938 }
2939 else
2940 {
2941 if (max_pixel_depth <= 8)
2942 {
2943 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2944 max_pixel_depth = 32;
2945 else
2946 max_pixel_depth = 24;
2947 }
2948 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2949 max_pixel_depth = 64;
2950 else
2951 max_pixel_depth = 48;
2952 }
2953 }
2954 #endif
2956 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
2957 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
2958 if(png_ptr->transformations & PNG_USER_TRANSFORM)
2959 {
2960 int user_pixel_depth=png_ptr->user_transform_depth*
2961 png_ptr->user_transform_channels;
2962 if(user_pixel_depth > max_pixel_depth)
2963 max_pixel_depth=user_pixel_depth;
2964 }
2965 #endif
2967 /* align the width on the next larger 8 pixels. Mainly used
2968 for interlacing */
2969 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
2970 /* calculate the maximum bytes needed, adding a byte and a pixel
2971 for safety's sake */
2972 row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
2973 1 + ((max_pixel_depth + 7) >> 3);
2974 #ifdef PNG_MAX_MALLOC_64K
2975 if (row_bytes > (png_uint_32)65536L)
2976 png_error(png_ptr, "This image requires a row greater than 64KB");
2977 #endif
2978 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
2979 png_ptr->row_buf = png_ptr->big_row_buf+32;
2980 #if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
2981 png_ptr->row_buf_size = row_bytes;
2982 #endif
2984 #ifdef PNG_MAX_MALLOC_64K
2985 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
2986 png_error(png_ptr, "This image requires a row greater than 64KB");
2987 #endif
2988 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
2989 png_ptr->rowbytes + 1));
2991 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
2993 png_debug1(3, "width = %lu,\n", png_ptr->width);
2994 png_debug1(3, "height = %lu,\n", png_ptr->height);
2995 png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
2996 png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
2997 png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
2998 png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
3000 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3001 }