istereo2

view libs/libpng/pngrutil.c @ 35:643f4ab609a4

added readme and license
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 31 Oct 2015 05:45:35 +0200
parents
children
line source
2 /* pngrutil.c - utilities to read a PNG file
3 *
4 * Last changed in libpng 1.2.33 [October 31, 2008]
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2008 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"
16 #if defined(PNG_READ_SUPPORTED)
18 #if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
19 # define WIN32_WCE_OLD
20 #endif
22 #ifdef PNG_FLOATING_POINT_SUPPORTED
23 # if defined(WIN32_WCE_OLD)
24 /* strtod() function is not supported on WindowsCE */
25 __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr)
26 {
27 double result = 0;
28 int len;
29 wchar_t *str, *end;
31 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
32 str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
33 if ( NULL != str )
34 {
35 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
36 result = wcstod(str, &end);
37 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
38 *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
39 png_free(png_ptr, str);
40 }
41 return result;
42 }
43 # else
44 # define png_strtod(p,a,b) strtod(a,b)
45 # endif
46 #endif
48 png_uint_32 PNGAPI
49 png_get_uint_31(png_structp png_ptr, png_bytep buf)
50 {
51 #ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
52 png_uint_32 i = png_get_uint_32(buf);
53 #else
54 /* Avoid an extra function call by inlining the result. */
55 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
56 ((png_uint_32)(*(buf + 1)) << 16) +
57 ((png_uint_32)(*(buf + 2)) << 8) +
58 (png_uint_32)(*(buf + 3));
59 #endif
60 if (i > PNG_UINT_31_MAX)
61 png_error(png_ptr, "PNG unsigned integer out of range.");
62 return (i);
63 }
64 #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
65 /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
66 png_uint_32 PNGAPI
67 png_get_uint_32(png_bytep buf)
68 {
69 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
70 ((png_uint_32)(*(buf + 1)) << 16) +
71 ((png_uint_32)(*(buf + 2)) << 8) +
72 (png_uint_32)(*(buf + 3));
74 return (i);
75 }
77 /* Grab a signed 32-bit integer from a buffer in big-endian format. The
78 * data is stored in the PNG file in two's complement format, and it is
79 * assumed that the machine format for signed integers is the same. */
80 png_int_32 PNGAPI
81 png_get_int_32(png_bytep buf)
82 {
83 png_int_32 i = ((png_int_32)(*buf) << 24) +
84 ((png_int_32)(*(buf + 1)) << 16) +
85 ((png_int_32)(*(buf + 2)) << 8) +
86 (png_int_32)(*(buf + 3));
88 return (i);
89 }
91 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
92 png_uint_16 PNGAPI
93 png_get_uint_16(png_bytep buf)
94 {
95 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
96 (png_uint_16)(*(buf + 1)));
98 return (i);
99 }
100 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
102 /* Read the chunk header (length + type name).
103 * Put the type name into png_ptr->chunk_name, and return the length.
104 */
105 png_uint_32 /* PRIVATE */
106 png_read_chunk_header(png_structp png_ptr)
107 {
108 png_byte buf[8];
109 png_uint_32 length;
111 /* read the length and the chunk name */
112 png_read_data(png_ptr, buf, 8);
113 length = png_get_uint_31(png_ptr, buf);
115 /* put the chunk name into png_ptr->chunk_name */
116 png_memcpy(png_ptr->chunk_name, buf + 4, 4);
118 png_debug2(0, "Reading %s chunk, length = %lu\n",
119 png_ptr->chunk_name, length);
121 /* reset the crc and run it over the chunk name */
122 png_reset_crc(png_ptr);
123 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
125 /* check to see if chunk name is valid */
126 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
128 return length;
129 }
131 /* Read data, and (optionally) run it through the CRC. */
132 void /* PRIVATE */
133 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
134 {
135 if (png_ptr == NULL) return;
136 png_read_data(png_ptr, buf, length);
137 png_calculate_crc(png_ptr, buf, length);
138 }
140 /* Optionally skip data and then check the CRC. Depending on whether we
141 are reading a ancillary or critical chunk, and how the program has set
142 things up, we may calculate the CRC on the data and print a message.
143 Returns '1' if there was a CRC error, '0' otherwise. */
144 int /* PRIVATE */
145 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
146 {
147 png_size_t i;
148 png_size_t istop = png_ptr->zbuf_size;
150 for (i = (png_size_t)skip; i > istop; i -= istop)
151 {
152 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
153 }
154 if (i)
155 {
156 png_crc_read(png_ptr, png_ptr->zbuf, i);
157 }
159 if (png_crc_error(png_ptr))
160 {
161 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
162 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
163 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
164 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
165 {
166 png_chunk_warning(png_ptr, "CRC error");
167 }
168 else
169 {
170 png_chunk_error(png_ptr, "CRC error");
171 }
172 return (1);
173 }
175 return (0);
176 }
178 /* Compare the CRC stored in the PNG file with that calculated by libpng from
179 the data it has read thus far. */
180 int /* PRIVATE */
181 png_crc_error(png_structp png_ptr)
182 {
183 png_byte crc_bytes[4];
184 png_uint_32 crc;
185 int need_crc = 1;
187 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
188 {
189 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
190 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
191 need_crc = 0;
192 }
193 else /* critical */
194 {
195 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
196 need_crc = 0;
197 }
199 png_read_data(png_ptr, crc_bytes, 4);
201 if (need_crc)
202 {
203 crc = png_get_uint_32(crc_bytes);
204 return ((int)(crc != png_ptr->crc));
205 }
206 else
207 return (0);
208 }
210 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
211 defined(PNG_READ_iCCP_SUPPORTED)
212 /*
213 * Decompress trailing data in a chunk. The assumption is that chunkdata
214 * points at an allocated area holding the contents of a chunk with a
215 * trailing compressed part. What we get back is an allocated area
216 * holding the original prefix part and an uncompressed version of the
217 * trailing part (the malloc area passed in is freed).
218 */
219 void /* PRIVATE */
220 png_decompress_chunk(png_structp png_ptr, int comp_type,
221 png_size_t chunklength,
222 png_size_t prefix_size, png_size_t *newlength)
223 {
224 static PNG_CONST char msg[] = "Error decoding compressed text";
225 png_charp text;
226 png_size_t text_size;
228 if (comp_type == PNG_COMPRESSION_TYPE_BASE)
229 {
230 int ret = Z_OK;
231 png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size);
232 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
233 png_ptr->zstream.next_out = png_ptr->zbuf;
234 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
236 text_size = 0;
237 text = NULL;
239 while (png_ptr->zstream.avail_in)
240 {
241 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
242 if (ret != Z_OK && ret != Z_STREAM_END)
243 {
244 if (png_ptr->zstream.msg != NULL)
245 png_warning(png_ptr, png_ptr->zstream.msg);
246 else
247 png_warning(png_ptr, msg);
248 inflateReset(&png_ptr->zstream);
249 png_ptr->zstream.avail_in = 0;
251 if (text == NULL)
252 {
253 text_size = prefix_size + png_sizeof(msg) + 1;
254 text = (png_charp)png_malloc_warn(png_ptr, text_size);
255 if (text == NULL)
256 {
257 png_free(png_ptr, png_ptr->chunkdata);
258 png_ptr->chunkdata = NULL;
259 png_error(png_ptr, "Not enough memory to decompress chunk");
260 }
261 png_memcpy(text, png_ptr->chunkdata, prefix_size);
262 }
264 text[text_size - 1] = 0x00;
266 /* Copy what we can of the error message into the text chunk */
267 text_size = (png_size_t)(chunklength -
268 (text - png_ptr->chunkdata) - 1);
269 if (text_size > png_sizeof(msg))
270 text_size = png_sizeof(msg);
271 png_memcpy(text + prefix_size, msg, text_size);
272 break;
273 }
274 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
275 {
276 if (text == NULL)
277 {
278 text_size = prefix_size +
279 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
280 text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
281 if (text == NULL)
282 {
283 png_free(png_ptr, png_ptr->chunkdata);
284 png_ptr->chunkdata = NULL;
285 png_error(png_ptr,
286 "Not enough memory to decompress chunk.");
287 }
288 png_memcpy(text + prefix_size, png_ptr->zbuf,
289 text_size - prefix_size);
290 png_memcpy(text, png_ptr->chunkdata, prefix_size);
291 *(text + text_size) = 0x00;
292 }
293 else
294 {
295 png_charp tmp;
297 tmp = text;
298 text = (png_charp)png_malloc_warn(png_ptr,
299 (png_uint_32)(text_size +
300 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
301 if (text == NULL)
302 {
303 png_free(png_ptr, tmp);
304 png_free(png_ptr, png_ptr->chunkdata);
305 png_ptr->chunkdata = NULL;
306 png_error(png_ptr,
307 "Not enough memory to decompress chunk..");
308 }
309 png_memcpy(text, tmp, text_size);
310 png_free(png_ptr, tmp);
311 png_memcpy(text + text_size, png_ptr->zbuf,
312 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
313 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
314 *(text + text_size) = 0x00;
315 }
316 if (ret == Z_STREAM_END)
317 break;
318 else
319 {
320 png_ptr->zstream.next_out = png_ptr->zbuf;
321 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
322 }
323 }
324 }
325 if (ret != Z_STREAM_END)
326 {
327 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
328 char umsg[52];
330 if (ret == Z_BUF_ERROR)
331 png_snprintf(umsg, 52,
332 "Buffer error in compressed datastream in %s chunk",
333 png_ptr->chunk_name);
334 else if (ret == Z_DATA_ERROR)
335 png_snprintf(umsg, 52,
336 "Data error in compressed datastream in %s chunk",
337 png_ptr->chunk_name);
338 else
339 png_snprintf(umsg, 52,
340 "Incomplete compressed datastream in %s chunk",
341 png_ptr->chunk_name);
342 png_warning(png_ptr, umsg);
343 #else
344 png_warning(png_ptr,
345 "Incomplete compressed datastream in chunk other than IDAT");
346 #endif
347 text_size = prefix_size;
348 if (text == NULL)
349 {
350 text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
351 if (text == NULL)
352 {
353 png_free(png_ptr, png_ptr->chunkdata);
354 png_ptr->chunkdata = NULL;
355 png_error(png_ptr, "Not enough memory for text.");
356 }
357 png_memcpy(text, png_ptr->chunkdata, prefix_size);
358 }
359 *(text + text_size) = 0x00;
360 }
362 inflateReset(&png_ptr->zstream);
363 png_ptr->zstream.avail_in = 0;
365 png_free(png_ptr, png_ptr->chunkdata);
366 png_ptr->chunkdata = text;
367 *newlength=text_size;
368 }
369 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
370 {
371 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
372 char umsg[50];
374 png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type);
375 png_warning(png_ptr, umsg);
376 #else
377 png_warning(png_ptr, "Unknown zTXt compression type");
378 #endif
380 *(png_ptr->chunkdata + prefix_size) = 0x00;
381 *newlength = prefix_size;
382 }
383 }
384 #endif
386 /* read and check the IDHR chunk */
387 void /* PRIVATE */
388 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
389 {
390 png_byte buf[13];
391 png_uint_32 width, height;
392 int bit_depth, color_type, compression_type, filter_type;
393 int interlace_type;
395 png_debug(1, "in png_handle_IHDR\n");
397 if (png_ptr->mode & PNG_HAVE_IHDR)
398 png_error(png_ptr, "Out of place IHDR");
400 /* check the length */
401 if (length != 13)
402 png_error(png_ptr, "Invalid IHDR chunk");
404 png_ptr->mode |= PNG_HAVE_IHDR;
406 png_crc_read(png_ptr, buf, 13);
407 png_crc_finish(png_ptr, 0);
409 width = png_get_uint_31(png_ptr, buf);
410 height = png_get_uint_31(png_ptr, buf + 4);
411 bit_depth = buf[8];
412 color_type = buf[9];
413 compression_type = buf[10];
414 filter_type = buf[11];
415 interlace_type = buf[12];
417 /* set internal variables */
418 png_ptr->width = width;
419 png_ptr->height = height;
420 png_ptr->bit_depth = (png_byte)bit_depth;
421 png_ptr->interlaced = (png_byte)interlace_type;
422 png_ptr->color_type = (png_byte)color_type;
423 #if defined(PNG_MNG_FEATURES_SUPPORTED)
424 png_ptr->filter_type = (png_byte)filter_type;
425 #endif
426 png_ptr->compression_type = (png_byte)compression_type;
428 /* find number of channels */
429 switch (png_ptr->color_type)
430 {
431 case PNG_COLOR_TYPE_GRAY:
432 case PNG_COLOR_TYPE_PALETTE:
433 png_ptr->channels = 1;
434 break;
435 case PNG_COLOR_TYPE_RGB:
436 png_ptr->channels = 3;
437 break;
438 case PNG_COLOR_TYPE_GRAY_ALPHA:
439 png_ptr->channels = 2;
440 break;
441 case PNG_COLOR_TYPE_RGB_ALPHA:
442 png_ptr->channels = 4;
443 break;
444 }
446 /* set up other useful info */
447 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
448 png_ptr->channels);
449 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
450 png_debug1(3, "bit_depth = %d\n", png_ptr->bit_depth);
451 png_debug1(3, "channels = %d\n", png_ptr->channels);
452 png_debug1(3, "rowbytes = %lu\n", png_ptr->rowbytes);
453 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
454 color_type, interlace_type, compression_type, filter_type);
455 }
457 /* read and check the palette */
458 void /* PRIVATE */
459 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
460 {
461 png_color palette[PNG_MAX_PALETTE_LENGTH];
462 int num, i;
463 #ifndef PNG_NO_POINTER_INDEXING
464 png_colorp pal_ptr;
465 #endif
467 png_debug(1, "in png_handle_PLTE\n");
469 if (!(png_ptr->mode & PNG_HAVE_IHDR))
470 png_error(png_ptr, "Missing IHDR before PLTE");
471 else if (png_ptr->mode & PNG_HAVE_IDAT)
472 {
473 png_warning(png_ptr, "Invalid PLTE after IDAT");
474 png_crc_finish(png_ptr, length);
475 return;
476 }
477 else if (png_ptr->mode & PNG_HAVE_PLTE)
478 png_error(png_ptr, "Duplicate PLTE chunk");
480 png_ptr->mode |= PNG_HAVE_PLTE;
482 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
483 {
484 png_warning(png_ptr,
485 "Ignoring PLTE chunk in grayscale PNG");
486 png_crc_finish(png_ptr, length);
487 return;
488 }
489 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
490 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
491 {
492 png_crc_finish(png_ptr, length);
493 return;
494 }
495 #endif
497 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
498 {
499 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
500 {
501 png_warning(png_ptr, "Invalid palette chunk");
502 png_crc_finish(png_ptr, length);
503 return;
504 }
505 else
506 {
507 png_error(png_ptr, "Invalid palette chunk");
508 }
509 }
511 num = (int)length / 3;
513 #ifndef PNG_NO_POINTER_INDEXING
514 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
515 {
516 png_byte buf[3];
518 png_crc_read(png_ptr, buf, 3);
519 pal_ptr->red = buf[0];
520 pal_ptr->green = buf[1];
521 pal_ptr->blue = buf[2];
522 }
523 #else
524 for (i = 0; i < num; i++)
525 {
526 png_byte buf[3];
528 png_crc_read(png_ptr, buf, 3);
529 /* don't depend upon png_color being any order */
530 palette[i].red = buf[0];
531 palette[i].green = buf[1];
532 palette[i].blue = buf[2];
533 }
534 #endif
536 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
537 whatever the normal CRC configuration tells us. However, if we
538 have an RGB image, the PLTE can be considered ancillary, so
539 we will act as though it is. */
540 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
541 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
542 #endif
543 {
544 png_crc_finish(png_ptr, 0);
545 }
546 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
547 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
548 {
549 /* If we don't want to use the data from an ancillary chunk,
550 we have two options: an error abort, or a warning and we
551 ignore the data in this chunk (which should be OK, since
552 it's considered ancillary for a RGB or RGBA image). */
553 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
554 {
555 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
556 {
557 png_chunk_error(png_ptr, "CRC error");
558 }
559 else
560 {
561 png_chunk_warning(png_ptr, "CRC error");
562 return;
563 }
564 }
565 /* Otherwise, we (optionally) emit a warning and use the chunk. */
566 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
567 {
568 png_chunk_warning(png_ptr, "CRC error");
569 }
570 }
571 #endif
573 png_set_PLTE(png_ptr, info_ptr, palette, num);
575 #if defined(PNG_READ_tRNS_SUPPORTED)
576 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
577 {
578 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
579 {
580 if (png_ptr->num_trans > (png_uint_16)num)
581 {
582 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
583 png_ptr->num_trans = (png_uint_16)num;
584 }
585 if (info_ptr->num_trans > (png_uint_16)num)
586 {
587 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
588 info_ptr->num_trans = (png_uint_16)num;
589 }
590 }
591 }
592 #endif
594 }
596 void /* PRIVATE */
597 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
598 {
599 png_debug(1, "in png_handle_IEND\n");
601 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
602 {
603 png_error(png_ptr, "No image in file");
604 }
606 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
608 if (length != 0)
609 {
610 png_warning(png_ptr, "Incorrect IEND chunk length");
611 }
612 png_crc_finish(png_ptr, length);
614 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
615 }
617 #if defined(PNG_READ_gAMA_SUPPORTED)
618 void /* PRIVATE */
619 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
620 {
621 png_fixed_point igamma;
622 #ifdef PNG_FLOATING_POINT_SUPPORTED
623 float file_gamma;
624 #endif
625 png_byte buf[4];
627 png_debug(1, "in png_handle_gAMA\n");
629 if (!(png_ptr->mode & PNG_HAVE_IHDR))
630 png_error(png_ptr, "Missing IHDR before gAMA");
631 else if (png_ptr->mode & PNG_HAVE_IDAT)
632 {
633 png_warning(png_ptr, "Invalid gAMA after IDAT");
634 png_crc_finish(png_ptr, length);
635 return;
636 }
637 else if (png_ptr->mode & PNG_HAVE_PLTE)
638 /* Should be an error, but we can cope with it */
639 png_warning(png_ptr, "Out of place gAMA chunk");
641 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
642 #if defined(PNG_READ_sRGB_SUPPORTED)
643 && !(info_ptr->valid & PNG_INFO_sRGB)
644 #endif
645 )
646 {
647 png_warning(png_ptr, "Duplicate gAMA chunk");
648 png_crc_finish(png_ptr, length);
649 return;
650 }
652 if (length != 4)
653 {
654 png_warning(png_ptr, "Incorrect gAMA chunk length");
655 png_crc_finish(png_ptr, length);
656 return;
657 }
659 png_crc_read(png_ptr, buf, 4);
660 if (png_crc_finish(png_ptr, 0))
661 return;
663 igamma = (png_fixed_point)png_get_uint_32(buf);
664 /* check for zero gamma */
665 if (igamma == 0)
666 {
667 png_warning(png_ptr,
668 "Ignoring gAMA chunk with gamma=0");
669 return;
670 }
672 #if defined(PNG_READ_sRGB_SUPPORTED)
673 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
674 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
675 {
676 png_warning(png_ptr,
677 "Ignoring incorrect gAMA value when sRGB is also present");
678 #ifndef PNG_NO_CONSOLE_IO
679 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
680 #endif
681 return;
682 }
683 #endif /* PNG_READ_sRGB_SUPPORTED */
685 #ifdef PNG_FLOATING_POINT_SUPPORTED
686 file_gamma = (float)igamma / (float)100000.0;
687 # ifdef PNG_READ_GAMMA_SUPPORTED
688 png_ptr->gamma = file_gamma;
689 # endif
690 png_set_gAMA(png_ptr, info_ptr, file_gamma);
691 #endif
692 #ifdef PNG_FIXED_POINT_SUPPORTED
693 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
694 #endif
695 }
696 #endif
698 #if defined(PNG_READ_sBIT_SUPPORTED)
699 void /* PRIVATE */
700 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
701 {
702 png_size_t truelen;
703 png_byte buf[4];
705 png_debug(1, "in png_handle_sBIT\n");
707 buf[0] = buf[1] = buf[2] = buf[3] = 0;
709 if (!(png_ptr->mode & PNG_HAVE_IHDR))
710 png_error(png_ptr, "Missing IHDR before sBIT");
711 else if (png_ptr->mode & PNG_HAVE_IDAT)
712 {
713 png_warning(png_ptr, "Invalid sBIT after IDAT");
714 png_crc_finish(png_ptr, length);
715 return;
716 }
717 else if (png_ptr->mode & PNG_HAVE_PLTE)
718 {
719 /* Should be an error, but we can cope with it */
720 png_warning(png_ptr, "Out of place sBIT chunk");
721 }
722 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
723 {
724 png_warning(png_ptr, "Duplicate sBIT chunk");
725 png_crc_finish(png_ptr, length);
726 return;
727 }
729 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
730 truelen = 3;
731 else
732 truelen = (png_size_t)png_ptr->channels;
734 if (length != truelen || length > 4)
735 {
736 png_warning(png_ptr, "Incorrect sBIT chunk length");
737 png_crc_finish(png_ptr, length);
738 return;
739 }
741 png_crc_read(png_ptr, buf, truelen);
742 if (png_crc_finish(png_ptr, 0))
743 return;
745 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
746 {
747 png_ptr->sig_bit.red = buf[0];
748 png_ptr->sig_bit.green = buf[1];
749 png_ptr->sig_bit.blue = buf[2];
750 png_ptr->sig_bit.alpha = buf[3];
751 }
752 else
753 {
754 png_ptr->sig_bit.gray = buf[0];
755 png_ptr->sig_bit.red = buf[0];
756 png_ptr->sig_bit.green = buf[0];
757 png_ptr->sig_bit.blue = buf[0];
758 png_ptr->sig_bit.alpha = buf[1];
759 }
760 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
761 }
762 #endif
764 #if defined(PNG_READ_cHRM_SUPPORTED)
765 void /* PRIVATE */
766 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
767 {
768 png_byte buf[32];
769 #ifdef PNG_FLOATING_POINT_SUPPORTED
770 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
771 #endif
772 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
773 int_y_green, int_x_blue, int_y_blue;
775 png_uint_32 uint_x, uint_y;
777 png_debug(1, "in png_handle_cHRM\n");
779 if (!(png_ptr->mode & PNG_HAVE_IHDR))
780 png_error(png_ptr, "Missing IHDR before cHRM");
781 else if (png_ptr->mode & PNG_HAVE_IDAT)
782 {
783 png_warning(png_ptr, "Invalid cHRM after IDAT");
784 png_crc_finish(png_ptr, length);
785 return;
786 }
787 else if (png_ptr->mode & PNG_HAVE_PLTE)
788 /* Should be an error, but we can cope with it */
789 png_warning(png_ptr, "Missing PLTE before cHRM");
791 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
792 #if defined(PNG_READ_sRGB_SUPPORTED)
793 && !(info_ptr->valid & PNG_INFO_sRGB)
794 #endif
795 )
796 {
797 png_warning(png_ptr, "Duplicate cHRM chunk");
798 png_crc_finish(png_ptr, length);
799 return;
800 }
802 if (length != 32)
803 {
804 png_warning(png_ptr, "Incorrect cHRM chunk length");
805 png_crc_finish(png_ptr, length);
806 return;
807 }
809 png_crc_read(png_ptr, buf, 32);
810 if (png_crc_finish(png_ptr, 0))
811 return;
813 uint_x = png_get_uint_32(buf);
814 uint_y = png_get_uint_32(buf + 4);
815 if (uint_x > 80000L || uint_y > 80000L ||
816 uint_x + uint_y > 100000L)
817 {
818 png_warning(png_ptr, "Invalid cHRM white point");
819 return;
820 }
821 int_x_white = (png_fixed_point)uint_x;
822 int_y_white = (png_fixed_point)uint_y;
824 uint_x = png_get_uint_32(buf + 8);
825 uint_y = png_get_uint_32(buf + 12);
826 if (uint_x + uint_y > 100000L)
827 {
828 png_warning(png_ptr, "Invalid cHRM red point");
829 return;
830 }
831 int_x_red = (png_fixed_point)uint_x;
832 int_y_red = (png_fixed_point)uint_y;
834 uint_x = png_get_uint_32(buf + 16);
835 uint_y = png_get_uint_32(buf + 20);
836 if (uint_x + uint_y > 100000L)
837 {
838 png_warning(png_ptr, "Invalid cHRM green point");
839 return;
840 }
841 int_x_green = (png_fixed_point)uint_x;
842 int_y_green = (png_fixed_point)uint_y;
844 uint_x = png_get_uint_32(buf + 24);
845 uint_y = png_get_uint_32(buf + 28);
846 if (uint_x + uint_y > 100000L)
847 {
848 png_warning(png_ptr, "Invalid cHRM blue point");
849 return;
850 }
851 int_x_blue = (png_fixed_point)uint_x;
852 int_y_blue = (png_fixed_point)uint_y;
854 #ifdef PNG_FLOATING_POINT_SUPPORTED
855 white_x = (float)int_x_white / (float)100000.0;
856 white_y = (float)int_y_white / (float)100000.0;
857 red_x = (float)int_x_red / (float)100000.0;
858 red_y = (float)int_y_red / (float)100000.0;
859 green_x = (float)int_x_green / (float)100000.0;
860 green_y = (float)int_y_green / (float)100000.0;
861 blue_x = (float)int_x_blue / (float)100000.0;
862 blue_y = (float)int_y_blue / (float)100000.0;
863 #endif
865 #if defined(PNG_READ_sRGB_SUPPORTED)
866 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
867 {
868 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
869 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
870 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
871 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
872 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
873 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
874 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
875 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
876 {
877 png_warning(png_ptr,
878 "Ignoring incorrect cHRM value when sRGB is also present");
879 #ifndef PNG_NO_CONSOLE_IO
880 #ifdef PNG_FLOATING_POINT_SUPPORTED
881 fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
882 white_x, white_y, red_x, red_y);
883 fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
884 green_x, green_y, blue_x, blue_y);
885 #else
886 fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
887 int_x_white, int_y_white, int_x_red, int_y_red);
888 fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
889 int_x_green, int_y_green, int_x_blue, int_y_blue);
890 #endif
891 #endif /* PNG_NO_CONSOLE_IO */
892 }
893 return;
894 }
895 #endif /* PNG_READ_sRGB_SUPPORTED */
897 #ifdef PNG_FLOATING_POINT_SUPPORTED
898 png_set_cHRM(png_ptr, info_ptr,
899 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
900 #endif
901 #ifdef PNG_FIXED_POINT_SUPPORTED
902 png_set_cHRM_fixed(png_ptr, info_ptr,
903 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
904 int_y_green, int_x_blue, int_y_blue);
905 #endif
906 }
907 #endif
909 #if defined(PNG_READ_sRGB_SUPPORTED)
910 void /* PRIVATE */
911 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
912 {
913 int intent;
914 png_byte buf[1];
916 png_debug(1, "in png_handle_sRGB\n");
918 if (!(png_ptr->mode & PNG_HAVE_IHDR))
919 png_error(png_ptr, "Missing IHDR before sRGB");
920 else if (png_ptr->mode & PNG_HAVE_IDAT)
921 {
922 png_warning(png_ptr, "Invalid sRGB after IDAT");
923 png_crc_finish(png_ptr, length);
924 return;
925 }
926 else if (png_ptr->mode & PNG_HAVE_PLTE)
927 /* Should be an error, but we can cope with it */
928 png_warning(png_ptr, "Out of place sRGB chunk");
930 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
931 {
932 png_warning(png_ptr, "Duplicate sRGB chunk");
933 png_crc_finish(png_ptr, length);
934 return;
935 }
937 if (length != 1)
938 {
939 png_warning(png_ptr, "Incorrect sRGB chunk length");
940 png_crc_finish(png_ptr, length);
941 return;
942 }
944 png_crc_read(png_ptr, buf, 1);
945 if (png_crc_finish(png_ptr, 0))
946 return;
948 intent = buf[0];
949 /* check for bad intent */
950 if (intent >= PNG_sRGB_INTENT_LAST)
951 {
952 png_warning(png_ptr, "Unknown sRGB intent");
953 return;
954 }
956 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
957 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
958 {
959 png_fixed_point igamma;
960 #ifdef PNG_FIXED_POINT_SUPPORTED
961 igamma=info_ptr->int_gamma;
962 #else
963 # ifdef PNG_FLOATING_POINT_SUPPORTED
964 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
965 # endif
966 #endif
967 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
968 {
969 png_warning(png_ptr,
970 "Ignoring incorrect gAMA value when sRGB is also present");
971 #ifndef PNG_NO_CONSOLE_IO
972 # ifdef PNG_FIXED_POINT_SUPPORTED
973 fprintf(stderr, "incorrect gamma=(%d/100000)\n",
974 (int)png_ptr->int_gamma);
975 # else
976 # ifdef PNG_FLOATING_POINT_SUPPORTED
977 fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
978 # endif
979 # endif
980 #endif
981 }
982 }
983 #endif /* PNG_READ_gAMA_SUPPORTED */
985 #ifdef PNG_READ_cHRM_SUPPORTED
986 #ifdef PNG_FIXED_POINT_SUPPORTED
987 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
988 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
989 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
990 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
991 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
992 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
993 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
994 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
995 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
996 {
997 png_warning(png_ptr,
998 "Ignoring incorrect cHRM value when sRGB is also present");
999 }
1000 #endif /* PNG_FIXED_POINT_SUPPORTED */
1001 #endif /* PNG_READ_cHRM_SUPPORTED */
1003 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
1005 #endif /* PNG_READ_sRGB_SUPPORTED */
1007 #if defined(PNG_READ_iCCP_SUPPORTED)
1008 void /* PRIVATE */
1009 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1010 /* Note: this does not properly handle chunks that are > 64K under DOS */
1012 png_byte compression_type;
1013 png_bytep pC;
1014 png_charp profile;
1015 png_uint_32 skip = 0;
1016 png_uint_32 profile_size, profile_length;
1017 png_size_t slength, prefix_length, data_length;
1019 png_debug(1, "in png_handle_iCCP\n");
1021 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1022 png_error(png_ptr, "Missing IHDR before iCCP");
1023 else if (png_ptr->mode & PNG_HAVE_IDAT)
1025 png_warning(png_ptr, "Invalid iCCP after IDAT");
1026 png_crc_finish(png_ptr, length);
1027 return;
1029 else if (png_ptr->mode & PNG_HAVE_PLTE)
1030 /* Should be an error, but we can cope with it */
1031 png_warning(png_ptr, "Out of place iCCP chunk");
1033 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1035 png_warning(png_ptr, "Duplicate iCCP chunk");
1036 png_crc_finish(png_ptr, length);
1037 return;
1040 #ifdef PNG_MAX_MALLOC_64K
1041 if (length > (png_uint_32)65535L)
1043 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1044 skip = length - (png_uint_32)65535L;
1045 length = (png_uint_32)65535L;
1047 #endif
1049 png_free(png_ptr, png_ptr->chunkdata);
1050 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1051 slength = (png_size_t)length;
1052 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1054 if (png_crc_finish(png_ptr, skip))
1056 png_free(png_ptr, png_ptr->chunkdata);
1057 png_ptr->chunkdata = NULL;
1058 return;
1061 png_ptr->chunkdata[slength] = 0x00;
1063 for (profile = png_ptr->chunkdata; *profile; profile++)
1064 /* empty loop to find end of name */ ;
1066 ++profile;
1068 /* there should be at least one zero (the compression type byte)
1069 following the separator, and we should be on it */
1070 if ( profile >= png_ptr->chunkdata + slength - 1)
1072 png_free(png_ptr, png_ptr->chunkdata);
1073 png_ptr->chunkdata = NULL;
1074 png_warning(png_ptr, "Malformed iCCP chunk");
1075 return;
1078 /* compression_type should always be zero */
1079 compression_type = *profile++;
1080 if (compression_type)
1082 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1083 compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1084 wrote nonzero) */
1087 prefix_length = profile - png_ptr->chunkdata;
1088 png_decompress_chunk(png_ptr, compression_type,
1089 slength, prefix_length, &data_length);
1091 profile_length = data_length - prefix_length;
1093 if ( prefix_length > data_length || profile_length < 4)
1095 png_free(png_ptr, png_ptr->chunkdata);
1096 png_ptr->chunkdata = NULL;
1097 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1098 return;
1101 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1102 pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
1103 profile_size = ((*(pC ))<<24) |
1104 ((*(pC + 1))<<16) |
1105 ((*(pC + 2))<< 8) |
1106 ((*(pC + 3)) );
1108 if (profile_size < profile_length)
1109 profile_length = profile_size;
1111 if (profile_size > profile_length)
1113 png_free(png_ptr, png_ptr->chunkdata);
1114 png_ptr->chunkdata = NULL;
1115 png_warning(png_ptr, "Ignoring truncated iCCP profile.");
1116 return;
1119 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
1120 compression_type, png_ptr->chunkdata + prefix_length, profile_length);
1121 png_free(png_ptr, png_ptr->chunkdata);
1122 png_ptr->chunkdata = NULL;
1124 #endif /* PNG_READ_iCCP_SUPPORTED */
1126 #if defined(PNG_READ_sPLT_SUPPORTED)
1127 void /* PRIVATE */
1128 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1129 /* Note: this does not properly handle chunks that are > 64K under DOS */
1131 png_bytep entry_start;
1132 png_sPLT_t new_palette;
1133 #ifdef PNG_NO_POINTER_INDEXING
1134 png_sPLT_entryp pp;
1135 #endif
1136 int data_length, entry_size, i;
1137 png_uint_32 skip = 0;
1138 png_size_t slength;
1140 png_debug(1, "in png_handle_sPLT\n");
1142 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1143 png_error(png_ptr, "Missing IHDR before sPLT");
1144 else if (png_ptr->mode & PNG_HAVE_IDAT)
1146 png_warning(png_ptr, "Invalid sPLT after IDAT");
1147 png_crc_finish(png_ptr, length);
1148 return;
1151 #ifdef PNG_MAX_MALLOC_64K
1152 if (length > (png_uint_32)65535L)
1154 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1155 skip = length - (png_uint_32)65535L;
1156 length = (png_uint_32)65535L;
1158 #endif
1160 png_free(png_ptr, png_ptr->chunkdata);
1161 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1162 slength = (png_size_t)length;
1163 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1165 if (png_crc_finish(png_ptr, skip))
1167 png_free(png_ptr, png_ptr->chunkdata);
1168 png_ptr->chunkdata = NULL;
1169 return;
1172 png_ptr->chunkdata[slength] = 0x00;
1174 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; entry_start++)
1175 /* empty loop to find end of name */ ;
1176 ++entry_start;
1178 /* a sample depth should follow the separator, and we should be on it */
1179 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
1181 png_free(png_ptr, png_ptr->chunkdata);
1182 png_ptr->chunkdata = NULL;
1183 png_warning(png_ptr, "malformed sPLT chunk");
1184 return;
1187 new_palette.depth = *entry_start++;
1188 entry_size = (new_palette.depth == 8 ? 6 : 10);
1189 data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
1191 /* integrity-check the data length */
1192 if (data_length % entry_size)
1194 png_free(png_ptr, png_ptr->chunkdata);
1195 png_ptr->chunkdata = NULL;
1196 png_warning(png_ptr, "sPLT chunk has bad length");
1197 return;
1200 new_palette.nentries = (png_int_32) ( data_length / entry_size);
1201 if ((png_uint_32) new_palette.nentries >
1202 (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
1204 png_warning(png_ptr, "sPLT chunk too long");
1205 return;
1207 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1208 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1209 if (new_palette.entries == NULL)
1211 png_warning(png_ptr, "sPLT chunk requires too much memory");
1212 return;
1215 #ifndef PNG_NO_POINTER_INDEXING
1216 for (i = 0; i < new_palette.nentries; i++)
1218 png_sPLT_entryp pp = new_palette.entries + i;
1220 if (new_palette.depth == 8)
1222 pp->red = *entry_start++;
1223 pp->green = *entry_start++;
1224 pp->blue = *entry_start++;
1225 pp->alpha = *entry_start++;
1227 else
1229 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1230 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1231 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1232 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1234 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1236 #else
1237 pp = new_palette.entries;
1238 for (i = 0; i < new_palette.nentries; i++)
1241 if (new_palette.depth == 8)
1243 pp[i].red = *entry_start++;
1244 pp[i].green = *entry_start++;
1245 pp[i].blue = *entry_start++;
1246 pp[i].alpha = *entry_start++;
1248 else
1250 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1251 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1252 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1253 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1255 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1257 #endif
1259 /* discard all chunk data except the name and stash that */
1260 new_palette.name = png_ptr->chunkdata;
1262 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1264 png_free(png_ptr, png_ptr->chunkdata);
1265 png_ptr->chunkdata = NULL;
1266 png_free(png_ptr, new_palette.entries);
1268 #endif /* PNG_READ_sPLT_SUPPORTED */
1270 #if defined(PNG_READ_tRNS_SUPPORTED)
1271 void /* PRIVATE */
1272 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1274 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1276 png_debug(1, "in png_handle_tRNS\n");
1278 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1279 png_error(png_ptr, "Missing IHDR before tRNS");
1280 else if (png_ptr->mode & PNG_HAVE_IDAT)
1282 png_warning(png_ptr, "Invalid tRNS after IDAT");
1283 png_crc_finish(png_ptr, length);
1284 return;
1286 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1288 png_warning(png_ptr, "Duplicate tRNS chunk");
1289 png_crc_finish(png_ptr, length);
1290 return;
1293 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1295 png_byte buf[2];
1297 if (length != 2)
1299 png_warning(png_ptr, "Incorrect tRNS chunk length");
1300 png_crc_finish(png_ptr, length);
1301 return;
1304 png_crc_read(png_ptr, buf, 2);
1305 png_ptr->num_trans = 1;
1306 png_ptr->trans_values.gray = png_get_uint_16(buf);
1308 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1310 png_byte buf[6];
1312 if (length != 6)
1314 png_warning(png_ptr, "Incorrect tRNS chunk length");
1315 png_crc_finish(png_ptr, length);
1316 return;
1318 png_crc_read(png_ptr, buf, (png_size_t)length);
1319 png_ptr->num_trans = 1;
1320 png_ptr->trans_values.red = png_get_uint_16(buf);
1321 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1322 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1324 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1326 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1328 /* Should be an error, but we can cope with it. */
1329 png_warning(png_ptr, "Missing PLTE before tRNS");
1331 if (length > (png_uint_32)png_ptr->num_palette ||
1332 length > PNG_MAX_PALETTE_LENGTH)
1334 png_warning(png_ptr, "Incorrect tRNS chunk length");
1335 png_crc_finish(png_ptr, length);
1336 return;
1338 if (length == 0)
1340 png_warning(png_ptr, "Zero length tRNS chunk");
1341 png_crc_finish(png_ptr, length);
1342 return;
1344 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1345 png_ptr->num_trans = (png_uint_16)length;
1347 else
1349 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1350 png_crc_finish(png_ptr, length);
1351 return;
1354 if (png_crc_finish(png_ptr, 0))
1356 png_ptr->num_trans = 0;
1357 return;
1360 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1361 &(png_ptr->trans_values));
1363 #endif
1365 #if defined(PNG_READ_bKGD_SUPPORTED)
1366 void /* PRIVATE */
1367 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1369 png_size_t truelen;
1370 png_byte buf[6];
1372 png_debug(1, "in png_handle_bKGD\n");
1374 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1375 png_error(png_ptr, "Missing IHDR before bKGD");
1376 else if (png_ptr->mode & PNG_HAVE_IDAT)
1378 png_warning(png_ptr, "Invalid bKGD after IDAT");
1379 png_crc_finish(png_ptr, length);
1380 return;
1382 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1383 !(png_ptr->mode & PNG_HAVE_PLTE))
1385 png_warning(png_ptr, "Missing PLTE before bKGD");
1386 png_crc_finish(png_ptr, length);
1387 return;
1389 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1391 png_warning(png_ptr, "Duplicate bKGD chunk");
1392 png_crc_finish(png_ptr, length);
1393 return;
1396 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1397 truelen = 1;
1398 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1399 truelen = 6;
1400 else
1401 truelen = 2;
1403 if (length != truelen)
1405 png_warning(png_ptr, "Incorrect bKGD chunk length");
1406 png_crc_finish(png_ptr, length);
1407 return;
1410 png_crc_read(png_ptr, buf, truelen);
1411 if (png_crc_finish(png_ptr, 0))
1412 return;
1414 /* We convert the index value into RGB components so that we can allow
1415 * arbitrary RGB values for background when we have transparency, and
1416 * so it is easy to determine the RGB values of the background color
1417 * from the info_ptr struct. */
1418 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1420 png_ptr->background.index = buf[0];
1421 if (info_ptr && info_ptr->num_palette)
1423 if (buf[0] > info_ptr->num_palette)
1425 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1426 return;
1428 png_ptr->background.red =
1429 (png_uint_16)png_ptr->palette[buf[0]].red;
1430 png_ptr->background.green =
1431 (png_uint_16)png_ptr->palette[buf[0]].green;
1432 png_ptr->background.blue =
1433 (png_uint_16)png_ptr->palette[buf[0]].blue;
1436 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1438 png_ptr->background.red =
1439 png_ptr->background.green =
1440 png_ptr->background.blue =
1441 png_ptr->background.gray = png_get_uint_16(buf);
1443 else
1445 png_ptr->background.red = png_get_uint_16(buf);
1446 png_ptr->background.green = png_get_uint_16(buf + 2);
1447 png_ptr->background.blue = png_get_uint_16(buf + 4);
1450 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1452 #endif
1454 #if defined(PNG_READ_hIST_SUPPORTED)
1455 void /* PRIVATE */
1456 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1458 unsigned int num, i;
1459 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1461 png_debug(1, "in png_handle_hIST\n");
1463 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1464 png_error(png_ptr, "Missing IHDR before hIST");
1465 else if (png_ptr->mode & PNG_HAVE_IDAT)
1467 png_warning(png_ptr, "Invalid hIST after IDAT");
1468 png_crc_finish(png_ptr, length);
1469 return;
1471 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1473 png_warning(png_ptr, "Missing PLTE before hIST");
1474 png_crc_finish(png_ptr, length);
1475 return;
1477 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1479 png_warning(png_ptr, "Duplicate hIST chunk");
1480 png_crc_finish(png_ptr, length);
1481 return;
1484 num = length / 2 ;
1485 if (num != (unsigned int) png_ptr->num_palette || num >
1486 (unsigned int) PNG_MAX_PALETTE_LENGTH)
1488 png_warning(png_ptr, "Incorrect hIST chunk length");
1489 png_crc_finish(png_ptr, length);
1490 return;
1493 for (i = 0; i < num; i++)
1495 png_byte buf[2];
1497 png_crc_read(png_ptr, buf, 2);
1498 readbuf[i] = png_get_uint_16(buf);
1501 if (png_crc_finish(png_ptr, 0))
1502 return;
1504 png_set_hIST(png_ptr, info_ptr, readbuf);
1506 #endif
1508 #if defined(PNG_READ_pHYs_SUPPORTED)
1509 void /* PRIVATE */
1510 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1512 png_byte buf[9];
1513 png_uint_32 res_x, res_y;
1514 int unit_type;
1516 png_debug(1, "in png_handle_pHYs\n");
1518 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1519 png_error(png_ptr, "Missing IHDR before pHYs");
1520 else if (png_ptr->mode & PNG_HAVE_IDAT)
1522 png_warning(png_ptr, "Invalid pHYs after IDAT");
1523 png_crc_finish(png_ptr, length);
1524 return;
1526 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1528 png_warning(png_ptr, "Duplicate pHYs chunk");
1529 png_crc_finish(png_ptr, length);
1530 return;
1533 if (length != 9)
1535 png_warning(png_ptr, "Incorrect pHYs chunk length");
1536 png_crc_finish(png_ptr, length);
1537 return;
1540 png_crc_read(png_ptr, buf, 9);
1541 if (png_crc_finish(png_ptr, 0))
1542 return;
1544 res_x = png_get_uint_32(buf);
1545 res_y = png_get_uint_32(buf + 4);
1546 unit_type = buf[8];
1547 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1549 #endif
1551 #if defined(PNG_READ_oFFs_SUPPORTED)
1552 void /* PRIVATE */
1553 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1555 png_byte buf[9];
1556 png_int_32 offset_x, offset_y;
1557 int unit_type;
1559 png_debug(1, "in png_handle_oFFs\n");
1561 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1562 png_error(png_ptr, "Missing IHDR before oFFs");
1563 else if (png_ptr->mode & PNG_HAVE_IDAT)
1565 png_warning(png_ptr, "Invalid oFFs after IDAT");
1566 png_crc_finish(png_ptr, length);
1567 return;
1569 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1571 png_warning(png_ptr, "Duplicate oFFs chunk");
1572 png_crc_finish(png_ptr, length);
1573 return;
1576 if (length != 9)
1578 png_warning(png_ptr, "Incorrect oFFs chunk length");
1579 png_crc_finish(png_ptr, length);
1580 return;
1583 png_crc_read(png_ptr, buf, 9);
1584 if (png_crc_finish(png_ptr, 0))
1585 return;
1587 offset_x = png_get_int_32(buf);
1588 offset_y = png_get_int_32(buf + 4);
1589 unit_type = buf[8];
1590 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1592 #endif
1594 #if defined(PNG_READ_pCAL_SUPPORTED)
1595 /* read the pCAL chunk (described in the PNG Extensions document) */
1596 void /* PRIVATE */
1597 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1599 png_int_32 X0, X1;
1600 png_byte type, nparams;
1601 png_charp buf, units, endptr;
1602 png_charpp params;
1603 png_size_t slength;
1604 int i;
1606 png_debug(1, "in png_handle_pCAL\n");
1608 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1609 png_error(png_ptr, "Missing IHDR before pCAL");
1610 else if (png_ptr->mode & PNG_HAVE_IDAT)
1612 png_warning(png_ptr, "Invalid pCAL after IDAT");
1613 png_crc_finish(png_ptr, length);
1614 return;
1616 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1618 png_warning(png_ptr, "Duplicate pCAL chunk");
1619 png_crc_finish(png_ptr, length);
1620 return;
1623 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
1624 length + 1);
1625 png_free(png_ptr, png_ptr->chunkdata);
1626 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1627 if (png_ptr->chunkdata == NULL)
1629 png_warning(png_ptr, "No memory for pCAL purpose.");
1630 return;
1632 slength = (png_size_t)length;
1633 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1635 if (png_crc_finish(png_ptr, 0))
1637 png_free(png_ptr, png_ptr->chunkdata);
1638 png_ptr->chunkdata = NULL;
1639 return;
1642 png_ptr->chunkdata[slength] = 0x00; /* null terminate the last string */
1644 png_debug(3, "Finding end of pCAL purpose string\n");
1645 for (buf = png_ptr->chunkdata; *buf; buf++)
1646 /* empty loop */ ;
1648 endptr = png_ptr->chunkdata + slength;
1650 /* We need to have at least 12 bytes after the purpose string
1651 in order to get the parameter information. */
1652 if (endptr <= buf + 12)
1654 png_warning(png_ptr, "Invalid pCAL data");
1655 png_free(png_ptr, png_ptr->chunkdata);
1656 png_ptr->chunkdata = NULL;
1657 return;
1660 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1661 X0 = png_get_int_32((png_bytep)buf+1);
1662 X1 = png_get_int_32((png_bytep)buf+5);
1663 type = buf[9];
1664 nparams = buf[10];
1665 units = buf + 11;
1667 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1668 /* Check that we have the right number of parameters for known
1669 equation types. */
1670 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1671 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1672 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1673 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1675 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1676 png_free(png_ptr, png_ptr->chunkdata);
1677 png_ptr->chunkdata = NULL;
1678 return;
1680 else if (type >= PNG_EQUATION_LAST)
1682 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1685 for (buf = units; *buf; buf++)
1686 /* Empty loop to move past the units string. */ ;
1688 png_debug(3, "Allocating pCAL parameters array\n");
1689 params = (png_charpp)png_malloc_warn(png_ptr,
1690 (png_uint_32)(nparams * png_sizeof(png_charp))) ;
1691 if (params == NULL)
1693 png_free(png_ptr, png_ptr->chunkdata);
1694 png_ptr->chunkdata = NULL;
1695 png_warning(png_ptr, "No memory for pCAL params.");
1696 return;
1699 /* Get pointers to the start of each parameter string. */
1700 for (i = 0; i < (int)nparams; i++)
1702 buf++; /* Skip the null string terminator from previous parameter. */
1704 png_debug1(3, "Reading pCAL parameter %d\n", i);
1705 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
1706 /* Empty loop to move past each parameter string */ ;
1708 /* Make sure we haven't run out of data yet */
1709 if (buf > endptr)
1711 png_warning(png_ptr, "Invalid pCAL data");
1712 png_free(png_ptr, png_ptr->chunkdata);
1713 png_ptr->chunkdata = NULL;
1714 png_free(png_ptr, params);
1715 return;
1719 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
1720 units, params);
1722 png_free(png_ptr, png_ptr->chunkdata);
1723 png_ptr->chunkdata = NULL;
1724 png_free(png_ptr, params);
1726 #endif
1728 #if defined(PNG_READ_sCAL_SUPPORTED)
1729 /* read the sCAL chunk */
1730 void /* PRIVATE */
1731 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1733 png_charp ep;
1734 #ifdef PNG_FLOATING_POINT_SUPPORTED
1735 double width, height;
1736 png_charp vp;
1737 #else
1738 #ifdef PNG_FIXED_POINT_SUPPORTED
1739 png_charp swidth, sheight;
1740 #endif
1741 #endif
1742 png_size_t slength;
1744 png_debug(1, "in png_handle_sCAL\n");
1746 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1747 png_error(png_ptr, "Missing IHDR before sCAL");
1748 else if (png_ptr->mode & PNG_HAVE_IDAT)
1750 png_warning(png_ptr, "Invalid sCAL after IDAT");
1751 png_crc_finish(png_ptr, length);
1752 return;
1754 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1756 png_warning(png_ptr, "Duplicate sCAL chunk");
1757 png_crc_finish(png_ptr, length);
1758 return;
1761 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1762 length + 1);
1763 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1764 if (png_ptr->chunkdata == NULL)
1766 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
1767 return;
1769 slength = (png_size_t)length;
1770 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1772 if (png_crc_finish(png_ptr, 0))
1774 png_free(png_ptr, png_ptr->chunkdata);
1775 png_ptr->chunkdata = NULL;
1776 return;
1779 png_ptr->chunkdata[slength] = 0x00; /* null terminate the last string */
1781 ep = png_ptr->chunkdata + 1; /* skip unit byte */
1783 #ifdef PNG_FLOATING_POINT_SUPPORTED
1784 width = png_strtod(png_ptr, ep, &vp);
1785 if (*vp)
1787 png_warning(png_ptr, "malformed width string in sCAL chunk");
1788 return;
1790 #else
1791 #ifdef PNG_FIXED_POINT_SUPPORTED
1792 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1793 if (swidth == NULL)
1795 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
1796 return;
1798 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1799 #endif
1800 #endif
1802 for (ep = png_ptr->chunkdata; *ep; ep++)
1803 /* empty loop */ ;
1804 ep++;
1806 if (png_ptr->chunkdata + slength < ep)
1808 png_warning(png_ptr, "Truncated sCAL chunk");
1809 #if defined(PNG_FIXED_POINT_SUPPORTED) && \
1810 !defined(PNG_FLOATING_POINT_SUPPORTED)
1811 png_free(png_ptr, swidth);
1812 #endif
1813 png_free(png_ptr, png_ptr->chunkdata);
1814 png_ptr->chunkdata = NULL;
1815 return;
1818 #ifdef PNG_FLOATING_POINT_SUPPORTED
1819 height = png_strtod(png_ptr, ep, &vp);
1820 if (*vp)
1822 png_warning(png_ptr, "malformed height string in sCAL chunk");
1823 return;
1825 #else
1826 #ifdef PNG_FIXED_POINT_SUPPORTED
1827 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1828 if (sheight == NULL)
1830 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
1831 return;
1833 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1834 #endif
1835 #endif
1837 if (png_ptr->chunkdata + slength < ep
1838 #ifdef PNG_FLOATING_POINT_SUPPORTED
1839 || width <= 0. || height <= 0.
1840 #endif
1843 png_warning(png_ptr, "Invalid sCAL data");
1844 png_free(png_ptr, png_ptr->chunkdata);
1845 png_ptr->chunkdata = NULL;
1846 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1847 png_free(png_ptr, swidth);
1848 png_free(png_ptr, sheight);
1849 #endif
1850 return;
1854 #ifdef PNG_FLOATING_POINT_SUPPORTED
1855 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
1856 #else
1857 #ifdef PNG_FIXED_POINT_SUPPORTED
1858 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
1859 #endif
1860 #endif
1862 png_free(png_ptr, png_ptr->chunkdata);
1863 png_ptr->chunkdata = NULL;
1864 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1865 png_free(png_ptr, swidth);
1866 png_free(png_ptr, sheight);
1867 #endif
1869 #endif
1871 #if defined(PNG_READ_tIME_SUPPORTED)
1872 void /* PRIVATE */
1873 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1875 png_byte buf[7];
1876 png_time mod_time;
1878 png_debug(1, "in png_handle_tIME\n");
1880 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1881 png_error(png_ptr, "Out of place tIME chunk");
1882 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1884 png_warning(png_ptr, "Duplicate tIME chunk");
1885 png_crc_finish(png_ptr, length);
1886 return;
1889 if (png_ptr->mode & PNG_HAVE_IDAT)
1890 png_ptr->mode |= PNG_AFTER_IDAT;
1892 if (length != 7)
1894 png_warning(png_ptr, "Incorrect tIME chunk length");
1895 png_crc_finish(png_ptr, length);
1896 return;
1899 png_crc_read(png_ptr, buf, 7);
1900 if (png_crc_finish(png_ptr, 0))
1901 return;
1903 mod_time.second = buf[6];
1904 mod_time.minute = buf[5];
1905 mod_time.hour = buf[4];
1906 mod_time.day = buf[3];
1907 mod_time.month = buf[2];
1908 mod_time.year = png_get_uint_16(buf);
1910 png_set_tIME(png_ptr, info_ptr, &mod_time);
1912 #endif
1914 #if defined(PNG_READ_tEXt_SUPPORTED)
1915 /* Note: this does not properly handle chunks that are > 64K under DOS */
1916 void /* PRIVATE */
1917 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1919 png_textp text_ptr;
1920 png_charp key;
1921 png_charp text;
1922 png_uint_32 skip = 0;
1923 png_size_t slength;
1924 int ret;
1926 png_debug(1, "in png_handle_tEXt\n");
1928 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1929 png_error(png_ptr, "Missing IHDR before tEXt");
1931 if (png_ptr->mode & PNG_HAVE_IDAT)
1932 png_ptr->mode |= PNG_AFTER_IDAT;
1934 #ifdef PNG_MAX_MALLOC_64K
1935 if (length > (png_uint_32)65535L)
1937 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1938 skip = length - (png_uint_32)65535L;
1939 length = (png_uint_32)65535L;
1941 #endif
1943 png_free(png_ptr, png_ptr->chunkdata);
1944 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1945 if (png_ptr->chunkdata == NULL)
1947 png_warning(png_ptr, "No memory to process text chunk.");
1948 return;
1950 slength = (png_size_t)length;
1951 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
1953 if (png_crc_finish(png_ptr, skip))
1955 png_free(png_ptr, png_ptr->chunkdata);
1956 png_ptr->chunkdata = NULL;
1957 return;
1960 key = png_ptr->chunkdata;
1961 key[slength] = 0x00;
1963 for (text = key; *text; text++)
1964 /* empty loop to find end of key */ ;
1966 if (text != key + slength)
1967 text++;
1969 text_ptr = (png_textp)png_malloc_warn(png_ptr,
1970 (png_uint_32)png_sizeof(png_text));
1971 if (text_ptr == NULL)
1973 png_warning(png_ptr, "Not enough memory to process text chunk.");
1974 png_free(png_ptr, png_ptr->chunkdata);
1975 png_ptr->chunkdata = NULL;
1976 return;
1978 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1979 text_ptr->key = key;
1980 #ifdef PNG_iTXt_SUPPORTED
1981 text_ptr->lang = NULL;
1982 text_ptr->lang_key = NULL;
1983 text_ptr->itxt_length = 0;
1984 #endif
1985 text_ptr->text = text;
1986 text_ptr->text_length = png_strlen(text);
1988 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
1990 png_free(png_ptr, png_ptr->chunkdata);
1991 png_ptr->chunkdata = NULL;
1992 png_free(png_ptr, text_ptr);
1993 if (ret)
1994 png_warning(png_ptr, "Insufficient memory to process text chunk.");
1996 #endif
1998 #if defined(PNG_READ_zTXt_SUPPORTED)
1999 /* note: this does not correctly handle chunks that are > 64K under DOS */
2000 void /* PRIVATE */
2001 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2003 png_textp text_ptr;
2004 png_charp text;
2005 int comp_type;
2006 int ret;
2007 png_size_t slength, prefix_len, data_len;
2009 png_debug(1, "in png_handle_zTXt\n");
2010 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2011 png_error(png_ptr, "Missing IHDR before zTXt");
2013 if (png_ptr->mode & PNG_HAVE_IDAT)
2014 png_ptr->mode |= PNG_AFTER_IDAT;
2016 #ifdef PNG_MAX_MALLOC_64K
2017 /* We will no doubt have problems with chunks even half this size, but
2018 there is no hard and fast rule to tell us where to stop. */
2019 if (length > (png_uint_32)65535L)
2021 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
2022 png_crc_finish(png_ptr, length);
2023 return;
2025 #endif
2027 png_free(png_ptr, png_ptr->chunkdata);
2028 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2029 if (png_ptr->chunkdata == NULL)
2031 png_warning(png_ptr, "Out of memory processing zTXt chunk.");
2032 return;
2034 slength = (png_size_t)length;
2035 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
2036 if (png_crc_finish(png_ptr, 0))
2038 png_free(png_ptr, png_ptr->chunkdata);
2039 png_ptr->chunkdata = NULL;
2040 return;
2043 png_ptr->chunkdata[slength] = 0x00;
2045 for (text = png_ptr->chunkdata; *text; text++)
2046 /* empty loop */ ;
2048 /* zTXt must have some text after the chunkdataword */
2049 if (text >= png_ptr->chunkdata + slength - 2)
2051 png_warning(png_ptr, "Truncated zTXt chunk");
2052 png_free(png_ptr, png_ptr->chunkdata);
2053 png_ptr->chunkdata = NULL;
2054 return;
2056 else
2058 comp_type = *(++text);
2059 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2061 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2062 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2064 text++; /* skip the compression_method byte */
2066 prefix_len = text - png_ptr->chunkdata;
2068 png_decompress_chunk(png_ptr, comp_type,
2069 (png_size_t)length, prefix_len, &data_len);
2071 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2072 (png_uint_32)png_sizeof(png_text));
2073 if (text_ptr == NULL)
2075 png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
2076 png_free(png_ptr, png_ptr->chunkdata);
2077 png_ptr->chunkdata = NULL;
2078 return;
2080 text_ptr->compression = comp_type;
2081 text_ptr->key = png_ptr->chunkdata;
2082 #ifdef PNG_iTXt_SUPPORTED
2083 text_ptr->lang = NULL;
2084 text_ptr->lang_key = NULL;
2085 text_ptr->itxt_length = 0;
2086 #endif
2087 text_ptr->text = png_ptr->chunkdata + prefix_len;
2088 text_ptr->text_length = data_len;
2090 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2092 png_free(png_ptr, text_ptr);
2093 png_free(png_ptr, png_ptr->chunkdata);
2094 png_ptr->chunkdata = NULL;
2095 if (ret)
2096 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2098 #endif
2100 #if defined(PNG_READ_iTXt_SUPPORTED)
2101 /* note: this does not correctly handle chunks that are > 64K under DOS */
2102 void /* PRIVATE */
2103 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2105 png_textp text_ptr;
2106 png_charp key, lang, text, lang_key;
2107 int comp_flag;
2108 int comp_type = 0;
2109 int ret;
2110 png_size_t slength, prefix_len, data_len;
2112 png_debug(1, "in png_handle_iTXt\n");
2114 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2115 png_error(png_ptr, "Missing IHDR before iTXt");
2117 if (png_ptr->mode & PNG_HAVE_IDAT)
2118 png_ptr->mode |= PNG_AFTER_IDAT;
2120 #ifdef PNG_MAX_MALLOC_64K
2121 /* We will no doubt have problems with chunks even half this size, but
2122 there is no hard and fast rule to tell us where to stop. */
2123 if (length > (png_uint_32)65535L)
2125 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
2126 png_crc_finish(png_ptr, length);
2127 return;
2129 #endif
2131 png_free(png_ptr, png_ptr->chunkdata);
2132 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2133 if (png_ptr->chunkdata == NULL)
2135 png_warning(png_ptr, "No memory to process iTXt chunk.");
2136 return;
2138 slength = (png_size_t)length;
2139 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
2140 if (png_crc_finish(png_ptr, 0))
2142 png_free(png_ptr, png_ptr->chunkdata);
2143 png_ptr->chunkdata = NULL;
2144 return;
2147 png_ptr->chunkdata[slength] = 0x00;
2149 for (lang = png_ptr->chunkdata; *lang; lang++)
2150 /* empty loop */ ;
2151 lang++; /* skip NUL separator */
2153 /* iTXt must have a language tag (possibly empty), two compression bytes,
2154 translated keyword (possibly empty), and possibly some text after the
2155 keyword */
2157 if (lang >= png_ptr->chunkdata + slength - 3)
2159 png_warning(png_ptr, "Truncated iTXt chunk");
2160 png_free(png_ptr, png_ptr->chunkdata);
2161 png_ptr->chunkdata = NULL;
2162 return;
2164 else
2166 comp_flag = *lang++;
2167 comp_type = *lang++;
2170 for (lang_key = lang; *lang_key; lang_key++)
2171 /* empty loop */ ;
2172 lang_key++; /* skip NUL separator */
2174 if (lang_key >= png_ptr->chunkdata + slength)
2176 png_warning(png_ptr, "Truncated iTXt chunk");
2177 png_free(png_ptr, png_ptr->chunkdata);
2178 png_ptr->chunkdata = NULL;
2179 return;
2182 for (text = lang_key; *text; text++)
2183 /* empty loop */ ;
2184 text++; /* skip NUL separator */
2185 if (text >= png_ptr->chunkdata + slength)
2187 png_warning(png_ptr, "Malformed iTXt chunk");
2188 png_free(png_ptr, png_ptr->chunkdata);
2189 png_ptr->chunkdata = NULL;
2190 return;
2193 prefix_len = text - png_ptr->chunkdata;
2195 key=png_ptr->chunkdata;
2196 if (comp_flag)
2197 png_decompress_chunk(png_ptr, comp_type,
2198 (size_t)length, prefix_len, &data_len);
2199 else
2200 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
2201 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2202 (png_uint_32)png_sizeof(png_text));
2203 if (text_ptr == NULL)
2205 png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
2206 png_free(png_ptr, png_ptr->chunkdata);
2207 png_ptr->chunkdata = NULL;
2208 return;
2210 text_ptr->compression = (int)comp_flag + 1;
2211 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
2212 text_ptr->lang = png_ptr->chunkdata + (lang - key);
2213 text_ptr->itxt_length = data_len;
2214 text_ptr->text_length = 0;
2215 text_ptr->key = png_ptr->chunkdata;
2216 text_ptr->text = png_ptr->chunkdata + prefix_len;
2218 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2220 png_free(png_ptr, text_ptr);
2221 png_free(png_ptr, png_ptr->chunkdata);
2222 png_ptr->chunkdata = NULL;
2223 if (ret)
2224 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
2226 #endif
2228 /* This function is called when we haven't found a handler for a
2229 chunk. If there isn't a problem with the chunk itself (ie bad
2230 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2231 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2232 case it will be saved away to be written out later. */
2233 void /* PRIVATE */
2234 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2236 png_uint_32 skip = 0;
2238 png_debug(1, "in png_handle_unknown\n");
2240 if (png_ptr->mode & PNG_HAVE_IDAT)
2242 #ifdef PNG_USE_LOCAL_ARRAYS
2243 PNG_CONST PNG_IDAT;
2244 #endif
2245 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2246 png_ptr->mode |= PNG_AFTER_IDAT;
2249 if (!(png_ptr->chunk_name[0] & 0x20))
2251 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2252 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2253 PNG_HANDLE_CHUNK_ALWAYS
2254 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2255 && png_ptr->read_user_chunk_fn == NULL
2256 #endif
2258 #endif
2259 png_chunk_error(png_ptr, "unknown critical chunk");
2262 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2263 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
2264 (png_ptr->read_user_chunk_fn != NULL))
2266 #ifdef PNG_MAX_MALLOC_64K
2267 if (length > (png_uint_32)65535L)
2269 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2270 skip = length - (png_uint_32)65535L;
2271 length = (png_uint_32)65535L;
2273 #endif
2274 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
2275 (png_charp)png_ptr->chunk_name,
2276 png_sizeof(png_ptr->unknown_chunk.name));
2277 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0';
2278 png_ptr->unknown_chunk.size = (png_size_t)length;
2279 if (length == 0)
2280 png_ptr->unknown_chunk.data = NULL;
2281 else
2283 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2284 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2286 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2287 if (png_ptr->read_user_chunk_fn != NULL)
2289 /* callback to user unknown chunk handler */
2290 int ret;
2291 ret = (*(png_ptr->read_user_chunk_fn))
2292 (png_ptr, &png_ptr->unknown_chunk);
2293 if (ret < 0)
2294 png_chunk_error(png_ptr, "error in user chunk");
2295 if (ret == 0)
2297 if (!(png_ptr->chunk_name[0] & 0x20))
2298 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2299 PNG_HANDLE_CHUNK_ALWAYS)
2300 png_chunk_error(png_ptr, "unknown critical chunk");
2301 png_set_unknown_chunks(png_ptr, info_ptr,
2302 &png_ptr->unknown_chunk, 1);
2305 else
2306 #endif
2307 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
2308 png_free(png_ptr, png_ptr->unknown_chunk.data);
2309 png_ptr->unknown_chunk.data = NULL;
2311 else
2312 #endif
2313 skip = length;
2315 png_crc_finish(png_ptr, skip);
2317 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2318 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
2319 #endif
2322 /* This function is called to verify that a chunk name is valid.
2323 This function can't have the "critical chunk check" incorporated
2324 into it, since in the future we will need to be able to call user
2325 functions to handle unknown critical chunks after we check that
2326 the chunk name itself is valid. */
2328 #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
2330 void /* PRIVATE */
2331 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2333 png_debug(1, "in png_check_chunk_name\n");
2334 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2335 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2337 png_chunk_error(png_ptr, "invalid chunk type");
2341 /* Combines the row recently read in with the existing pixels in the
2342 row. This routine takes care of alpha and transparency if requested.
2343 This routine also handles the two methods of progressive display
2344 of interlaced images, depending on the mask value.
2345 The mask value describes which pixels are to be combined with
2346 the row. The pattern always repeats every 8 pixels, so just 8
2347 bits are needed. A one indicates the pixel is to be combined,
2348 a zero indicates the pixel is to be skipped. This is in addition
2349 to any alpha or transparency value associated with the pixel. If
2350 you want all pixels to be combined, pass 0xff (255) in mask. */
2352 void /* PRIVATE */
2353 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2355 png_debug(1, "in png_combine_row\n");
2356 if (mask == 0xff)
2358 png_memcpy(row, png_ptr->row_buf + 1,
2359 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
2361 else
2363 switch (png_ptr->row_info.pixel_depth)
2365 case 1:
2367 png_bytep sp = png_ptr->row_buf + 1;
2368 png_bytep dp = row;
2369 int s_inc, s_start, s_end;
2370 int m = 0x80;
2371 int shift;
2372 png_uint_32 i;
2373 png_uint_32 row_width = png_ptr->width;
2375 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2376 if (png_ptr->transformations & PNG_PACKSWAP)
2378 s_start = 0;
2379 s_end = 7;
2380 s_inc = 1;
2382 else
2383 #endif
2385 s_start = 7;
2386 s_end = 0;
2387 s_inc = -1;
2390 shift = s_start;
2392 for (i = 0; i < row_width; i++)
2394 if (m & mask)
2396 int value;
2398 value = (*sp >> shift) & 0x01;
2399 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2400 *dp |= (png_byte)(value << shift);
2403 if (shift == s_end)
2405 shift = s_start;
2406 sp++;
2407 dp++;
2409 else
2410 shift += s_inc;
2412 if (m == 1)
2413 m = 0x80;
2414 else
2415 m >>= 1;
2417 break;
2419 case 2:
2421 png_bytep sp = png_ptr->row_buf + 1;
2422 png_bytep dp = row;
2423 int s_start, s_end, s_inc;
2424 int m = 0x80;
2425 int shift;
2426 png_uint_32 i;
2427 png_uint_32 row_width = png_ptr->width;
2428 int value;
2430 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2431 if (png_ptr->transformations & PNG_PACKSWAP)
2433 s_start = 0;
2434 s_end = 6;
2435 s_inc = 2;
2437 else
2438 #endif
2440 s_start = 6;
2441 s_end = 0;
2442 s_inc = -2;
2445 shift = s_start;
2447 for (i = 0; i < row_width; i++)
2449 if (m & mask)
2451 value = (*sp >> shift) & 0x03;
2452 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2453 *dp |= (png_byte)(value << shift);
2456 if (shift == s_end)
2458 shift = s_start;
2459 sp++;
2460 dp++;
2462 else
2463 shift += s_inc;
2464 if (m == 1)
2465 m = 0x80;
2466 else
2467 m >>= 1;
2469 break;
2471 case 4:
2473 png_bytep sp = png_ptr->row_buf + 1;
2474 png_bytep dp = row;
2475 int s_start, s_end, s_inc;
2476 int m = 0x80;
2477 int shift;
2478 png_uint_32 i;
2479 png_uint_32 row_width = png_ptr->width;
2480 int value;
2482 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2483 if (png_ptr->transformations & PNG_PACKSWAP)
2485 s_start = 0;
2486 s_end = 4;
2487 s_inc = 4;
2489 else
2490 #endif
2492 s_start = 4;
2493 s_end = 0;
2494 s_inc = -4;
2496 shift = s_start;
2498 for (i = 0; i < row_width; i++)
2500 if (m & mask)
2502 value = (*sp >> shift) & 0xf;
2503 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2504 *dp |= (png_byte)(value << shift);
2507 if (shift == s_end)
2509 shift = s_start;
2510 sp++;
2511 dp++;
2513 else
2514 shift += s_inc;
2515 if (m == 1)
2516 m = 0x80;
2517 else
2518 m >>= 1;
2520 break;
2522 default:
2524 png_bytep sp = png_ptr->row_buf + 1;
2525 png_bytep dp = row;
2526 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2527 png_uint_32 i;
2528 png_uint_32 row_width = png_ptr->width;
2529 png_byte m = 0x80;
2532 for (i = 0; i < row_width; i++)
2534 if (m & mask)
2536 png_memcpy(dp, sp, pixel_bytes);
2539 sp += pixel_bytes;
2540 dp += pixel_bytes;
2542 if (m == 1)
2543 m = 0x80;
2544 else
2545 m >>= 1;
2547 break;
2553 #ifdef PNG_READ_INTERLACING_SUPPORTED
2554 /* OLD pre-1.0.9 interface:
2555 void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2556 png_uint_32 transformations)
2557 */
2558 void /* PRIVATE */
2559 png_do_read_interlace(png_structp png_ptr)
2561 png_row_infop row_info = &(png_ptr->row_info);
2562 png_bytep row = png_ptr->row_buf + 1;
2563 int pass = png_ptr->pass;
2564 png_uint_32 transformations = png_ptr->transformations;
2565 #ifdef PNG_USE_LOCAL_ARRAYS
2566 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2567 /* offset to next interlace block */
2568 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2569 #endif
2571 png_debug(1, "in png_do_read_interlace\n");
2572 if (row != NULL && row_info != NULL)
2574 png_uint_32 final_width;
2576 final_width = row_info->width * png_pass_inc[pass];
2578 switch (row_info->pixel_depth)
2580 case 1:
2582 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2583 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2584 int sshift, dshift;
2585 int s_start, s_end, s_inc;
2586 int jstop = png_pass_inc[pass];
2587 png_byte v;
2588 png_uint_32 i;
2589 int j;
2591 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2592 if (transformations & PNG_PACKSWAP)
2594 sshift = (int)((row_info->width + 7) & 0x07);
2595 dshift = (int)((final_width + 7) & 0x07);
2596 s_start = 7;
2597 s_end = 0;
2598 s_inc = -1;
2600 else
2601 #endif
2603 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2604 dshift = 7 - (int)((final_width + 7) & 0x07);
2605 s_start = 0;
2606 s_end = 7;
2607 s_inc = 1;
2610 for (i = 0; i < row_info->width; i++)
2612 v = (png_byte)((*sp >> sshift) & 0x01);
2613 for (j = 0; j < jstop; j++)
2615 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2616 *dp |= (png_byte)(v << dshift);
2617 if (dshift == s_end)
2619 dshift = s_start;
2620 dp--;
2622 else
2623 dshift += s_inc;
2625 if (sshift == s_end)
2627 sshift = s_start;
2628 sp--;
2630 else
2631 sshift += s_inc;
2633 break;
2635 case 2:
2637 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2638 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2639 int sshift, dshift;
2640 int s_start, s_end, s_inc;
2641 int jstop = png_pass_inc[pass];
2642 png_uint_32 i;
2644 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2645 if (transformations & PNG_PACKSWAP)
2647 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2648 dshift = (int)(((final_width + 3) & 0x03) << 1);
2649 s_start = 6;
2650 s_end = 0;
2651 s_inc = -2;
2653 else
2654 #endif
2656 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2657 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2658 s_start = 0;
2659 s_end = 6;
2660 s_inc = 2;
2663 for (i = 0; i < row_info->width; i++)
2665 png_byte v;
2666 int j;
2668 v = (png_byte)((*sp >> sshift) & 0x03);
2669 for (j = 0; j < jstop; j++)
2671 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2672 *dp |= (png_byte)(v << dshift);
2673 if (dshift == s_end)
2675 dshift = s_start;
2676 dp--;
2678 else
2679 dshift += s_inc;
2681 if (sshift == s_end)
2683 sshift = s_start;
2684 sp--;
2686 else
2687 sshift += s_inc;
2689 break;
2691 case 4:
2693 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2694 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2695 int sshift, dshift;
2696 int s_start, s_end, s_inc;
2697 png_uint_32 i;
2698 int jstop = png_pass_inc[pass];
2700 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2701 if (transformations & PNG_PACKSWAP)
2703 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2704 dshift = (int)(((final_width + 1) & 0x01) << 2);
2705 s_start = 4;
2706 s_end = 0;
2707 s_inc = -4;
2709 else
2710 #endif
2712 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2713 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2714 s_start = 0;
2715 s_end = 4;
2716 s_inc = 4;
2719 for (i = 0; i < row_info->width; i++)
2721 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2722 int j;
2724 for (j = 0; j < jstop; j++)
2726 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2727 *dp |= (png_byte)(v << dshift);
2728 if (dshift == s_end)
2730 dshift = s_start;
2731 dp--;
2733 else
2734 dshift += s_inc;
2736 if (sshift == s_end)
2738 sshift = s_start;
2739 sp--;
2741 else
2742 sshift += s_inc;
2744 break;
2746 default:
2748 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2749 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2750 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2752 int jstop = png_pass_inc[pass];
2753 png_uint_32 i;
2755 for (i = 0; i < row_info->width; i++)
2757 png_byte v[8];
2758 int j;
2760 png_memcpy(v, sp, pixel_bytes);
2761 for (j = 0; j < jstop; j++)
2763 png_memcpy(dp, v, pixel_bytes);
2764 dp -= pixel_bytes;
2766 sp -= pixel_bytes;
2768 break;
2771 row_info->width = final_width;
2772 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
2774 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2775 transformations = transformations; /* silence compiler warning */
2776 #endif
2778 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2780 void /* PRIVATE */
2781 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2782 png_bytep prev_row, int filter)
2784 png_debug(1, "in png_read_filter_row\n");
2785 png_debug2(2, "row = %lu, filter = %d\n", png_ptr->row_number, filter);
2786 switch (filter)
2788 case PNG_FILTER_VALUE_NONE:
2789 break;
2790 case PNG_FILTER_VALUE_SUB:
2792 png_uint_32 i;
2793 png_uint_32 istop = row_info->rowbytes;
2794 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2795 png_bytep rp = row + bpp;
2796 png_bytep lp = row;
2798 for (i = bpp; i < istop; i++)
2800 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2801 rp++;
2803 break;
2805 case PNG_FILTER_VALUE_UP:
2807 png_uint_32 i;
2808 png_uint_32 istop = row_info->rowbytes;
2809 png_bytep rp = row;
2810 png_bytep pp = prev_row;
2812 for (i = 0; i < istop; i++)
2814 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2815 rp++;
2817 break;
2819 case PNG_FILTER_VALUE_AVG:
2821 png_uint_32 i;
2822 png_bytep rp = row;
2823 png_bytep pp = prev_row;
2824 png_bytep lp = row;
2825 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2826 png_uint_32 istop = row_info->rowbytes - bpp;
2828 for (i = 0; i < bpp; i++)
2830 *rp = (png_byte)(((int)(*rp) +
2831 ((int)(*pp++) / 2 )) & 0xff);
2832 rp++;
2835 for (i = 0; i < istop; i++)
2837 *rp = (png_byte)(((int)(*rp) +
2838 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2839 rp++;
2841 break;
2843 case PNG_FILTER_VALUE_PAETH:
2845 png_uint_32 i;
2846 png_bytep rp = row;
2847 png_bytep pp = prev_row;
2848 png_bytep lp = row;
2849 png_bytep cp = prev_row;
2850 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2851 png_uint_32 istop=row_info->rowbytes - bpp;
2853 for (i = 0; i < bpp; i++)
2855 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2856 rp++;
2859 for (i = 0; i < istop; i++) /* use leftover rp,pp */
2861 int a, b, c, pa, pb, pc, p;
2863 a = *lp++;
2864 b = *pp++;
2865 c = *cp++;
2867 p = b - c;
2868 pc = a - c;
2870 #ifdef PNG_USE_ABS
2871 pa = abs(p);
2872 pb = abs(pc);
2873 pc = abs(p + pc);
2874 #else
2875 pa = p < 0 ? -p : p;
2876 pb = pc < 0 ? -pc : pc;
2877 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2878 #endif
2880 /*
2881 if (pa <= pb && pa <= pc)
2882 p = a;
2883 else if (pb <= pc)
2884 p = b;
2885 else
2886 p = c;
2887 */
2889 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
2891 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2892 rp++;
2894 break;
2896 default:
2897 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2898 *row = 0;
2899 break;
2903 void /* PRIVATE */
2904 png_read_finish_row(png_structp png_ptr)
2906 #ifdef PNG_USE_LOCAL_ARRAYS
2907 #ifdef PNG_READ_INTERLACING_SUPPORTED
2908 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2910 /* start of interlace block */
2911 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2913 /* offset to next interlace block */
2914 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2916 /* start of interlace block in the y direction */
2917 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2919 /* offset to next interlace block in the y direction */
2920 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2921 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2922 #endif
2924 png_debug(1, "in png_read_finish_row\n");
2925 png_ptr->row_number++;
2926 if (png_ptr->row_number < png_ptr->num_rows)
2927 return;
2929 #ifdef PNG_READ_INTERLACING_SUPPORTED
2930 if (png_ptr->interlaced)
2932 png_ptr->row_number = 0;
2933 png_memset_check(png_ptr, png_ptr->prev_row, 0,
2934 png_ptr->rowbytes + 1);
2935 do
2937 png_ptr->pass++;
2938 if (png_ptr->pass >= 7)
2939 break;
2940 png_ptr->iwidth = (png_ptr->width +
2941 png_pass_inc[png_ptr->pass] - 1 -
2942 png_pass_start[png_ptr->pass]) /
2943 png_pass_inc[png_ptr->pass];
2945 png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
2946 png_ptr->iwidth) + 1;
2948 if (!(png_ptr->transformations & PNG_INTERLACE))
2950 png_ptr->num_rows = (png_ptr->height +
2951 png_pass_yinc[png_ptr->pass] - 1 -
2952 png_pass_ystart[png_ptr->pass]) /
2953 png_pass_yinc[png_ptr->pass];
2954 if (!(png_ptr->num_rows))
2955 continue;
2957 else /* if (png_ptr->transformations & PNG_INTERLACE) */
2958 break;
2959 } while (png_ptr->iwidth == 0);
2961 if (png_ptr->pass < 7)
2962 return;
2964 #endif /* PNG_READ_INTERLACING_SUPPORTED */
2966 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
2968 #ifdef PNG_USE_LOCAL_ARRAYS
2969 PNG_CONST PNG_IDAT;
2970 #endif
2971 char extra;
2972 int ret;
2974 png_ptr->zstream.next_out = (Byte *)&extra;
2975 png_ptr->zstream.avail_out = (uInt)1;
2976 for (;;)
2978 if (!(png_ptr->zstream.avail_in))
2980 while (!png_ptr->idat_size)
2982 png_byte chunk_length[4];
2984 png_crc_finish(png_ptr, 0);
2986 png_read_data(png_ptr, chunk_length, 4);
2987 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
2988 png_reset_crc(png_ptr);
2989 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2990 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
2991 png_error(png_ptr, "Not enough image data");
2994 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2995 png_ptr->zstream.next_in = png_ptr->zbuf;
2996 if (png_ptr->zbuf_size > png_ptr->idat_size)
2997 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2998 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2999 png_ptr->idat_size -= png_ptr->zstream.avail_in;
3001 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
3002 if (ret == Z_STREAM_END)
3004 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
3005 png_ptr->idat_size)
3006 png_warning(png_ptr, "Extra compressed data");
3007 png_ptr->mode |= PNG_AFTER_IDAT;
3008 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3009 break;
3011 if (ret != Z_OK)
3012 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
3013 "Decompression Error");
3015 if (!(png_ptr->zstream.avail_out))
3017 png_warning(png_ptr, "Extra compressed data.");
3018 png_ptr->mode |= PNG_AFTER_IDAT;
3019 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3020 break;
3024 png_ptr->zstream.avail_out = 0;
3027 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
3028 png_warning(png_ptr, "Extra compression data");
3030 inflateReset(&png_ptr->zstream);
3032 png_ptr->mode |= PNG_AFTER_IDAT;
3035 void /* PRIVATE */
3036 png_read_start_row(png_structp png_ptr)
3038 #ifdef PNG_USE_LOCAL_ARRAYS
3039 #ifdef PNG_READ_INTERLACING_SUPPORTED
3040 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3042 /* start of interlace block */
3043 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3045 /* offset to next interlace block */
3046 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3048 /* start of interlace block in the y direction */
3049 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3051 /* offset to next interlace block in the y direction */
3052 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3053 #endif
3054 #endif
3056 int max_pixel_depth;
3057 png_size_t row_bytes;
3059 png_debug(1, "in png_read_start_row\n");
3060 png_ptr->zstream.avail_in = 0;
3061 png_init_read_transformations(png_ptr);
3062 #ifdef PNG_READ_INTERLACING_SUPPORTED
3063 if (png_ptr->interlaced)
3065 if (!(png_ptr->transformations & PNG_INTERLACE))
3066 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
3067 png_pass_ystart[0]) / png_pass_yinc[0];
3068 else
3069 png_ptr->num_rows = png_ptr->height;
3071 png_ptr->iwidth = (png_ptr->width +
3072 png_pass_inc[png_ptr->pass] - 1 -
3073 png_pass_start[png_ptr->pass]) /
3074 png_pass_inc[png_ptr->pass];
3076 png_ptr->irowbytes =
3077 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1;
3079 else
3080 #endif /* PNG_READ_INTERLACING_SUPPORTED */
3082 png_ptr->num_rows = png_ptr->height;
3083 png_ptr->iwidth = png_ptr->width;
3084 png_ptr->irowbytes = png_ptr->rowbytes + 1;
3086 max_pixel_depth = png_ptr->pixel_depth;
3088 #if defined(PNG_READ_PACK_SUPPORTED)
3089 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
3090 max_pixel_depth = 8;
3091 #endif
3093 #if defined(PNG_READ_EXPAND_SUPPORTED)
3094 if (png_ptr->transformations & PNG_EXPAND)
3096 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3098 if (png_ptr->num_trans)
3099 max_pixel_depth = 32;
3100 else
3101 max_pixel_depth = 24;
3103 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3105 if (max_pixel_depth < 8)
3106 max_pixel_depth = 8;
3107 if (png_ptr->num_trans)
3108 max_pixel_depth *= 2;
3110 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3112 if (png_ptr->num_trans)
3114 max_pixel_depth *= 4;
3115 max_pixel_depth /= 3;
3119 #endif
3121 #if defined(PNG_READ_FILLER_SUPPORTED)
3122 if (png_ptr->transformations & (PNG_FILLER))
3124 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3125 max_pixel_depth = 32;
3126 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3128 if (max_pixel_depth <= 8)
3129 max_pixel_depth = 16;
3130 else
3131 max_pixel_depth = 32;
3133 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3135 if (max_pixel_depth <= 32)
3136 max_pixel_depth = 32;
3137 else
3138 max_pixel_depth = 64;
3141 #endif
3143 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
3144 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3146 if (
3147 #if defined(PNG_READ_EXPAND_SUPPORTED)
3148 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3149 #endif
3150 #if defined(PNG_READ_FILLER_SUPPORTED)
3151 (png_ptr->transformations & (PNG_FILLER)) ||
3152 #endif
3153 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3155 if (max_pixel_depth <= 16)
3156 max_pixel_depth = 32;
3157 else
3158 max_pixel_depth = 64;
3160 else
3162 if (max_pixel_depth <= 8)
3164 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3165 max_pixel_depth = 32;
3166 else
3167 max_pixel_depth = 24;
3169 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3170 max_pixel_depth = 64;
3171 else
3172 max_pixel_depth = 48;
3175 #endif
3177 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3178 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
3179 if (png_ptr->transformations & PNG_USER_TRANSFORM)
3181 int user_pixel_depth = png_ptr->user_transform_depth*
3182 png_ptr->user_transform_channels;
3183 if (user_pixel_depth > max_pixel_depth)
3184 max_pixel_depth=user_pixel_depth;
3186 #endif
3188 /* align the width on the next larger 8 pixels. Mainly used
3189 for interlacing */
3190 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
3191 /* calculate the maximum bytes needed, adding a byte and a pixel
3192 for safety's sake */
3193 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
3194 1 + ((max_pixel_depth + 7) >> 3);
3195 #ifdef PNG_MAX_MALLOC_64K
3196 if (row_bytes > (png_uint_32)65536L)
3197 png_error(png_ptr, "This image requires a row greater than 64KB");
3198 #endif
3200 if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
3202 png_free(png_ptr, png_ptr->big_row_buf);
3203 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
3204 png_ptr->row_buf = png_ptr->big_row_buf+32;
3205 png_ptr->old_big_row_buf_size = row_bytes+64;
3208 #ifdef PNG_MAX_MALLOC_64K
3209 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
3210 png_error(png_ptr, "This image requires a row greater than 64KB");
3211 #endif
3212 if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
3213 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
3215 if (png_ptr->rowbytes+1 > png_ptr->old_prev_row_size)
3217 png_free(png_ptr, png_ptr->prev_row);
3218 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3219 png_ptr->rowbytes + 1));
3220 png_ptr->old_prev_row_size = png_ptr->rowbytes+1;
3223 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
3225 png_debug1(3, "width = %lu,\n", png_ptr->width);
3226 png_debug1(3, "height = %lu,\n", png_ptr->height);
3227 png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
3228 png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
3229 png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
3230 png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
3232 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3234 #endif /* PNG_READ_SUPPORTED */