2 /* pngrutil.c - utilities to read a PNG file
3 *
4 * libpng 1.0.9 - January 31, 2001
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2001 Glenn Randers-Pehrson
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
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 + (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];
335 /* check for width and height valid values */
336 if (width == 0 || width > PNG_MAX_UINT || height == 0 ||
337 height > PNG_MAX_UINT)
338 png_error(png_ptr, "Invalid image size in IHDR");
340 /* check other values */
341 if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
342 bit_depth != 8 && bit_depth != 16)
343 png_error(png_ptr, "Invalid bit depth in IHDR");
345 if (color_type < 0 || color_type == 1 ||
346 color_type == 5 || color_type > 6)
347 png_error(png_ptr, "Invalid color type in IHDR");
349 if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
350 ((color_type == PNG_COLOR_TYPE_RGB ||
351 color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
352 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
353 png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");
355 if (interlace_type >= PNG_INTERLACE_LAST)
356 png_error(png_ptr, "Unknown interlace method in IHDR");
358 if (compression_type != PNG_COMPRESSION_TYPE_BASE)
359 png_error(png_ptr, "Unknown compression method in IHDR");
361 #if defined(PNG_MNG_FEATURES_SUPPORTED)
362 /* Accept filter_method 64 (intrapixel differencing) only if
363 * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
364 * 2. Libpng did not read a PNG signature (this filter_method is only
365 * used in PNG datastreams that are embedded in MNG datastreams) and
366 * 3. The application called png_permit_mng_features with a mask that
367 * included PNG_FLAG_MNG_FILTER_64 and
368 * 4. The filter_method is 64 and
369 * 5. The color_type is RGB or RGBA
370 */
371 if((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)&&png_ptr->mng_features_permitted)
372 png_warning(png_ptr,"MNG features are not allowed in a PNG datastream\n");
373 if(filter_type != PNG_FILTER_TYPE_BASE)
374 {
375 if(!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
376 (filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
377 ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
378 (color_type == PNG_COLOR_TYPE_RGB ||
379 color_type == PNG_COLOR_TYPE_RGB_ALPHA)))
380 png_error(png_ptr, "Unknown filter method in IHDR");
381 if(png_ptr->mode&PNG_HAVE_PNG_SIGNATURE)
382 png_warning(png_ptr, "Invalid filter method in IHDR");
383 }
384 #else
385 if(filter_type != PNG_FILTER_TYPE_BASE)
386 png_error(png_ptr, "Unknown filter method in IHDR");
387 #endif
389 /* set internal variables */
390 png_ptr->width = width;
391 png_ptr->height = height;
392 png_ptr->bit_depth = (png_byte)bit_depth;
393 png_ptr->interlaced = (png_byte)interlace_type;
394 png_ptr->color_type = (png_byte)color_type;
395 png_ptr->filter_type = (png_byte)filter_type;
397 /* find number of channels */
398 switch (png_ptr->color_type)
399 {
400 case PNG_COLOR_TYPE_GRAY:
401 case PNG_COLOR_TYPE_PALETTE:
402 png_ptr->channels = 1;
403 break;
404 case PNG_COLOR_TYPE_RGB:
405 png_ptr->channels = 3;
406 break;
407 case PNG_COLOR_TYPE_GRAY_ALPHA:
408 png_ptr->channels = 2;
409 break;
410 case PNG_COLOR_TYPE_RGB_ALPHA:
411 png_ptr->channels = 4;
412 break;
413 }
415 /* set up other useful info */
416 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
417 png_ptr->channels);
418 png_ptr->rowbytes = ((png_ptr->width *
419 (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
420 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
421 png_debug1(3,"channels = %d\n", png_ptr->channels);
422 png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
423 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
424 color_type, interlace_type, compression_type, filter_type);
425 }
427 /* read and check the palette */
428 void /* PRIVATE */
429 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
430 {
431 png_color palette[PNG_MAX_PALETTE_LENGTH];
432 int num, i;
433 #ifndef PNG_NO_POINTER_INDEXING
434 png_colorp pal_ptr;
435 #endif
437 png_debug(1, "in png_handle_PLTE\n");
439 if (!(png_ptr->mode & PNG_HAVE_IHDR))
440 png_error(png_ptr, "Missing IHDR before PLTE");
441 else if (png_ptr->mode & PNG_HAVE_IDAT)
442 {
443 png_warning(png_ptr, "Invalid PLTE after IDAT");
444 png_crc_finish(png_ptr, length);
445 return;
446 }
447 else if (png_ptr->mode & PNG_HAVE_PLTE)
448 png_error(png_ptr, "Duplicate PLTE chunk");
450 png_ptr->mode |= PNG_HAVE_PLTE;
452 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
453 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
454 {
455 png_crc_finish(png_ptr, length);
456 return;
457 }
458 #endif
460 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
461 {
462 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
463 {
464 png_warning(png_ptr, "Invalid palette chunk");
465 png_crc_finish(png_ptr, length);
466 return;
467 }
468 else
469 {
470 png_error(png_ptr, "Invalid palette chunk");
471 }
472 }
474 num = (int)length / 3;
476 #ifndef PNG_NO_POINTER_INDEXING
477 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
478 {
479 png_byte buf[3];
481 png_crc_read(png_ptr, buf, 3);
482 pal_ptr->red = buf[0];
483 pal_ptr->green = buf[1];
484 pal_ptr->blue = buf[2];
485 }
486 #else
487 for (i = 0; i < num; i++)
488 {
489 png_byte buf[3];
491 png_crc_read(png_ptr, buf, 3);
492 /* don't depend upon png_color being any order */
493 palette[i].red = buf[0];
494 palette[i].green = buf[1];
495 palette[i].blue = buf[2];
496 }
497 #endif
499 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
500 whatever the normal CRC configuration tells us. However, if we
501 have an RGB image, the PLTE can be considered ancillary, so
502 we will act as though it is. */
503 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
504 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
505 #endif
506 {
507 png_crc_finish(png_ptr, 0);
508 }
509 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
510 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
511 {
512 /* If we don't want to use the data from an ancillary chunk,
513 we have two options: an error abort, or a warning and we
514 ignore the data in this chunk (which should be OK, since
515 it's considered ancillary for a RGB or RGBA image). */
516 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
517 {
518 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
519 {
520 png_chunk_error(png_ptr, "CRC error");
521 }
522 else
523 {
524 png_chunk_warning(png_ptr, "CRC error");
525 return;
526 }
527 }
528 /* Otherwise, we (optionally) emit a warning and use the chunk. */
529 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
530 {
531 png_chunk_warning(png_ptr, "CRC error");
532 }
533 }
534 #endif
536 png_set_PLTE(png_ptr, info_ptr, palette, num);
538 #if defined(PNG_READ_tRNS_SUPPORTED)
539 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
540 {
541 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
542 {
543 if (png_ptr->num_trans > (png_uint_16)num)
544 {
545 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
546 png_ptr->num_trans = (png_uint_16)num;
547 }
548 if (info_ptr->num_trans > (png_uint_16)num)
549 {
550 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
551 info_ptr->num_trans = (png_uint_16)num;
552 }
553 }
554 }
555 #endif
557 }
559 void /* PRIVATE */
560 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
561 {
562 png_debug(1, "in png_handle_IEND\n");
564 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
565 {
566 png_error(png_ptr, "No image in file");
568 /* to quiet compiler warnings about unused info_ptr */
569 if (info_ptr == NULL)
570 return;
571 }
573 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
575 if (length != 0)
576 {
577 png_warning(png_ptr, "Incorrect IEND chunk length");
578 }
579 png_crc_finish(png_ptr, length);
580 }
582 #if defined(PNG_READ_gAMA_SUPPORTED)
583 void /* PRIVATE */
584 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
585 {
586 png_fixed_point igamma;
587 #ifdef PNG_FLOATING_POINT_SUPPORTED
588 float file_gamma;
589 #endif
590 png_byte buf[4];
592 png_debug(1, "in png_handle_gAMA\n");
594 if (!(png_ptr->mode & PNG_HAVE_IHDR))
595 png_error(png_ptr, "Missing IHDR before gAMA");
596 else if (png_ptr->mode & PNG_HAVE_IDAT)
597 {
598 png_warning(png_ptr, "Invalid gAMA after IDAT");
599 png_crc_finish(png_ptr, length);
600 return;
601 }
602 else if (png_ptr->mode & PNG_HAVE_PLTE)
603 /* Should be an error, but we can cope with it */
604 png_warning(png_ptr, "Out of place gAMA chunk");
606 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
607 #if defined(PNG_READ_sRGB_SUPPORTED)
608 && !(info_ptr->valid & PNG_INFO_sRGB)
609 #endif
610 )
611 {
612 png_warning(png_ptr, "Duplicate gAMA chunk");
613 png_crc_finish(png_ptr, length);
614 return;
615 }
617 if (length != 4)
618 {
619 png_warning(png_ptr, "Incorrect gAMA chunk length");
620 png_crc_finish(png_ptr, length);
621 return;
622 }
624 png_crc_read(png_ptr, buf, 4);
625 if (png_crc_finish(png_ptr, 0))
626 return;
628 igamma = (png_fixed_point)png_get_uint_32(buf);
629 /* check for zero gamma */
630 if (igamma == 0)
631 return;
633 #if defined(PNG_READ_sRGB_SUPPORTED)
634 if (info_ptr->valid & PNG_INFO_sRGB)
635 if(igamma < 45000L || igamma > 46000L)
636 {
637 png_warning(png_ptr,
638 "Ignoring incorrect gAMA value when sRGB is also present");
639 #ifndef PNG_NO_CONSOLE_IO
640 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
641 #endif
642 return;
643 }
644 #endif /* PNG_READ_sRGB_SUPPORTED */
646 #ifdef PNG_FLOATING_POINT_SUPPORTED
647 file_gamma = (float)igamma / (float)100000.0;
648 # ifdef PNG_READ_GAMMA_SUPPORTED
649 png_ptr->gamma = file_gamma;
650 # endif
651 png_set_gAMA(png_ptr, info_ptr, file_gamma);
652 #endif
653 #ifdef PNG_FIXED_POINT_SUPPORTED
654 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
655 #endif
656 }
657 #endif
659 #if defined(PNG_READ_sBIT_SUPPORTED)
660 void /* PRIVATE */
661 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
662 {
663 png_size_t truelen;
664 png_byte buf[4];
666 png_debug(1, "in png_handle_sBIT\n");
668 buf[0] = buf[1] = buf[2] = buf[3] = 0;
670 if (!(png_ptr->mode & PNG_HAVE_IHDR))
671 png_error(png_ptr, "Missing IHDR before sBIT");
672 else if (png_ptr->mode & PNG_HAVE_IDAT)
673 {
674 png_warning(png_ptr, "Invalid sBIT after IDAT");
675 png_crc_finish(png_ptr, length);
676 return;
677 }
678 else if (png_ptr->mode & PNG_HAVE_PLTE)
679 {
680 /* Should be an error, but we can cope with it */
681 png_warning(png_ptr, "Out of place sBIT chunk");
682 }
683 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
684 {
685 png_warning(png_ptr, "Duplicate sBIT chunk");
686 png_crc_finish(png_ptr, length);
687 return;
688 }
690 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
691 truelen = 3;
692 else
693 truelen = (png_size_t)png_ptr->channels;
695 if (length != truelen)
696 {
697 png_warning(png_ptr, "Incorrect sBIT chunk length");
698 png_crc_finish(png_ptr, length);
699 return;
700 }
702 png_crc_read(png_ptr, buf, truelen);
703 if (png_crc_finish(png_ptr, 0))
704 return;
706 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
707 {
708 png_ptr->sig_bit.red = buf[0];
709 png_ptr->sig_bit.green = buf[1];
710 png_ptr->sig_bit.blue = buf[2];
711 png_ptr->sig_bit.alpha = buf[3];
712 }
713 else
714 {
715 png_ptr->sig_bit.gray = buf[0];
716 png_ptr->sig_bit.red = buf[0];
717 png_ptr->sig_bit.green = buf[0];
718 png_ptr->sig_bit.blue = buf[0];
719 png_ptr->sig_bit.alpha = buf[1];
720 }
721 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
722 }
723 #endif
725 #if defined(PNG_READ_cHRM_SUPPORTED)
726 void /* PRIVATE */
727 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
728 {
729 png_byte buf[4];
730 #ifdef PNG_FLOATING_POINT_SUPPORTED
731 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
732 #endif
733 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
734 int_y_green, int_x_blue, int_y_blue;
736 png_debug(1, "in png_handle_cHRM\n");
738 if (!(png_ptr->mode & PNG_HAVE_IHDR))
739 png_error(png_ptr, "Missing IHDR before cHRM");
740 else if (png_ptr->mode & PNG_HAVE_IDAT)
741 {
742 png_warning(png_ptr, "Invalid cHRM after IDAT");
743 png_crc_finish(png_ptr, length);
744 return;
745 }
746 else if (png_ptr->mode & PNG_HAVE_PLTE)
747 /* Should be an error, but we can cope with it */
748 png_warning(png_ptr, "Missing PLTE before cHRM");
750 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
751 #if defined(PNG_READ_sRGB_SUPPORTED)
752 && !(info_ptr->valid & PNG_INFO_sRGB)
753 #endif
754 )
755 {
756 png_warning(png_ptr, "Duplicate cHRM chunk");
757 png_crc_finish(png_ptr, length);
758 return;
759 }
761 if (length != 32)
762 {
763 png_warning(png_ptr, "Incorrect cHRM chunk length");
764 png_crc_finish(png_ptr, length);
765 return;
766 }
768 png_crc_read(png_ptr, buf, 4);
769 int_x_white = (png_fixed_point)png_get_uint_32(buf);
771 png_crc_read(png_ptr, buf, 4);
772 int_y_white = (png_fixed_point)png_get_uint_32(buf);
774 if (int_x_white > 80000L || int_y_white > 80000L ||
775 int_x_white + int_y_white > 100000L)
776 {
777 png_warning(png_ptr, "Invalid cHRM white point");
778 png_crc_finish(png_ptr, 24);
779 return;
780 }
782 png_crc_read(png_ptr, buf, 4);
783 int_x_red = (png_fixed_point)png_get_uint_32(buf);
785 png_crc_read(png_ptr, buf, 4);
786 int_y_red = (png_fixed_point)png_get_uint_32(buf);
788 if (int_x_red > 80000L || int_y_red > 80000L ||
789 int_x_red + int_y_red > 100000L)
790 {
791 png_warning(png_ptr, "Invalid cHRM red point");
792 png_crc_finish(png_ptr, 16);
793 return;
794 }
796 png_crc_read(png_ptr, buf, 4);
797 int_x_green = (png_fixed_point)png_get_uint_32(buf);
799 png_crc_read(png_ptr, buf, 4);
800 int_y_green = (png_fixed_point)png_get_uint_32(buf);
802 if (int_x_green > 80000L || int_y_green > 80000L ||
803 int_x_green + int_y_green > 100000L)
804 {
805 png_warning(png_ptr, "Invalid cHRM green point");
806 png_crc_finish(png_ptr, 8);
807 return;
808 }
810 png_crc_read(png_ptr, buf, 4);
811 int_x_blue = (png_fixed_point)png_get_uint_32(buf);
813 png_crc_read(png_ptr, buf, 4);
814 int_y_blue = (png_fixed_point)png_get_uint_32(buf);
816 if (int_x_blue > 80000L || int_y_blue > 80000L ||
817 int_x_blue + int_y_blue > 100000L)
818 {
819 png_warning(png_ptr, "Invalid cHRM blue point");
820 png_crc_finish(png_ptr, 0);
821 return;
822 }
823 #ifdef PNG_FLOATING_POINT_SUPPORTED
824 white_x = (float)int_x_white / (float)100000.0;
825 white_y = (float)int_y_white / (float)100000.0;
826 red_x = (float)int_x_red / (float)100000.0;
827 red_y = (float)int_y_red / (float)100000.0;
828 green_x = (float)int_x_green / (float)100000.0;
829 green_y = (float)int_y_green / (float)100000.0;
830 blue_x = (float)int_x_blue / (float)100000.0;
831 blue_y = (float)int_y_blue / (float)100000.0;
832 #endif
834 #if defined(PNG_READ_sRGB_SUPPORTED)
835 if (info_ptr->valid & PNG_INFO_sRGB)
836 {
837 if (abs(int_x_white - 31270L) > 1000 ||
838 abs(int_y_white - 32900L) > 1000 ||
839 abs( int_x_red - 64000L) > 1000 ||
840 abs( int_y_red - 33000L) > 1000 ||
841 abs(int_x_green - 30000L) > 1000 ||
842 abs(int_y_green - 60000L) > 1000 ||
843 abs( int_x_blue - 15000L) > 1000 ||
844 abs( int_y_blue - 6000L) > 1000)
845 {
847 png_warning(png_ptr,
848 "Ignoring incorrect cHRM value when sRGB is also present");
849 #ifndef PNG_NO_CONSOLE_IO
850 #ifdef PNG_FLOATING_POINT_SUPPORTED
851 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
852 white_x, white_y, red_x, red_y);
853 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
854 green_x, green_y, blue_x, blue_y);
855 #else
856 fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
857 int_x_white, int_y_white, int_x_red, int_y_red);
858 fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
859 int_x_green, int_y_green, int_x_blue, int_y_blue);
860 #endif
861 #endif /* PNG_NO_CONSOLE_IO */
862 }
863 png_crc_finish(png_ptr, 0);
864 return;
865 }
866 #endif /* PNG_READ_sRGB_SUPPORTED */
868 #ifdef PNG_FLOATING_POINT_SUPPORTED
869 png_set_cHRM(png_ptr, info_ptr,
870 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
871 #endif
872 #ifdef PNG_FIXED_POINT_SUPPORTED
873 png_set_cHRM_fixed(png_ptr, info_ptr,
874 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
875 int_y_green, int_x_blue, int_y_blue);
876 #endif
877 if (png_crc_finish(png_ptr, 0))
878 return;
879 }
880 #endif
882 #if defined(PNG_READ_sRGB_SUPPORTED)
883 void /* PRIVATE */
884 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
885 {
886 int intent;
887 png_byte buf[1];
889 png_debug(1, "in png_handle_sRGB\n");
891 if (!(png_ptr->mode & PNG_HAVE_IHDR))
892 png_error(png_ptr, "Missing IHDR before sRGB");
893 else if (png_ptr->mode & PNG_HAVE_IDAT)
894 {
895 png_warning(png_ptr, "Invalid sRGB after IDAT");
896 png_crc_finish(png_ptr, length);
897 return;
898 }
899 else if (png_ptr->mode & PNG_HAVE_PLTE)
900 /* Should be an error, but we can cope with it */
901 png_warning(png_ptr, "Out of place sRGB chunk");
903 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
904 {
905 png_warning(png_ptr, "Duplicate sRGB chunk");
906 png_crc_finish(png_ptr, length);
907 return;
908 }
910 if (length != 1)
911 {
912 png_warning(png_ptr, "Incorrect sRGB chunk length");
913 png_crc_finish(png_ptr, length);
914 return;
915 }
917 png_crc_read(png_ptr, buf, 1);
918 if (png_crc_finish(png_ptr, 0))
919 return;
921 intent = buf[0];
922 /* check for bad intent */
923 if (intent >= PNG_sRGB_INTENT_LAST)
924 {
925 png_warning(png_ptr, "Unknown sRGB intent");
926 return;
927 }
929 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
930 if ((info_ptr->valid & PNG_INFO_gAMA))
931 {
932 int igamma;
933 #ifdef PNG_FIXED_POINT_SUPPORTED
934 igamma=(int)info_ptr->int_gamma;
935 #else
936 # ifdef PNG_FLOATING_POINT_SUPPORTED
937 igamma=(int)(info_ptr->gamma * 100000.);
938 # endif
939 #endif
940 #if 0 && defined(PNG_cHRM_SUPPORTED) && !defined(PNG_FIXED_POINT_SUPPORTED)
941 /* We need to define these here because they aren't in png.h */
942 png_fixed_point int_x_white;
943 png_fixed_point int_y_white;
944 png_fixed_point int_x_red;
945 png_fixed_point int_y_red;
946 png_fixed_point int_x_green;
947 png_fixed_point int_y_green;
948 png_fixed_point int_x_blue;
949 png_fixed_point int_y_blue;
950 #endif
951 if(igamma < 45000L || igamma > 46000L)
952 {
953 png_warning(png_ptr,
954 "Ignoring incorrect gAMA value when sRGB is also present");
955 #ifndef PNG_NO_CONSOLE_IO
956 # ifdef PNG_FIXED_POINT_SUPPORTED
957 fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
958 # else
959 # ifdef PNG_FLOATING_POINT_SUPPORTED
960 fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
961 # endif
962 # endif
963 #endif
964 }
965 }
966 #endif /* PNG_READ_gAMA_SUPPORTED */
968 #ifdef PNG_READ_cHRM_SUPPORTED
969 #ifdef PNG_FIXED_POINT_SUPPORTED
970 if (info_ptr->valid & PNG_INFO_cHRM)
971 if (abs(info_ptr->int_x_white - 31270L) > 1000 ||
972 abs(info_ptr->int_y_white - 32900L) > 1000 ||
973 abs( info_ptr->int_x_red - 64000L) > 1000 ||
974 abs( info_ptr->int_y_red - 33000L) > 1000 ||
975 abs(info_ptr->int_x_green - 30000L) > 1000 ||
976 abs(info_ptr->int_y_green - 60000L) > 1000 ||
977 abs( info_ptr->int_x_blue - 15000L) > 1000 ||
978 abs( info_ptr->int_y_blue - 6000L) > 1000)
979 {
980 png_warning(png_ptr,
981 "Ignoring incorrect cHRM value when sRGB is also present");
982 }
983 #endif /* PNG_FIXED_POINT_SUPPORTED */
984 #endif /* PNG_READ_cHRM_SUPPORTED */
986 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
987 }
988 #endif /* PNG_READ_sRGB_SUPPORTED */
990 #if defined(PNG_READ_iCCP_SUPPORTED)
991 void /* PRIVATE */
992 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
993 /* Note: this does not properly handle chunks that are > 64K under DOS */
994 {
995 png_charp chunkdata;
996 png_byte compression_type;
997 png_charp profile;
998 png_uint_32 skip = 0;
999 png_uint_32 profile_size = 0;
1000 png_uint_32 profile_length = 0;
1001 png_size_t slength, prefix_length, data_length;
1003 png_debug(1, "in png_handle_iCCP\n");
1005 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1006 png_error(png_ptr, "Missing IHDR before iCCP");
1007 else if (png_ptr->mode & PNG_HAVE_IDAT)
1008 {
1009 png_warning(png_ptr, "Invalid iCCP after IDAT");
1010 png_crc_finish(png_ptr, length);
1011 return;
1012 }
1013 else if (png_ptr->mode & PNG_HAVE_PLTE)
1014 /* Should be an error, but we can cope with it */
1015 png_warning(png_ptr, "Out of place iCCP chunk");
1017 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1018 {
1019 png_warning(png_ptr, "Duplicate iCCP chunk");
1020 png_crc_finish(png_ptr, length);
1021 return;
1022 }
1024 #ifdef PNG_MAX_MALLOC_64K
1025 if (length > (png_uint_32)65535L)
1026 {
1027 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1028 skip = length - (png_uint_32)65535L;
1029 length = (png_uint_32)65535L;
1030 }
1031 #endif
1033 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1034 slength = (png_size_t)length;
1035 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1037 if (png_crc_finish(png_ptr, skip))
1038 {
1039 png_free(png_ptr, chunkdata);
1040 return;
1041 }
1043 chunkdata[slength] = 0x00;
1045 for (profile = chunkdata; *profile; profile++)
1046 /* empty loop to find end of name */ ;
1048 ++profile;
1050 /* there should be at least one zero (the compression type byte)
1051 following the separator, and we should be on it */
1052 if ( profile >= chunkdata + slength)
1053 {
1054 png_free(png_ptr, chunkdata);
1055 png_warning(png_ptr, "Malformed iCCP chunk");
1056 return;
1057 }
1059 /* compression_type should always be zero */
1060 compression_type = *profile++;
1061 if (compression_type)
1062 {
1063 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1064 compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1065 wrote nonzero) */
1066 }
1068 prefix_length = profile - chunkdata;
1069 chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
1070 slength, prefix_length, &data_length);
1072 profile_length = data_length - prefix_length;
1074 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1075 profile_size = ((*(chunkdata+prefix_length))<<24) |
1076 ((*(chunkdata+prefix_length+1))<<16) |
1077 ((*(chunkdata+prefix_length+2))<< 8) |
1078 ((*(chunkdata+prefix_length+3)) );
1080 if(profile_size < profile_length)
1081 profile_length = profile_size;
1083 if(profile_size > profile_length)
1084 {
1085 png_warning(png_ptr, "Ignoring truncated iCCP profile.\n");
1086 return;
1087 }
1089 png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
1090 chunkdata + prefix_length, profile_length);
1091 png_free(png_ptr, chunkdata);
1092 }
1093 #endif /* PNG_READ_iCCP_SUPPORTED */
1095 #if defined(PNG_READ_sPLT_SUPPORTED)
1096 void /* PRIVATE */
1097 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1098 /* Note: this does not properly handle chunks that are > 64K under DOS */
1099 {
1100 png_bytep chunkdata;
1101 png_bytep entry_start;
1102 png_sPLT_t new_palette;
1103 #ifdef PNG_NO_POINTER_INDEXING
1104 png_sPLT_entryp pp;
1105 #endif
1106 int data_length, entry_size, i;
1107 png_uint_32 skip = 0;
1108 png_size_t slength;
1110 png_debug(1, "in png_handle_sPLT\n");
1112 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1113 png_error(png_ptr, "Missing IHDR before sPLT");
1114 else if (png_ptr->mode & PNG_HAVE_IDAT)
1115 {
1116 png_warning(png_ptr, "Invalid sPLT after IDAT");
1117 png_crc_finish(png_ptr, length);
1118 return;
1119 }
1121 #ifdef PNG_MAX_MALLOC_64K
1122 if (length > (png_uint_32)65535L)
1123 {
1124 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1125 skip = length - (png_uint_32)65535L;
1126 length = (png_uint_32)65535L;
1127 }
1128 #endif
1130 chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
1131 slength = (png_size_t)length;
1132 png_crc_read(png_ptr, chunkdata, slength);
1134 if (png_crc_finish(png_ptr, skip))
1135 {
1136 png_free(png_ptr, chunkdata);
1137 return;
1138 }
1140 chunkdata[slength] = 0x00;
1142 for (entry_start = chunkdata; *entry_start; entry_start++)
1143 /* empty loop to find end of name */ ;
1144 ++entry_start;
1146 /* a sample depth should follow the separator, and we should be on it */
1147 if (entry_start > chunkdata + slength)
1148 {
1149 png_free(png_ptr, chunkdata);
1150 png_warning(png_ptr, "malformed sPLT chunk");
1151 return;
1152 }
1154 new_palette.depth = *entry_start++;
1155 entry_size = (new_palette.depth == 8 ? 6 : 10);
1156 data_length = (slength - (entry_start - chunkdata));
1158 /* integrity-check the data length */
1159 if (data_length % entry_size)
1160 {
1161 png_free(png_ptr, chunkdata);
1162 png_error(png_ptr, "sPLT chunk has bad length");
1163 }
1165 new_palette.nentries = data_length / entry_size;
1166 new_palette.entries = (png_sPLT_entryp)png_malloc(
1167 png_ptr, new_palette.nentries * sizeof(png_sPLT_entry));
1169 #ifndef PNG_NO_POINTER_INDEXING
1170 for (i = 0; i < new_palette.nentries; i++)
1171 {
1172 png_sPLT_entryp pp = new_palette.entries + i;
1174 if (new_palette.depth == 8)
1175 {
1176 pp->red = *entry_start++;
1177 pp->green = *entry_start++;
1178 pp->blue = *entry_start++;
1179 pp->alpha = *entry_start++;
1180 }
1181 else
1182 {
1183 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1184 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1185 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1186 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1187 }
1188 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1189 }
1190 #else
1191 pp = new_palette.entries;
1192 for (i = 0; i < new_palette.nentries; i++)
1193 {
1195 if (new_palette.depth == 8)
1196 {
1197 pp[i].red = *entry_start++;
1198 pp[i].green = *entry_start++;
1199 pp[i].blue = *entry_start++;
1200 pp[i].alpha = *entry_start++;
1201 }
1202 else
1203 {
1204 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1205 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1206 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1207 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1208 }
1209 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1210 }
1211 #endif
1213 /* discard all chunk data except the name and stash that */
1214 new_palette.name = (png_charp)chunkdata;
1216 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1218 png_free(png_ptr, chunkdata);
1219 png_free(png_ptr, new_palette.entries);
1220 }
1221 #endif /* PNG_READ_sPLT_SUPPORTED */
1223 #if defined(PNG_READ_tRNS_SUPPORTED)
1224 void /* PRIVATE */
1225 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1226 {
1227 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1229 png_debug(1, "in png_handle_tRNS\n");
1231 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1232 png_error(png_ptr, "Missing IHDR before tRNS");
1233 else if (png_ptr->mode & PNG_HAVE_IDAT)
1234 {
1235 png_warning(png_ptr, "Invalid tRNS after IDAT");
1236 png_crc_finish(png_ptr, length);
1237 return;
1238 }
1239 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1240 {
1241 png_warning(png_ptr, "Duplicate tRNS chunk");
1242 png_crc_finish(png_ptr, length);
1243 return;
1244 }
1246 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1247 {
1248 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1249 {
1250 /* Should be an error, but we can cope with it */
1251 png_warning(png_ptr, "Missing PLTE before tRNS");
1252 }
1253 else if (length > (png_uint_32)png_ptr->num_palette)
1254 {
1255 png_warning(png_ptr, "Incorrect tRNS chunk length");
1256 png_crc_finish(png_ptr, length);
1257 return;
1258 }
1259 if (length == 0)
1260 {
1261 png_warning(png_ptr, "Zero length tRNS chunk");
1262 png_crc_finish(png_ptr, length);
1263 return;
1264 }
1266 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1267 png_ptr->num_trans = (png_uint_16)length;
1268 }
1269 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1270 {
1271 png_byte buf[6];
1273 if (length != 6)
1274 {
1275 png_warning(png_ptr, "Incorrect tRNS chunk length");
1276 png_crc_finish(png_ptr, length);
1277 return;
1278 }
1280 png_crc_read(png_ptr, buf, (png_size_t)length);
1281 png_ptr->num_trans = 1;
1282 png_ptr->trans_values.red = png_get_uint_16(buf);
1283 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1284 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1285 }
1286 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1287 {
1288 png_byte buf[6];
1290 if (length != 2)
1291 {
1292 png_warning(png_ptr, "Incorrect tRNS chunk length");
1293 png_crc_finish(png_ptr, length);
1294 return;
1295 }
1297 png_crc_read(png_ptr, buf, 2);
1298 png_ptr->num_trans = 1;
1299 png_ptr->trans_values.gray = png_get_uint_16(buf);
1300 }
1301 else
1302 {
1303 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1304 png_crc_finish(png_ptr, length);
1305 return;
1306 }
1308 if (png_crc_finish(png_ptr, 0))
1309 return;
1311 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1312 &(png_ptr->trans_values));
1313 }
1314 #endif
1316 #if defined(PNG_READ_bKGD_SUPPORTED)
1317 void /* PRIVATE */
1318 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1319 {
1320 png_size_t truelen;
1321 png_byte buf[6];
1323 png_debug(1, "in png_handle_bKGD\n");
1325 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1326 png_error(png_ptr, "Missing IHDR before bKGD");
1327 else if (png_ptr->mode & PNG_HAVE_IDAT)
1328 {
1329 png_warning(png_ptr, "Invalid bKGD after IDAT");
1330 png_crc_finish(png_ptr, length);
1331 return;
1332 }
1333 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1334 !(png_ptr->mode & PNG_HAVE_PLTE))
1335 {
1336 png_warning(png_ptr, "Missing PLTE before bKGD");
1337 png_crc_finish(png_ptr, length);
1338 return;
1339 }
1340 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1341 {
1342 png_warning(png_ptr, "Duplicate bKGD chunk");
1343 png_crc_finish(png_ptr, length);
1344 return;
1345 }
1347 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1348 truelen = 1;
1349 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1350 truelen = 6;
1351 else
1352 truelen = 2;
1354 if (length != truelen)
1355 {
1356 png_warning(png_ptr, "Incorrect bKGD chunk length");
1357 png_crc_finish(png_ptr, length);
1358 return;
1359 }
1361 png_crc_read(png_ptr, buf, truelen);
1362 if (png_crc_finish(png_ptr, 0))
1363 return;
1365 /* We convert the index value into RGB components so that we can allow
1366 * arbitrary RGB values for background when we have transparency, and
1367 * so it is easy to determine the RGB values of the background color
1368 * from the info_ptr struct. */
1369 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1370 {
1371 png_ptr->background.index = buf[0];
1372 if(info_ptr->num_palette)
1373 {
1374 if(buf[0] > info_ptr->num_palette)
1375 {
1376 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1377 return;
1378 }
1379 png_ptr->background.red =
1380 (png_uint_16)png_ptr->palette[buf[0]].red;
1381 png_ptr->background.green =
1382 (png_uint_16)png_ptr->palette[buf[0]].green;
1383 png_ptr->background.blue =
1384 (png_uint_16)png_ptr->palette[buf[0]].blue;
1385 }
1386 }
1387 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1388 {
1389 png_ptr->background.red =
1390 png_ptr->background.green =
1391 png_ptr->background.blue =
1392 png_ptr->background.gray = png_get_uint_16(buf);
1393 }
1394 else
1395 {
1396 png_ptr->background.red = png_get_uint_16(buf);
1397 png_ptr->background.green = png_get_uint_16(buf + 2);
1398 png_ptr->background.blue = png_get_uint_16(buf + 4);
1399 }
1401 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1402 }
1403 #endif
1405 #if defined(PNG_READ_hIST_SUPPORTED)
1406 void /* PRIVATE */
1407 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1408 {
1409 int num, i;
1410 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1412 png_debug(1, "in png_handle_hIST\n");
1414 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1415 png_error(png_ptr, "Missing IHDR before hIST");
1416 else if (png_ptr->mode & PNG_HAVE_IDAT)
1417 {
1418 png_warning(png_ptr, "Invalid hIST after IDAT");
1419 png_crc_finish(png_ptr, length);
1420 return;
1421 }
1422 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1423 {
1424 png_warning(png_ptr, "Missing PLTE before hIST");
1425 png_crc_finish(png_ptr, length);
1426 return;
1427 }
1428 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1429 {
1430 png_warning(png_ptr, "Duplicate hIST chunk");
1431 png_crc_finish(png_ptr, length);
1432 return;
1433 }
1435 num = (int)length / 2 ;
1436 if (num != png_ptr->num_palette)
1437 {
1438 png_warning(png_ptr, "Incorrect hIST chunk length");
1439 png_crc_finish(png_ptr, length);
1440 return;
1441 }
1443 for (i = 0; i < num; i++)
1444 {
1445 png_byte buf[2];
1447 png_crc_read(png_ptr, buf, 2);
1448 readbuf[i] = png_get_uint_16(buf);
1449 }
1451 if (png_crc_finish(png_ptr, 0))
1452 return;
1454 png_set_hIST(png_ptr, info_ptr, readbuf);
1455 }
1456 #endif
1458 #if defined(PNG_READ_pHYs_SUPPORTED)
1459 void /* PRIVATE */
1460 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1461 {
1462 png_byte buf[9];
1463 png_uint_32 res_x, res_y;
1464 int unit_type;
1466 png_debug(1, "in png_handle_pHYs\n");
1468 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1469 png_error(png_ptr, "Missing IHDR before pHYs");
1470 else if (png_ptr->mode & PNG_HAVE_IDAT)
1471 {
1472 png_warning(png_ptr, "Invalid pHYs after IDAT");
1473 png_crc_finish(png_ptr, length);
1474 return;
1475 }
1476 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1477 {
1478 png_warning(png_ptr, "Duplicate pHYs chunk");
1479 png_crc_finish(png_ptr, length);
1480 return;
1481 }
1483 if (length != 9)
1484 {
1485 png_warning(png_ptr, "Incorrect pHYs chunk length");
1486 png_crc_finish(png_ptr, length);
1487 return;
1488 }
1490 png_crc_read(png_ptr, buf, 9);
1491 if (png_crc_finish(png_ptr, 0))
1492 return;
1494 res_x = png_get_uint_32(buf);
1495 res_y = png_get_uint_32(buf + 4);
1496 unit_type = buf[8];
1497 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1498 }
1499 #endif
1501 #if defined(PNG_READ_oFFs_SUPPORTED)
1502 void /* PRIVATE */
1503 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1504 {
1505 png_byte buf[9];
1506 png_int_32 offset_x, offset_y;
1507 int unit_type;
1509 png_debug(1, "in png_handle_oFFs\n");
1511 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1512 png_error(png_ptr, "Missing IHDR before oFFs");
1513 else if (png_ptr->mode & PNG_HAVE_IDAT)
1514 {
1515 png_warning(png_ptr, "Invalid oFFs after IDAT");
1516 png_crc_finish(png_ptr, length);
1517 return;
1518 }
1519 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1520 {
1521 png_warning(png_ptr, "Duplicate oFFs chunk");
1522 png_crc_finish(png_ptr, length);
1523 return;
1524 }
1526 if (length != 9)
1527 {
1528 png_warning(png_ptr, "Incorrect oFFs chunk length");
1529 png_crc_finish(png_ptr, length);
1530 return;
1531 }
1533 png_crc_read(png_ptr, buf, 9);
1534 if (png_crc_finish(png_ptr, 0))
1535 return;
1537 offset_x = png_get_int_32(buf);
1538 offset_y = png_get_int_32(buf + 4);
1539 unit_type = buf[8];
1540 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1541 }
1542 #endif
1544 #if defined(PNG_READ_pCAL_SUPPORTED)
1545 /* read the pCAL chunk (described in the PNG Extensions document) */
1546 void /* PRIVATE */
1547 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1548 {
1549 png_charp purpose;
1550 png_int_32 X0, X1;
1551 png_byte type, nparams;
1552 png_charp buf, units, endptr;
1553 png_charpp params;
1554 png_size_t slength;
1555 int i;
1557 png_debug(1, "in png_handle_pCAL\n");
1559 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1560 png_error(png_ptr, "Missing IHDR before pCAL");
1561 else if (png_ptr->mode & PNG_HAVE_IDAT)
1562 {
1563 png_warning(png_ptr, "Invalid pCAL after IDAT");
1564 png_crc_finish(png_ptr, length);
1565 return;
1566 }
1567 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1568 {
1569 png_warning(png_ptr, "Duplicate pCAL chunk");
1570 png_crc_finish(png_ptr, length);
1571 return;
1572 }
1574 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
1575 length + 1);
1576 purpose = (png_charp)png_malloc(png_ptr, length + 1);
1577 slength = (png_size_t)length;
1578 png_crc_read(png_ptr, (png_bytep)purpose, slength);
1580 if (png_crc_finish(png_ptr, 0))
1581 {
1582 png_free(png_ptr, purpose);
1583 return;
1584 }
1586 purpose[slength] = 0x00; /* null terminate the last string */
1588 png_debug(3, "Finding end of pCAL purpose string\n");
1589 for (buf = purpose; *buf; buf++)
1590 /* empty loop */ ;
1592 endptr = purpose + slength;
1594 /* We need to have at least 12 bytes after the purpose string
1595 in order to get the parameter information. */
1596 if (endptr <= buf + 12)
1597 {
1598 png_warning(png_ptr, "Invalid pCAL data");
1599 png_free(png_ptr, purpose);
1600 return;
1601 }
1603 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1604 X0 = png_get_int_32((png_bytep)buf+1);
1605 X1 = png_get_int_32((png_bytep)buf+5);
1606 type = buf[9];
1607 nparams = buf[10];
1608 units = buf + 11;
1610 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1611 /* Check that we have the right number of parameters for known
1612 equation types. */
1613 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1614 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1615 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1616 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1617 {
1618 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1619 png_free(png_ptr, purpose);
1620 return;
1621 }
1622 else if (type >= PNG_EQUATION_LAST)
1623 {
1624 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1625 }
1627 for (buf = units; *buf; buf++)
1628 /* Empty loop to move past the units string. */ ;
1630 png_debug(3, "Allocating pCAL parameters array\n");
1631 params = (png_charpp)png_malloc(png_ptr, (png_uint_32)(nparams
1632 *sizeof(png_charp))) ;
1634 /* Get pointers to the start of each parameter string. */
1635 for (i = 0; i < (int)nparams; i++)
1636 {
1637 buf++; /* Skip the null string terminator from previous parameter. */
1639 png_debug1(3, "Reading pCAL parameter %d\n", i);
1640 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
1641 /* Empty loop to move past each parameter string */ ;
1643 /* Make sure we haven't run out of data yet */
1644 if (buf > endptr)
1645 {
1646 png_warning(png_ptr, "Invalid pCAL data");
1647 png_free(png_ptr, purpose);
1648 png_free(png_ptr, params);
1649 return;
1650 }
1651 }
1653 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1654 units, params);
1656 png_free(png_ptr, purpose);
1657 png_free(png_ptr, params);
1658 }
1659 #endif
1661 #if defined(PNG_READ_sCAL_SUPPORTED)
1662 /* read the sCAL chunk */
1663 void /* PRIVATE */
1664 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1665 {
1666 png_charp buffer, ep;
1667 #ifdef PNG_FLOATING_POINT_SUPPORTED
1668 double width, height;
1669 png_charp vp;
1670 #else
1671 #ifdef PNG_FIXED_POINT_SUPPORTED
1672 png_charp swidth, sheight;
1673 #endif
1674 #endif
1675 png_size_t slength;
1677 png_debug(1, "in png_handle_sCAL\n");
1679 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1680 png_error(png_ptr, "Missing IHDR before sCAL");
1681 else if (png_ptr->mode & PNG_HAVE_IDAT)
1682 {
1683 png_warning(png_ptr, "Invalid sCAL after IDAT");
1684 png_crc_finish(png_ptr, length);
1685 return;
1686 }
1687 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1688 {
1689 png_warning(png_ptr, "Duplicate sCAL chunk");
1690 png_crc_finish(png_ptr, length);
1691 return;
1692 }
1694 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1695 length + 1);
1696 buffer = (png_charp)png_malloc(png_ptr, length + 1);
1697 slength = (png_size_t)length;
1698 png_crc_read(png_ptr, (png_bytep)buffer, slength);
1700 if (png_crc_finish(png_ptr, 0))
1701 {
1702 png_free(png_ptr, buffer);
1703 return;
1704 }
1706 buffer[slength] = 0x00; /* null terminate the last string */
1708 ep = buffer + 1; /* skip unit byte */
1710 #ifdef PNG_FLOATING_POINT_SUPPORTED
1711 width = strtod(ep, &vp);
1712 if (*vp)
1713 {
1714 png_warning(png_ptr, "malformed width string in sCAL chunk");
1715 return;
1716 }
1717 #else
1718 #ifdef PNG_FIXED_POINT_SUPPORTED
1719 swidth = (png_charp)png_malloc(png_ptr, strlen(ep) + 1);
1720 png_memcpy(swidth, ep, (png_size_t)strlen(ep));
1721 #endif
1722 #endif
1724 for (ep = buffer; *ep; ep++)
1725 /* empty loop */ ;
1726 ep++;
1728 #ifdef PNG_FLOATING_POINT_SUPPORTED
1729 height = strtod(ep, &vp);
1730 if (*vp)
1731 {
1732 png_warning(png_ptr, "malformed height string in sCAL chunk");
1733 return;
1734 }
1735 #else
1736 #ifdef PNG_FIXED_POINT_SUPPORTED
1737 sheight = (png_charp)png_malloc(png_ptr, strlen(ep) + 1);
1738 png_memcpy(sheight, ep, (png_size_t)strlen(ep));
1739 #endif
1740 #endif
1742 if (buffer + slength < ep
1743 #ifdef PNG_FLOATING_POINT_SUPPORTED
1744 || width <= 0. || height <= 0.
1745 #endif
1746 )
1747 {
1748 png_warning(png_ptr, "Invalid sCAL data");
1749 png_free(png_ptr, buffer);
1750 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1751 png_free(png_ptr, swidth);
1752 png_free(png_ptr, sheight);
1753 #endif
1754 return;
1755 }
1758 #ifdef PNG_FLOATING_POINT_SUPPORTED
1759 png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1760 #else
1761 #ifdef PNG_FIXED_POINT_SUPPORTED
1762 png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1763 #endif
1764 #endif
1766 png_free(png_ptr, buffer);
1767 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1768 png_free(png_ptr, swidth);
1769 png_free(png_ptr, sheight);
1770 #endif
1771 }
1772 #endif
1774 #if defined(PNG_READ_tIME_SUPPORTED)
1775 void /* PRIVATE */
1776 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1777 {
1778 png_byte buf[7];
1779 png_time mod_time;
1781 png_debug(1, "in png_handle_tIME\n");
1783 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1784 png_error(png_ptr, "Out of place tIME chunk");
1785 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1786 {
1787 png_warning(png_ptr, "Duplicate tIME chunk");
1788 png_crc_finish(png_ptr, length);
1789 return;
1790 }
1792 if (png_ptr->mode & PNG_HAVE_IDAT)
1793 png_ptr->mode |= PNG_AFTER_IDAT;
1795 if (length != 7)
1796 {
1797 png_warning(png_ptr, "Incorrect tIME chunk length");
1798 png_crc_finish(png_ptr, length);
1799 return;
1800 }
1802 png_crc_read(png_ptr, buf, 7);
1803 if (png_crc_finish(png_ptr, 0))
1804 return;
1806 mod_time.second = buf[6];
1807 mod_time.minute = buf[5];
1808 mod_time.hour = buf[4];
1809 mod_time.day = buf[3];
1810 mod_time.month = buf[2];
1811 mod_time.year = png_get_uint_16(buf);
1813 png_set_tIME(png_ptr, info_ptr, &mod_time);
1814 }
1815 #endif
1817 #if defined(PNG_READ_tEXt_SUPPORTED)
1818 /* Note: this does not properly handle chunks that are > 64K under DOS */
1819 void /* PRIVATE */
1820 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1821 {
1822 png_textp text_ptr;
1823 png_charp key;
1824 png_charp text;
1825 png_uint_32 skip = 0;
1826 png_size_t slength;
1828 png_debug(1, "in png_handle_tEXt\n");
1830 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1831 png_error(png_ptr, "Missing IHDR before tEXt");
1833 if (png_ptr->mode & PNG_HAVE_IDAT)
1834 png_ptr->mode |= PNG_AFTER_IDAT;
1836 #ifdef PNG_MAX_MALLOC_64K
1837 if (length > (png_uint_32)65535L)
1838 {
1839 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1840 skip = length - (png_uint_32)65535L;
1841 length = (png_uint_32)65535L;
1842 }
1843 #endif
1845 key = (png_charp)png_malloc(png_ptr, length + 1);
1846 slength = (png_size_t)length;
1847 png_crc_read(png_ptr, (png_bytep)key, slength);
1849 if (png_crc_finish(png_ptr, skip))
1850 {
1851 png_free(png_ptr, key);
1852 return;
1853 }
1855 key[slength] = 0x00;
1857 for (text = key; *text; text++)
1858 /* empty loop to find end of key */ ;
1860 if (text != key + slength)
1861 text++;
1863 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1864 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1865 text_ptr->key = key;
1866 #ifdef PNG_iTXt_SUPPORTED
1867 text_ptr->lang = NULL;
1868 text_ptr->lang_key = NULL;
1869 text_ptr->itxt_length = 0;
1870 #endif
1871 text_ptr->text = text;
1872 text_ptr->text_length = png_strlen(text);
1874 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1876 png_free(png_ptr, key);
1877 png_free(png_ptr, text_ptr);
1878 }
1879 #endif
1881 #if defined(PNG_READ_zTXt_SUPPORTED)
1882 /* note: this does not correctly handle chunks that are > 64K under DOS */
1883 void /* PRIVATE */
1884 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1885 {
1886 png_textp text_ptr;
1887 png_charp chunkdata;
1888 png_charp text;
1889 int comp_type;
1890 png_size_t slength, prefix_len, data_len;
1892 png_debug(1, "in png_handle_zTXt\n");
1893 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1894 png_error(png_ptr, "Missing IHDR before zTXt");
1896 if (png_ptr->mode & PNG_HAVE_IDAT)
1897 png_ptr->mode |= PNG_AFTER_IDAT;
1899 #ifdef PNG_MAX_MALLOC_64K
1900 /* We will no doubt have problems with chunks even half this size, but
1901 there is no hard and fast rule to tell us where to stop. */
1902 if (length > (png_uint_32)65535L)
1903 {
1904 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1905 png_crc_finish(png_ptr, length);
1906 return;
1907 }
1908 #endif
1910 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1911 slength = (png_size_t)length;
1912 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1913 if (png_crc_finish(png_ptr, 0))
1914 {
1915 png_free(png_ptr, chunkdata);
1916 return;
1917 }
1919 chunkdata[slength] = 0x00;
1921 for (text = chunkdata; *text; text++)
1922 /* empty loop */ ;
1924 /* zTXt must have some text after the chunkdataword */
1925 if (text == chunkdata + slength)
1926 {
1927 comp_type = PNG_TEXT_COMPRESSION_NONE;
1928 png_warning(png_ptr, "Zero length zTXt chunk");
1929 }
1930 else
1931 {
1932 comp_type = *(++text);
1933 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
1934 {
1935 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
1936 comp_type = PNG_TEXT_COMPRESSION_zTXt;
1937 }
1938 text++; /* skip the compression_method byte */
1939 }
1940 prefix_len = text - chunkdata;
1942 chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
1943 (png_size_t)length, prefix_len, &data_len);
1945 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1946 text_ptr->compression = comp_type;
1947 text_ptr->key = chunkdata;
1948 #ifdef PNG_iTXt_SUPPORTED
1949 text_ptr->lang = NULL;
1950 text_ptr->lang_key = NULL;
1951 text_ptr->itxt_length = 0;
1952 #endif
1953 text_ptr->text = chunkdata + prefix_len;
1954 text_ptr->text_length = data_len;
1956 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1958 png_free(png_ptr, text_ptr);
1959 png_free(png_ptr, chunkdata);
1960 }
1961 #endif
1963 #if defined(PNG_READ_iTXt_SUPPORTED)
1964 /* note: this does not correctly handle chunks that are > 64K under DOS */
1965 void /* PRIVATE */
1966 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1967 {
1968 png_textp text_ptr;
1969 png_charp chunkdata;
1970 png_charp key, lang, text, lang_key;
1971 int comp_flag;
1972 int comp_type = 0;
1973 png_size_t slength, prefix_len, data_len;
1975 png_debug(1, "in png_handle_iTXt\n");
1977 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1978 png_error(png_ptr, "Missing IHDR before iTXt");
1980 if (png_ptr->mode & PNG_HAVE_IDAT)
1981 png_ptr->mode |= PNG_AFTER_IDAT;
1983 #ifdef PNG_MAX_MALLOC_64K
1984 /* We will no doubt have problems with chunks even half this size, but
1985 there is no hard and fast rule to tell us where to stop. */
1986 if (length > (png_uint_32)65535L)
1987 {
1988 png_warning(png_ptr,"iTXt chunk too large to fit in memory");
1989 png_crc_finish(png_ptr, length);
1990 return;
1991 }
1992 #endif
1994 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1995 slength = (png_size_t)length;
1996 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1997 if (png_crc_finish(png_ptr, 0))
1998 {
1999 png_free(png_ptr, chunkdata);
2000 return;
2001 }
2003 chunkdata[slength] = 0x00;
2005 for (lang = chunkdata; *lang; lang++)
2006 /* empty loop */ ;
2007 lang++; /* skip NUL separator */
2009 /* iTXt must have a language tag (possibly empty), two compression bytes,
2010 translated keyword (possibly empty), and possibly some text after the
2011 keyword */
2013 if (lang >= chunkdata + slength)
2014 {
2015 comp_flag = PNG_TEXT_COMPRESSION_NONE;
2016 png_warning(png_ptr, "Zero length iTXt chunk");
2017 }
2018 else
2019 {
2020 comp_flag = *lang++;
2021 comp_type = *lang++;
2022 }
2024 for (lang_key = lang; *lang_key; lang_key++)
2025 /* empty loop */ ;
2026 lang_key++; /* skip NUL separator */
2028 for (text = lang_key; *text; text++)
2029 /* empty loop */ ;
2030 text++; /* skip NUL separator */
2032 prefix_len = text - chunkdata;
2034 key=chunkdata;
2035 if (comp_flag)
2036 chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
2037 (size_t)length, prefix_len, &data_len);
2038 else
2039 data_len=png_strlen(chunkdata + prefix_len);
2040 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
2041 text_ptr->compression = (int)comp_flag + 1;
2042 text_ptr->lang_key = chunkdata+(lang_key-key);
2043 text_ptr->lang = chunkdata+(lang-key);
2044 text_ptr->itxt_length = data_len;
2045 text_ptr->text_length = 0;
2046 text_ptr->key = chunkdata;
2047 text_ptr->text = chunkdata + prefix_len;
2049 png_set_text(png_ptr, info_ptr, text_ptr, 1);
2051 png_free(png_ptr, text_ptr);
2052 png_free(png_ptr, chunkdata);
2053 }
2054 #endif
2056 /* This function is called when we haven't found a handler for a
2057 chunk. If there isn't a problem with the chunk itself (ie bad
2058 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2059 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2060 case it will be saved away to be written out later. */
2061 void /* PRIVATE */
2062 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2063 {
2064 png_uint_32 skip = 0;
2066 png_debug(1, "in png_handle_unknown\n");
2068 if (png_ptr->mode & PNG_HAVE_IDAT)
2069 {
2070 #ifdef PNG_USE_LOCAL_ARRAYS
2071 PNG_IDAT;
2072 #endif
2073 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2074 png_ptr->mode |= PNG_AFTER_IDAT;
2075 }
2077 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
2079 if (!(png_ptr->chunk_name[0] & 0x20))
2080 {
2081 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2082 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2083 HANDLE_CHUNK_ALWAYS
2084 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2085 && png_ptr->read_user_chunk_fn == (png_user_chunk_ptr)NULL
2086 #endif
2087 )
2088 #endif
2089 png_chunk_error(png_ptr, "unknown critical chunk");
2090 }
2092 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2093 if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
2094 {
2095 png_unknown_chunk chunk;
2097 #ifdef PNG_MAX_MALLOC_64K
2098 if (length > (png_uint_32)65535L)
2099 {
2100 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2101 skip = length - (png_uint_32)65535L;
2102 length = (png_uint_32)65535L;
2103 }
2104 #endif
2105 strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
2106 chunk.data = (png_bytep)png_malloc(png_ptr, length);
2107 png_crc_read(png_ptr, chunk.data, length);
2108 chunk.size = length;
2109 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2110 if(png_ptr->read_user_chunk_fn != (png_user_chunk_ptr)NULL)
2111 {
2112 /* callback to user unknown chunk handler */
2113 if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
2114 {
2115 if (!(png_ptr->chunk_name[0] & 0x20))
2116 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2117 HANDLE_CHUNK_ALWAYS)
2118 png_chunk_error(png_ptr, "unknown critical chunk");
2119 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2120 }
2121 }
2122 else
2123 #endif
2124 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2125 png_free(png_ptr, chunk.data);
2126 }
2127 else
2128 #endif
2129 skip = length;
2131 png_crc_finish(png_ptr, skip);
2133 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2134 if (info_ptr == NULL)
2135 /* quiet compiler warnings about unused info_ptr */ ;
2136 #endif
2137 }
2139 /* This function is called to verify that a chunk name is valid.
2140 This function can't have the "critical chunk check" incorporated
2141 into it, since in the future we will need to be able to call user
2142 functions to handle unknown critical chunks after we check that
2143 the chunk name itself is valid. */
2145 #define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
2147 void /* PRIVATE */
2148 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2149 {
2150 png_debug(1, "in png_check_chunk_name\n");
2151 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2152 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2153 {
2154 png_chunk_error(png_ptr, "invalid chunk type");
2155 }
2156 }
2158 /* Combines the row recently read in with the existing pixels in the
2159 row. This routine takes care of alpha and transparency if requested.
2160 This routine also handles the two methods of progressive display
2161 of interlaced images, depending on the mask value.
2162 The mask value describes which pixels are to be combined with
2163 the row. The pattern always repeats every 8 pixels, so just 8
2164 bits are needed. A one indicates the pixel is to be combined,
2165 a zero indicates the pixel is to be skipped. This is in addition
2166 to any alpha or transparency value associated with the pixel. If
2167 you want all pixels to be combined, pass 0xff (255) in mask. */
2168 #ifndef PNG_HAVE_ASSEMBLER_COMBINE_ROW
2169 void /* PRIVATE */
2170 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2171 {
2172 png_debug(1,"in png_combine_row\n");
2173 if (mask == 0xff)
2174 {
2175 png_memcpy(row, png_ptr->row_buf + 1,
2176 (png_size_t)((png_ptr->width *
2177 png_ptr->row_info.pixel_depth + 7) >> 3));
2178 }
2179 else
2180 {
2181 switch (png_ptr->row_info.pixel_depth)
2182 {
2183 case 1:
2184 {
2185 png_bytep sp = png_ptr->row_buf + 1;
2186 png_bytep dp = row;
2187 int s_inc, s_start, s_end;
2188 int m = 0x80;
2189 int shift;
2190 png_uint_32 i;
2191 png_uint_32 row_width = png_ptr->width;
2193 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2194 if (png_ptr->transformations & PNG_PACKSWAP)
2195 {
2196 s_start = 0;
2197 s_end = 7;
2198 s_inc = 1;
2199 }
2200 else
2201 #endif
2202 {
2203 s_start = 7;
2204 s_end = 0;
2205 s_inc = -1;
2206 }
2208 shift = s_start;
2210 for (i = 0; i < row_width; i++)
2211 {
2212 if (m & mask)
2213 {
2214 int value;
2216 value = (*sp >> shift) & 0x01;
2217 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2218 *dp |= (png_byte)(value << shift);
2219 }
2221 if (shift == s_end)
2222 {
2223 shift = s_start;
2224 sp++;
2225 dp++;
2226 }
2227 else
2228 shift += s_inc;
2230 if (m == 1)
2231 m = 0x80;
2232 else
2233 m >>= 1;
2234 }
2235 break;
2236 }
2237 case 2:
2238 {
2239 png_bytep sp = png_ptr->row_buf + 1;
2240 png_bytep dp = row;
2241 int s_start, s_end, s_inc;
2242 int m = 0x80;
2243 int shift;
2244 png_uint_32 i;
2245 png_uint_32 row_width = png_ptr->width;
2246 int value;
2248 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2249 if (png_ptr->transformations & PNG_PACKSWAP)
2250 {
2251 s_start = 0;
2252 s_end = 6;
2253 s_inc = 2;
2254 }
2255 else
2256 #endif
2257 {
2258 s_start = 6;
2259 s_end = 0;
2260 s_inc = -2;
2261 }
2263 shift = s_start;
2265 for (i = 0; i < row_width; i++)
2266 {
2267 if (m & mask)
2268 {
2269 value = (*sp >> shift) & 0x03;
2270 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2271 *dp |= (png_byte)(value << shift);
2272 }
2274 if (shift == s_end)
2275 {
2276 shift = s_start;
2277 sp++;
2278 dp++;
2279 }
2280 else
2281 shift += s_inc;
2282 if (m == 1)
2283 m = 0x80;
2284 else
2285 m >>= 1;
2286 }
2287 break;
2288 }
2289 case 4:
2290 {
2291 png_bytep sp = png_ptr->row_buf + 1;
2292 png_bytep dp = row;
2293 int s_start, s_end, s_inc;
2294 int m = 0x80;
2295 int shift;
2296 png_uint_32 i;
2297 png_uint_32 row_width = png_ptr->width;
2298 int value;
2300 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2301 if (png_ptr->transformations & PNG_PACKSWAP)
2302 {
2303 s_start = 0;
2304 s_end = 4;
2305 s_inc = 4;
2306 }
2307 else
2308 #endif
2309 {
2310 s_start = 4;
2311 s_end = 0;
2312 s_inc = -4;
2313 }
2314 shift = s_start;
2316 for (i = 0; i < row_width; i++)
2317 {
2318 if (m & mask)
2319 {
2320 value = (*sp >> shift) & 0xf;
2321 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2322 *dp |= (png_byte)(value << shift);
2323 }
2325 if (shift == s_end)
2326 {
2327 shift = s_start;
2328 sp++;
2329 dp++;
2330 }
2331 else
2332 shift += s_inc;
2333 if (m == 1)
2334 m = 0x80;
2335 else
2336 m >>= 1;
2337 }
2338 break;
2339 }
2340 default:
2341 {
2342 png_bytep sp = png_ptr->row_buf + 1;
2343 png_bytep dp = row;
2344 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2345 png_uint_32 i;
2346 png_uint_32 row_width = png_ptr->width;
2347 png_byte m = 0x80;
2350 for (i = 0; i < row_width; i++)
2351 {
2352 if (m & mask)
2353 {
2354 png_memcpy(dp, sp, pixel_bytes);
2355 }
2357 sp += pixel_bytes;
2358 dp += pixel_bytes;
2360 if (m == 1)
2361 m = 0x80;
2362 else
2363 m >>= 1;
2364 }
2365 break;
2366 }
2367 }
2368 }
2369 }
2370 #endif /* !PNG_HAVE_ASSEMBLER_COMBINE_ROW */
2372 #ifdef PNG_READ_INTERLACING_SUPPORTED
2373 #ifndef PNG_HAVE_ASSEMBLER_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */
2374 void /* PRIVATE */
2375 png_do_read_interlace(png_structp png_ptr)
2376 {
2377 png_row_infop row_info = &(png_ptr->row_info);
2378 png_bytep row = png_ptr->row_buf + 1;
2379 int pass = png_ptr->pass;
2380 png_uint_32 transformations = png_ptr->transformations;
2381 #ifdef PNG_USE_LOCAL_ARRAYS
2382 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2383 /* offset to next interlace block */
2384 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2385 #endif
2387 png_debug(1,"in png_do_read_interlace (stock C version)\n");
2388 if (row != NULL && row_info != NULL)
2389 {
2390 png_uint_32 final_width;
2392 final_width = row_info->width * png_pass_inc[pass];
2394 switch (row_info->pixel_depth)
2395 {
2396 case 1:
2397 {
2398 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2399 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2400 int sshift, dshift;
2401 int s_start, s_end, s_inc;
2402 int jstop = png_pass_inc[pass];
2403 png_byte v;
2404 png_uint_32 i;
2405 int j;
2407 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2408 if (transformations & PNG_PACKSWAP)
2409 {
2410 sshift = (int)((row_info->width + 7) & 0x07);
2411 dshift = (int)((final_width + 7) & 0x07);
2412 s_start = 7;
2413 s_end = 0;
2414 s_inc = -1;
2415 }
2416 else
2417 #endif
2418 {
2419 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2420 dshift = 7 - (int)((final_width + 7) & 0x07);
2421 s_start = 0;
2422 s_end = 7;
2423 s_inc = 1;
2424 }
2426 for (i = 0; i < row_info->width; i++)
2427 {
2428 v = (png_byte)((*sp >> sshift) & 0x01);
2429 for (j = 0; j < jstop; j++)
2430 {
2431 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2432 *dp |= (png_byte)(v << dshift);
2433 if (dshift == s_end)
2434 {
2435 dshift = s_start;
2436 dp--;
2437 }
2438 else
2439 dshift += s_inc;
2440 }
2441 if (sshift == s_end)
2442 {
2443 sshift = s_start;
2444 sp--;
2445 }
2446 else
2447 sshift += s_inc;
2448 }
2449 break;
2450 }
2451 case 2:
2452 {
2453 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2454 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2455 int sshift, dshift;
2456 int s_start, s_end, s_inc;
2457 int jstop = png_pass_inc[pass];
2458 png_uint_32 i;
2460 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2461 if (transformations & PNG_PACKSWAP)
2462 {
2463 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2464 dshift = (int)(((final_width + 3) & 0x03) << 1);
2465 s_start = 6;
2466 s_end = 0;
2467 s_inc = -2;
2468 }
2469 else
2470 #endif
2471 {
2472 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2473 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2474 s_start = 0;
2475 s_end = 6;
2476 s_inc = 2;
2477 }
2479 for (i = 0; i < row_info->width; i++)
2480 {
2481 png_byte v;
2482 int j;
2484 v = (png_byte)((*sp >> sshift) & 0x03);
2485 for (j = 0; j < jstop; j++)
2486 {
2487 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2488 *dp |= (png_byte)(v << dshift);
2489 if (dshift == s_end)
2490 {
2491 dshift = s_start;
2492 dp--;
2493 }
2494 else
2495 dshift += s_inc;
2496 }
2497 if (sshift == s_end)
2498 {
2499 sshift = s_start;
2500 sp--;
2501 }
2502 else
2503 sshift += s_inc;
2504 }
2505 break;
2506 }
2507 case 4:
2508 {
2509 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2510 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2511 int sshift, dshift;
2512 int s_start, s_end, s_inc;
2513 png_uint_32 i;
2514 int jstop = png_pass_inc[pass];
2516 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2517 if (transformations & PNG_PACKSWAP)
2518 {
2519 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2520 dshift = (int)(((final_width + 1) & 0x01) << 2);
2521 s_start = 4;
2522 s_end = 0;
2523 s_inc = -4;
2524 }
2525 else
2526 #endif
2527 {
2528 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2529 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2530 s_start = 0;
2531 s_end = 4;
2532 s_inc = 4;
2533 }
2535 for (i = 0; i < row_info->width; i++)
2536 {
2537 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2538 int j;
2540 for (j = 0; j < jstop; j++)
2541 {
2542 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2543 *dp |= (png_byte)(v << dshift);
2544 if (dshift == s_end)
2545 {
2546 dshift = s_start;
2547 dp--;
2548 }
2549 else
2550 dshift += s_inc;
2551 }
2552 if (sshift == s_end)
2553 {
2554 sshift = s_start;
2555 sp--;
2556 }
2557 else
2558 sshift += s_inc;
2559 }
2560 break;
2561 }
2562 default:
2563 {
2564 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2565 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2566 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2568 int jstop = png_pass_inc[pass];
2569 png_uint_32 i;
2571 for (i = 0; i < row_info->width; i++)
2572 {
2573 png_byte v[8];
2574 int j;
2576 png_memcpy(v, sp, pixel_bytes);
2577 for (j = 0; j < jstop; j++)
2578 {
2579 png_memcpy(dp, v, pixel_bytes);
2580 dp -= pixel_bytes;
2581 }
2582 sp -= pixel_bytes;
2583 }
2584 break;
2585 }
2586 }
2587 row_info->width = final_width;
2588 row_info->rowbytes = ((final_width *
2589 (png_uint_32)row_info->pixel_depth + 7) >> 3);
2590 }
2591 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2592 /* silence compiler warning */
2593 if (transformations)
2594 return;
2595 #endif
2596 }
2597 #endif /* !PNG_HAVE_ASSEMBLER_READ_INTERLACE */
2598 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2600 #ifndef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
2601 void /* PRIVATE */
2602 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2603 png_bytep prev_row, int filter)
2604 {
2605 png_debug(1, "in png_read_filter_row\n");
2606 png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
2607 switch (filter)
2608 {
2609 case PNG_FILTER_VALUE_NONE:
2610 break;
2611 case PNG_FILTER_VALUE_SUB:
2612 {
2613 png_uint_32 i;
2614 png_uint_32 istop = row_info->rowbytes;
2615 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2616 png_bytep rp = row + bpp;
2617 png_bytep lp = row;
2619 for (i = bpp; i < istop; i++)
2620 {
2621 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2622 rp++;
2623 }
2624 break;
2625 }
2626 case PNG_FILTER_VALUE_UP:
2627 {
2628 png_uint_32 i;
2629 png_uint_32 istop = row_info->rowbytes;
2630 png_bytep rp = row;
2631 png_bytep pp = prev_row;
2633 for (i = 0; i < istop; i++)
2634 {
2635 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2636 rp++;
2637 }
2638 break;
2639 }
2640 case PNG_FILTER_VALUE_AVG:
2641 {
2642 png_uint_32 i;
2643 png_bytep rp = row;
2644 png_bytep pp = prev_row;
2645 png_bytep lp = row;
2646 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2647 png_uint_32 istop = row_info->rowbytes - bpp;
2649 for (i = 0; i < bpp; i++)
2650 {
2651 *rp = (png_byte)(((int)(*rp) +
2652 ((int)(*pp++) / 2 )) & 0xff);
2653 rp++;
2654 }
2656 for (i = 0; i < istop; i++)
2657 {
2658 *rp = (png_byte)(((int)(*rp) +
2659 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2660 rp++;
2661 }
2662 break;
2663 }
2664 case PNG_FILTER_VALUE_PAETH:
2665 {
2666 png_uint_32 i;
2667 png_bytep rp = row;
2668 png_bytep pp = prev_row;
2669 png_bytep lp = row;
2670 png_bytep cp = prev_row;
2671 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2672 png_uint_32 istop=row_info->rowbytes - bpp;
2674 for (i = 0; i < bpp; i++)
2675 {
2676 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2677 rp++;
2678 }
2680 for (i = 0; i < istop; i++) /* use leftover rp,pp */
2681 {
2682 int a, b, c, pa, pb, pc, p;
2684 a = *lp++;
2685 b = *pp++;
2686 c = *cp++;
2688 p = b - c;
2689 pc = a - c;
2691 #ifdef PNG_USE_ABS
2692 pa = abs(p);
2693 pb = abs(pc);
2694 pc = abs(p + pc);
2695 #else
2696 pa = p < 0 ? -p : p;
2697 pb = pc < 0 ? -pc : pc;
2698 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2699 #endif
2701 /*
2702 if (pa <= pb && pa <= pc)
2703 p = a;
2704 else if (pb <= pc)
2705 p = b;
2706 else
2707 p = c;
2708 */
2710 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2712 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2713 rp++;
2714 }
2715 break;
2716 }
2717 default:
2718 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2719 *row=0;
2720 break;
2721 }
2722 }
2723 #endif /* !PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
2725 void /* PRIVATE */
2726 png_read_finish_row(png_structp png_ptr)
2727 {
2728 #ifdef PNG_USE_LOCAL_ARRAYS
2729 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2731 /* start of interlace block */
2732 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2734 /* offset to next interlace block */
2735 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2737 /* start of interlace block in the y direction */
2738 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2740 /* offset to next interlace block in the y direction */
2741 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2742 #endif
2744 png_debug(1, "in png_read_finish_row\n");
2745 png_ptr->row_number++;
2746 if (png_ptr->row_number < png_ptr->num_rows)
2747 return;
2749 if (png_ptr->interlaced)
2750 {
2751 png_ptr->row_number = 0;
2752 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
2753 do
2754 {
2755 png_ptr->pass++;
2756 if (png_ptr->pass >= 7)
2757 break;
2758 png_ptr->iwidth = (png_ptr->width +
2759 png_pass_inc[png_ptr->pass] - 1 -
2760 png_pass_start[png_ptr->pass]) /
2761 png_pass_inc[png_ptr->pass];
2762 png_ptr->irowbytes = ((png_ptr->iwidth *
2763 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2765 if (!(png_ptr->transformations & PNG_INTERLACE))
2766 {
2767 png_ptr->num_rows = (png_ptr->height +
2768 png_pass_yinc[png_ptr->pass] - 1 -
2769 png_pass_ystart[png_ptr->pass]) /
2770 png_pass_yinc[png_ptr->pass];
2771 if (!(png_ptr->num_rows))
2772 continue;
2773 }
2774 else /* if (png_ptr->transformations & PNG_INTERLACE) */
2775 break;
2776 } while (png_ptr->iwidth == 0);
2778 if (png_ptr->pass < 7)
2779 return;
2780 }
2782 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
2783 {
2784 #ifdef PNG_USE_LOCAL_ARRAYS
2785 PNG_IDAT;
2786 #endif
2787 char extra;
2788 int ret;
2790 png_ptr->zstream.next_out = (Byte *)&extra;
2791 png_ptr->zstream.avail_out = (uInt)1;
2792 for(;;)
2793 {
2794 if (!(png_ptr->zstream.avail_in))
2795 {
2796 while (!png_ptr->idat_size)
2797 {
2798 png_byte chunk_length[4];
2800 png_crc_finish(png_ptr, 0);
2802 png_read_data(png_ptr, chunk_length, 4);
2803 png_ptr->idat_size = png_get_uint_32(chunk_length);
2805 png_reset_crc(png_ptr);
2806 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2807 if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
2808 png_error(png_ptr, "Not enough image data");
2810 }
2811 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2812 png_ptr->zstream.next_in = png_ptr->zbuf;
2813 if (png_ptr->zbuf_size > png_ptr->idat_size)
2814 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2815 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2816 png_ptr->idat_size -= png_ptr->zstream.avail_in;
2817 }
2818 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
2819 if (ret == Z_STREAM_END)
2820 {
2821 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
2822 png_ptr->idat_size)
2823 png_error(png_ptr, "Extra compressed data");
2824 png_ptr->mode |= PNG_AFTER_IDAT;
2825 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2826 break;
2827 }
2828 if (ret != Z_OK)
2829 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
2830 "Decompression Error");
2832 if (!(png_ptr->zstream.avail_out))
2833 png_error(png_ptr, "Extra compressed data");
2835 }
2836 png_ptr->zstream.avail_out = 0;
2837 }
2839 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
2840 png_error(png_ptr, "Extra compression data");
2842 inflateReset(&png_ptr->zstream);
2844 png_ptr->mode |= PNG_AFTER_IDAT;
2845 }
2847 void /* PRIVATE */
2848 png_read_start_row(png_structp png_ptr)
2849 {
2850 #ifdef PNG_USE_LOCAL_ARRAYS
2851 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2853 /* start of interlace block */
2854 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2856 /* offset to next interlace block */
2857 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2859 /* start of interlace block in the y direction */
2860 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2862 /* offset to next interlace block in the y direction */
2863 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2864 #endif
2866 int max_pixel_depth;
2867 png_uint_32 row_bytes;
2869 png_debug(1, "in png_read_start_row\n");
2870 png_ptr->zstream.avail_in = 0;
2871 png_init_read_transformations(png_ptr);
2872 if (png_ptr->interlaced)
2873 {
2874 if (!(png_ptr->transformations & PNG_INTERLACE))
2875 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2876 png_pass_ystart[0]) / png_pass_yinc[0];
2877 else
2878 png_ptr->num_rows = png_ptr->height;
2880 png_ptr->iwidth = (png_ptr->width +
2881 png_pass_inc[png_ptr->pass] - 1 -
2882 png_pass_start[png_ptr->pass]) /
2883 png_pass_inc[png_ptr->pass];
2885 row_bytes = ((png_ptr->iwidth *
2886 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2887 png_ptr->irowbytes = (png_size_t)row_bytes;
2888 if((png_uint_32)png_ptr->irowbytes != row_bytes)
2889 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
2890 }
2891 else
2892 {
2893 png_ptr->num_rows = png_ptr->height;
2894 png_ptr->iwidth = png_ptr->width;
2895 png_ptr->irowbytes = png_ptr->rowbytes + 1;
2896 }
2897 max_pixel_depth = png_ptr->pixel_depth;
2899 #if defined(PNG_READ_PACK_SUPPORTED)
2900 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
2901 max_pixel_depth = 8;
2902 #endif
2904 #if defined(PNG_READ_EXPAND_SUPPORTED)
2905 if (png_ptr->transformations & PNG_EXPAND)
2906 {
2907 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2908 {
2909 if (png_ptr->num_trans)
2910 max_pixel_depth = 32;
2911 else
2912 max_pixel_depth = 24;
2913 }
2914 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2915 {
2916 if (max_pixel_depth < 8)
2917 max_pixel_depth = 8;
2918 if (png_ptr->num_trans)
2919 max_pixel_depth *= 2;
2920 }
2921 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2922 {
2923 if (png_ptr->num_trans)
2924 {
2925 max_pixel_depth *= 4;
2926 max_pixel_depth /= 3;
2927 }
2928 }
2929 }
2930 #endif
2932 #if defined(PNG_READ_FILLER_SUPPORTED)
2933 if (png_ptr->transformations & (PNG_FILLER))
2934 {
2935 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2936 max_pixel_depth = 32;
2937 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2938 {
2939 if (max_pixel_depth <= 8)
2940 max_pixel_depth = 16;
2941 else
2942 max_pixel_depth = 32;
2943 }
2944 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2945 {
2946 if (max_pixel_depth <= 32)
2947 max_pixel_depth = 32;
2948 else
2949 max_pixel_depth = 64;
2950 }
2951 }
2952 #endif
2954 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2955 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
2956 {
2957 if (
2958 #if defined(PNG_READ_EXPAND_SUPPORTED)
2959 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
2960 #endif
2961 #if defined(PNG_READ_FILLER_SUPPORTED)
2962 (png_ptr->transformations & (PNG_FILLER)) ||
2963 #endif
2964 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
2965 {
2966 if (max_pixel_depth <= 16)
2967 max_pixel_depth = 32;
2968 else
2969 max_pixel_depth = 64;
2970 }
2971 else
2972 {
2973 if (max_pixel_depth <= 8)
2974 {
2975 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2976 max_pixel_depth = 32;
2977 else
2978 max_pixel_depth = 24;
2979 }
2980 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2981 max_pixel_depth = 64;
2982 else
2983 max_pixel_depth = 48;
2984 }
2985 }
2986 #endif
2988 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
2989 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
2990 if(png_ptr->transformations & PNG_USER_TRANSFORM)
2991 {
2992 int user_pixel_depth=png_ptr->user_transform_depth*
2993 png_ptr->user_transform_channels;
2994 if(user_pixel_depth > max_pixel_depth)
2995 max_pixel_depth=user_pixel_depth;
2996 }
2997 #endif
2999 /* align the width on the next larger 8 pixels. Mainly used
3000 for interlacing */
3001 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
3002 /* calculate the maximum bytes needed, adding a byte and a pixel
3003 for safety's sake */
3004 row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
3005 1 + ((max_pixel_depth + 7) >> 3);
3006 #ifdef PNG_MAX_MALLOC_64K
3007 if (row_bytes > (png_uint_32)65536L)
3008 png_error(png_ptr, "This image requires a row greater than 64KB");
3009 #endif
3010 png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, row_bytes);
3012 #ifdef PNG_MAX_MALLOC_64K
3013 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
3014 png_error(png_ptr, "This image requires a row greater than 64KB");
3015 #endif
3016 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3017 png_ptr->rowbytes + 1));
3019 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
3021 png_debug1(3, "width = %lu,\n", png_ptr->width);
3022 png_debug1(3, "height = %lu,\n", png_ptr->height);
3023 png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
3024 png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
3025 png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
3026 png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
3028 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3029 }