blob: 531cb0570eb59c75d94064ada7bc29d3505ec1e4 [file] [log] [blame]
The Android Open Source Project893912b2009-03-03 19:30:05 -08001
2/* pngrutil.c - utilities to read a PNG file
3 *
4 * Last changed in libpng 1.2.27 [April 29, 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 */
13
14#define PNG_INTERNAL
15#include "png.h"
16
17#if defined(PNG_READ_SUPPORTED)
18
19#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
20# define WIN32_WCE_OLD
21#endif
22
23#ifdef PNG_FLOATING_POINT_SUPPORTED
24# if defined(WIN32_WCE_OLD)
25/* strtod() function is not supported on WindowsCE */
26__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr)
27{
28 double result = 0;
29 int len;
30 wchar_t *str, *end;
31
32 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
33 str = (wchar_t *)png_malloc(png_ptr, len * sizeof(wchar_t));
34 if ( NULL != str )
35 {
36 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
37 result = wcstod(str, &end);
38 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
39 *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
40 png_free(png_ptr, str);
41 }
42 return result;
43}
44# else
45# define png_strtod(p,a,b) strtod(a,b)
46# endif
47#endif
48
49png_uint_32 PNGAPI
50png_get_uint_31(png_structp png_ptr, png_bytep buf)
51{
52 png_uint_32 i = png_get_uint_32(buf);
53 if (i > PNG_UINT_31_MAX)
54 png_error(png_ptr, "PNG unsigned integer out of range.");
55 return (i);
56}
57#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
58/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
59png_uint_32 PNGAPI
60png_get_uint_32(png_bytep buf)
61{
62 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
63 ((png_uint_32)(*(buf + 1)) << 16) +
64 ((png_uint_32)(*(buf + 2)) << 8) +
65 (png_uint_32)(*(buf + 3));
66
67 return (i);
68}
69
70/* Grab a signed 32-bit integer from a buffer in big-endian format. The
71 * data is stored in the PNG file in two's complement format, and it is
72 * assumed that the machine format for signed integers is the same. */
73png_int_32 PNGAPI
74png_get_int_32(png_bytep buf)
75{
76 png_int_32 i = ((png_int_32)(*buf) << 24) +
77 ((png_int_32)(*(buf + 1)) << 16) +
78 ((png_int_32)(*(buf + 2)) << 8) +
79 (png_int_32)(*(buf + 3));
80
81 return (i);
82}
83
84/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
85png_uint_16 PNGAPI
86png_get_uint_16(png_bytep buf)
87{
88 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
89 (png_uint_16)(*(buf + 1)));
90
91 return (i);
92}
93#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
94
95/* Read data, and (optionally) run it through the CRC. */
96void /* PRIVATE */
97png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
98{
99 if(png_ptr == NULL) return;
100 png_read_data(png_ptr, buf, length);
101 png_calculate_crc(png_ptr, buf, length);
102}
103
104/* Optionally skip data and then check the CRC. Depending on whether we
105 are reading a ancillary or critical chunk, and how the program has set
106 things up, we may calculate the CRC on the data and print a message.
107 Returns '1' if there was a CRC error, '0' otherwise. */
108int /* PRIVATE */
109png_crc_finish(png_structp png_ptr, png_uint_32 skip)
110{
111 png_size_t i;
112 png_size_t istop = png_ptr->zbuf_size;
113
114 for (i = (png_size_t)skip; i > istop; i -= istop)
115 {
116 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
117 }
118 if (i)
119 {
120 png_crc_read(png_ptr, png_ptr->zbuf, i);
121 }
122
123 if (png_crc_error(png_ptr))
124 {
125 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
126 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
127 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
128 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
129 {
130 png_chunk_warning(png_ptr, "CRC error");
131 }
132 else
133 {
134 png_chunk_error(png_ptr, "CRC error");
135 }
136 return (1);
137 }
138
139 return (0);
140}
141
142/* Compare the CRC stored in the PNG file with that calculated by libpng from
143 the data it has read thus far. */
144int /* PRIVATE */
145png_crc_error(png_structp png_ptr)
146{
147 png_byte crc_bytes[4];
148 png_uint_32 crc;
149 int need_crc = 1;
150
151 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
152 {
153 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
154 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
155 need_crc = 0;
156 }
157 else /* critical */
158 {
159 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
160 need_crc = 0;
161 }
162
163 png_read_data(png_ptr, crc_bytes, 4);
164
165 if (need_crc)
166 {
167 crc = png_get_uint_32(crc_bytes);
168 return ((int)(crc != png_ptr->crc));
169 }
170 else
171 return (0);
172}
173
174#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
175 defined(PNG_READ_iCCP_SUPPORTED)
176/*
177 * Decompress trailing data in a chunk. The assumption is that chunkdata
178 * points at an allocated area holding the contents of a chunk with a
179 * trailing compressed part. What we get back is an allocated area
180 * holding the original prefix part and an uncompressed version of the
181 * trailing part (the malloc area passed in is freed).
182 */
183png_charp /* PRIVATE */
184png_decompress_chunk(png_structp png_ptr, int comp_type,
185 png_charp chunkdata, png_size_t chunklength,
186 png_size_t prefix_size, png_size_t *newlength)
187{
188 static PNG_CONST char msg[] = "Error decoding compressed text";
189 png_charp text;
190 png_size_t text_size;
191
192 if (comp_type == PNG_COMPRESSION_TYPE_BASE)
193 {
194 int ret = Z_OK;
195 png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
196 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
197 png_ptr->zstream.next_out = png_ptr->zbuf;
198 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
199
200 text_size = 0;
201 text = NULL;
202
203 while (png_ptr->zstream.avail_in)
204 {
205 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
206 if (ret != Z_OK && ret != Z_STREAM_END)
207 {
208 if (png_ptr->zstream.msg != NULL)
209 png_warning(png_ptr, png_ptr->zstream.msg);
210 else
211 png_warning(png_ptr, msg);
212 inflateReset(&png_ptr->zstream);
213 png_ptr->zstream.avail_in = 0;
214
215 if (text == NULL)
216 {
217 text_size = prefix_size + png_sizeof(msg) + 1;
218 text = (png_charp)png_malloc_warn(png_ptr, text_size);
219 if (text == NULL)
220 {
221 png_free(png_ptr,chunkdata);
222 png_error(png_ptr,"Not enough memory to decompress chunk");
223 }
224 png_memcpy(text, chunkdata, prefix_size);
225 }
226
227 text[text_size - 1] = 0x00;
228
229 /* Copy what we can of the error message into the text chunk */
230 text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
231 text_size = png_sizeof(msg) > text_size ? text_size :
232 png_sizeof(msg);
233 png_memcpy(text + prefix_size, msg, text_size);
234 break;
235 }
236 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
237 {
238 if (text == NULL)
239 {
240 text_size = prefix_size +
241 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
242 text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
243 if (text == NULL)
244 {
245 png_free(png_ptr,chunkdata);
246 png_error(png_ptr,"Not enough memory to decompress chunk.");
247 }
248 png_memcpy(text + prefix_size, png_ptr->zbuf,
249 text_size - prefix_size);
250 png_memcpy(text, chunkdata, prefix_size);
251 *(text + text_size) = 0x00;
252 }
253 else
254 {
255 png_charp tmp;
256
257 tmp = text;
258 text = (png_charp)png_malloc_warn(png_ptr,
259 (png_uint_32)(text_size +
260 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
261 if (text == NULL)
262 {
263 png_free(png_ptr, tmp);
264 png_free(png_ptr, chunkdata);
265 png_error(png_ptr,"Not enough memory to decompress chunk..");
266 }
267 png_memcpy(text, tmp, text_size);
268 png_free(png_ptr, tmp);
269 png_memcpy(text + text_size, png_ptr->zbuf,
270 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
271 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
272 *(text + text_size) = 0x00;
273 }
274 if (ret == Z_STREAM_END)
275 break;
276 else
277 {
278 png_ptr->zstream.next_out = png_ptr->zbuf;
279 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
280 }
281 }
282 }
283 if (ret != Z_STREAM_END)
284 {
285#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
286 char umsg[52];
287
288 if (ret == Z_BUF_ERROR)
289 png_snprintf(umsg, 52,
290 "Buffer error in compressed datastream in %s chunk",
291 png_ptr->chunk_name);
292 else if (ret == Z_DATA_ERROR)
293 png_snprintf(umsg, 52,
294 "Data error in compressed datastream in %s chunk",
295 png_ptr->chunk_name);
296 else
297 png_snprintf(umsg, 52,
298 "Incomplete compressed datastream in %s chunk",
299 png_ptr->chunk_name);
300 png_warning(png_ptr, umsg);
301#else
302 png_warning(png_ptr,
303 "Incomplete compressed datastream in chunk other than IDAT");
304#endif
305 text_size=prefix_size;
306 if (text == NULL)
307 {
308 text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
309 if (text == NULL)
310 {
311 png_free(png_ptr, chunkdata);
312 png_error(png_ptr,"Not enough memory for text.");
313 }
314 png_memcpy(text, chunkdata, prefix_size);
315 }
316 *(text + text_size) = 0x00;
317 }
318
319 inflateReset(&png_ptr->zstream);
320 png_ptr->zstream.avail_in = 0;
321
322 png_free(png_ptr, chunkdata);
323 chunkdata = text;
324 *newlength=text_size;
325 }
326 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
327 {
328#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
329 char umsg[50];
330
331 png_snprintf(umsg, 50,
332 "Unknown zTXt compression type %d", comp_type);
333 png_warning(png_ptr, umsg);
334#else
335 png_warning(png_ptr, "Unknown zTXt compression type");
336#endif
337
338 *(chunkdata + prefix_size) = 0x00;
339 *newlength=prefix_size;
340 }
341
342 return chunkdata;
343}
344#endif
345
346/* read and check the IDHR chunk */
347void /* PRIVATE */
348png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
349{
350 png_byte buf[13];
351 png_uint_32 width, height;
352 int bit_depth, color_type, compression_type, filter_type;
353 int interlace_type;
354
355 png_debug(1, "in png_handle_IHDR\n");
356
357 if (png_ptr->mode & PNG_HAVE_IHDR)
358 png_error(png_ptr, "Out of place IHDR");
359
360 /* check the length */
361 if (length != 13)
362 png_error(png_ptr, "Invalid IHDR chunk");
363
364 png_ptr->mode |= PNG_HAVE_IHDR;
365
366 png_crc_read(png_ptr, buf, 13);
367 png_crc_finish(png_ptr, 0);
368
369 width = png_get_uint_31(png_ptr, buf);
370 height = png_get_uint_31(png_ptr, buf + 4);
371 bit_depth = buf[8];
372 color_type = buf[9];
373 compression_type = buf[10];
374 filter_type = buf[11];
375 interlace_type = buf[12];
376
377 /* set internal variables */
378 png_ptr->width = width;
379 png_ptr->height = height;
380 png_ptr->bit_depth = (png_byte)bit_depth;
381 png_ptr->interlaced = (png_byte)interlace_type;
382 png_ptr->color_type = (png_byte)color_type;
383#if defined(PNG_MNG_FEATURES_SUPPORTED)
384 png_ptr->filter_type = (png_byte)filter_type;
385#endif
386 png_ptr->compression_type = (png_byte)compression_type;
387
388 /* find number of channels */
389 switch (png_ptr->color_type)
390 {
391 case PNG_COLOR_TYPE_GRAY:
392 case PNG_COLOR_TYPE_PALETTE:
393 png_ptr->channels = 1;
394 break;
395 case PNG_COLOR_TYPE_RGB:
396 png_ptr->channels = 3;
397 break;
398 case PNG_COLOR_TYPE_GRAY_ALPHA:
399 png_ptr->channels = 2;
400 break;
401 case PNG_COLOR_TYPE_RGB_ALPHA:
402 png_ptr->channels = 4;
403 break;
404 }
405
406 /* set up other useful info */
407 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
408 png_ptr->channels);
409 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
410 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
411 png_debug1(3,"channels = %d\n", png_ptr->channels);
412 png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
413 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
414 color_type, interlace_type, compression_type, filter_type);
415}
416
417/* read and check the palette */
418void /* PRIVATE */
419png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
420{
421 png_color palette[PNG_MAX_PALETTE_LENGTH];
422 int num, i;
423#ifndef PNG_NO_POINTER_INDEXING
424 png_colorp pal_ptr;
425#endif
426
427 png_debug(1, "in png_handle_PLTE\n");
428
429 if (!(png_ptr->mode & PNG_HAVE_IHDR))
430 png_error(png_ptr, "Missing IHDR before PLTE");
431 else if (png_ptr->mode & PNG_HAVE_IDAT)
432 {
433 png_warning(png_ptr, "Invalid PLTE after IDAT");
434 png_crc_finish(png_ptr, length);
435 return;
436 }
437 else if (png_ptr->mode & PNG_HAVE_PLTE)
438 png_error(png_ptr, "Duplicate PLTE chunk");
439
440 png_ptr->mode |= PNG_HAVE_PLTE;
441
442 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
443 {
444 png_warning(png_ptr,
445 "Ignoring PLTE chunk in grayscale PNG");
446 png_crc_finish(png_ptr, length);
447 return;
448 }
449#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
450 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
451 {
452 png_crc_finish(png_ptr, length);
453 return;
454 }
455#endif
456
457 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
458 {
459 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
460 {
461 png_warning(png_ptr, "Invalid palette chunk");
462 png_crc_finish(png_ptr, length);
463 return;
464 }
465 else
466 {
467 png_error(png_ptr, "Invalid palette chunk");
468 }
469 }
470
471 num = (int)length / 3;
472
473#ifndef PNG_NO_POINTER_INDEXING
474 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
475 {
476 png_byte buf[3];
477
478 png_crc_read(png_ptr, buf, 3);
479 pal_ptr->red = buf[0];
480 pal_ptr->green = buf[1];
481 pal_ptr->blue = buf[2];
482 }
483#else
484 for (i = 0; i < num; i++)
485 {
486 png_byte buf[3];
487
488 png_crc_read(png_ptr, buf, 3);
489 /* don't depend upon png_color being any order */
490 palette[i].red = buf[0];
491 palette[i].green = buf[1];
492 palette[i].blue = buf[2];
493 }
494#endif
495
496 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
497 whatever the normal CRC configuration tells us. However, if we
498 have an RGB image, the PLTE can be considered ancillary, so
499 we will act as though it is. */
500#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
501 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
502#endif
503 {
504 png_crc_finish(png_ptr, 0);
505 }
506#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
507 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
508 {
509 /* If we don't want to use the data from an ancillary chunk,
510 we have two options: an error abort, or a warning and we
511 ignore the data in this chunk (which should be OK, since
512 it's considered ancillary for a RGB or RGBA image). */
513 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
514 {
515 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
516 {
517 png_chunk_error(png_ptr, "CRC error");
518 }
519 else
520 {
521 png_chunk_warning(png_ptr, "CRC error");
522 return;
523 }
524 }
525 /* Otherwise, we (optionally) emit a warning and use the chunk. */
526 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
527 {
528 png_chunk_warning(png_ptr, "CRC error");
529 }
530 }
531#endif
532
533 png_set_PLTE(png_ptr, info_ptr, palette, num);
534
535#if defined(PNG_READ_tRNS_SUPPORTED)
536 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
537 {
538 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
539 {
540 if (png_ptr->num_trans > (png_uint_16)num)
541 {
542 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
543 png_ptr->num_trans = (png_uint_16)num;
544 }
545 if (info_ptr->num_trans > (png_uint_16)num)
546 {
547 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
548 info_ptr->num_trans = (png_uint_16)num;
549 }
550 }
551 }
552#endif
553
554}
555
556void /* PRIVATE */
557png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
558{
559 png_debug(1, "in png_handle_IEND\n");
560
561 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
562 {
563 png_error(png_ptr, "No image in file");
564 }
565
566 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
567
568 if (length != 0)
569 {
570 png_warning(png_ptr, "Incorrect IEND chunk length");
571 }
572 png_crc_finish(png_ptr, length);
573
574 info_ptr =info_ptr; /* quiet compiler warnings about unused info_ptr */
575}
576
577#if defined(PNG_READ_gAMA_SUPPORTED)
578void /* PRIVATE */
579png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
580{
581 png_fixed_point igamma;
582#ifdef PNG_FLOATING_POINT_SUPPORTED
583 float file_gamma;
584#endif
585 png_byte buf[4];
586
587 png_debug(1, "in png_handle_gAMA\n");
588
589 if (!(png_ptr->mode & PNG_HAVE_IHDR))
590 png_error(png_ptr, "Missing IHDR before gAMA");
591 else if (png_ptr->mode & PNG_HAVE_IDAT)
592 {
593 png_warning(png_ptr, "Invalid gAMA after IDAT");
594 png_crc_finish(png_ptr, length);
595 return;
596 }
597 else if (png_ptr->mode & PNG_HAVE_PLTE)
598 /* Should be an error, but we can cope with it */
599 png_warning(png_ptr, "Out of place gAMA chunk");
600
601 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
602#if defined(PNG_READ_sRGB_SUPPORTED)
603 && !(info_ptr->valid & PNG_INFO_sRGB)
604#endif
605 )
606 {
607 png_warning(png_ptr, "Duplicate gAMA chunk");
608 png_crc_finish(png_ptr, length);
609 return;
610 }
611
612 if (length != 4)
613 {
614 png_warning(png_ptr, "Incorrect gAMA chunk length");
615 png_crc_finish(png_ptr, length);
616 return;
617 }
618
619 png_crc_read(png_ptr, buf, 4);
620 if (png_crc_finish(png_ptr, 0))
621 return;
622
623 igamma = (png_fixed_point)png_get_uint_32(buf);
624 /* check for zero gamma */
625 if (igamma == 0)
626 {
627 png_warning(png_ptr,
628 "Ignoring gAMA chunk with gamma=0");
629 return;
630 }
631
632#if defined(PNG_READ_sRGB_SUPPORTED)
633 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
634 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
635 {
636 png_warning(png_ptr,
637 "Ignoring incorrect gAMA value when sRGB is also present");
638#ifndef PNG_NO_CONSOLE_IO
639 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
640#endif
641 return;
642 }
643#endif /* PNG_READ_sRGB_SUPPORTED */
644
645#ifdef PNG_FLOATING_POINT_SUPPORTED
646 file_gamma = (float)igamma / (float)100000.0;
647# ifdef PNG_READ_GAMMA_SUPPORTED
648 png_ptr->gamma = file_gamma;
649# endif
650 png_set_gAMA(png_ptr, info_ptr, file_gamma);
651#endif
652#ifdef PNG_FIXED_POINT_SUPPORTED
653 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
654#endif
655}
656#endif
657
658#if defined(PNG_READ_sBIT_SUPPORTED)
659void /* PRIVATE */
660png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
661{
662 png_size_t truelen;
663 png_byte buf[4];
664
665 png_debug(1, "in png_handle_sBIT\n");
666
667 buf[0] = buf[1] = buf[2] = buf[3] = 0;
668
669 if (!(png_ptr->mode & PNG_HAVE_IHDR))
670 png_error(png_ptr, "Missing IHDR before sBIT");
671 else if (png_ptr->mode & PNG_HAVE_IDAT)
672 {
673 png_warning(png_ptr, "Invalid sBIT after IDAT");
674 png_crc_finish(png_ptr, length);
675 return;
676 }
677 else if (png_ptr->mode & PNG_HAVE_PLTE)
678 {
679 /* Should be an error, but we can cope with it */
680 png_warning(png_ptr, "Out of place sBIT chunk");
681 }
682 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
683 {
684 png_warning(png_ptr, "Duplicate sBIT chunk");
685 png_crc_finish(png_ptr, length);
686 return;
687 }
688
689 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
690 truelen = 3;
691 else
692 truelen = (png_size_t)png_ptr->channels;
693
694 if (length != truelen || length > 4)
695 {
696 png_warning(png_ptr, "Incorrect sBIT chunk length");
697 png_crc_finish(png_ptr, length);
698 return;
699 }
700
701 png_crc_read(png_ptr, buf, truelen);
702 if (png_crc_finish(png_ptr, 0))
703 return;
704
705 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
706 {
707 png_ptr->sig_bit.red = buf[0];
708 png_ptr->sig_bit.green = buf[1];
709 png_ptr->sig_bit.blue = buf[2];
710 png_ptr->sig_bit.alpha = buf[3];
711 }
712 else
713 {
714 png_ptr->sig_bit.gray = buf[0];
715 png_ptr->sig_bit.red = buf[0];
716 png_ptr->sig_bit.green = buf[0];
717 png_ptr->sig_bit.blue = buf[0];
718 png_ptr->sig_bit.alpha = buf[1];
719 }
720 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
721}
722#endif
723
724#if defined(PNG_READ_cHRM_SUPPORTED)
725void /* PRIVATE */
726png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
727{
728 png_byte buf[4];
729#ifdef PNG_FLOATING_POINT_SUPPORTED
730 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
731#endif
732 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
733 int_y_green, int_x_blue, int_y_blue;
734
735 png_uint_32 uint_x, uint_y;
736
737 png_debug(1, "in png_handle_cHRM\n");
738
739 if (!(png_ptr->mode & PNG_HAVE_IHDR))
740 png_error(png_ptr, "Missing IHDR before cHRM");
741 else if (png_ptr->mode & PNG_HAVE_IDAT)
742 {
743 png_warning(png_ptr, "Invalid cHRM after IDAT");
744 png_crc_finish(png_ptr, length);
745 return;
746 }
747 else if (png_ptr->mode & PNG_HAVE_PLTE)
748 /* Should be an error, but we can cope with it */
749 png_warning(png_ptr, "Missing PLTE before cHRM");
750
751 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
752#if defined(PNG_READ_sRGB_SUPPORTED)
753 && !(info_ptr->valid & PNG_INFO_sRGB)
754#endif
755 )
756 {
757 png_warning(png_ptr, "Duplicate cHRM chunk");
758 png_crc_finish(png_ptr, length);
759 return;
760 }
761
762 if (length != 32)
763 {
764 png_warning(png_ptr, "Incorrect cHRM chunk length");
765 png_crc_finish(png_ptr, length);
766 return;
767 }
768
769 png_crc_read(png_ptr, buf, 4);
770 uint_x = png_get_uint_32(buf);
771
772 png_crc_read(png_ptr, buf, 4);
773 uint_y = png_get_uint_32(buf);
774
775 if (uint_x > 80000L || uint_y > 80000L ||
776 uint_x + uint_y > 100000L)
777 {
778 png_warning(png_ptr, "Invalid cHRM white point");
779 png_crc_finish(png_ptr, 24);
780 return;
781 }
782 int_x_white = (png_fixed_point)uint_x;
783 int_y_white = (png_fixed_point)uint_y;
784
785 png_crc_read(png_ptr, buf, 4);
786 uint_x = png_get_uint_32(buf);
787
788 png_crc_read(png_ptr, buf, 4);
789 uint_y = png_get_uint_32(buf);
790
791 if (uint_x + uint_y > 100000L)
792 {
793 png_warning(png_ptr, "Invalid cHRM red point");
794 png_crc_finish(png_ptr, 16);
795 return;
796 }
797 int_x_red = (png_fixed_point)uint_x;
798 int_y_red = (png_fixed_point)uint_y;
799
800 png_crc_read(png_ptr, buf, 4);
801 uint_x = png_get_uint_32(buf);
802
803 png_crc_read(png_ptr, buf, 4);
804 uint_y = png_get_uint_32(buf);
805
806 if (uint_x + uint_y > 100000L)
807 {
808 png_warning(png_ptr, "Invalid cHRM green point");
809 png_crc_finish(png_ptr, 8);
810 return;
811 }
812 int_x_green = (png_fixed_point)uint_x;
813 int_y_green = (png_fixed_point)uint_y;
814
815 png_crc_read(png_ptr, buf, 4);
816 uint_x = png_get_uint_32(buf);
817
818 png_crc_read(png_ptr, buf, 4);
819 uint_y = png_get_uint_32(buf);
820
821 if (uint_x + uint_y > 100000L)
822 {
823 png_warning(png_ptr, "Invalid cHRM blue point");
824 png_crc_finish(png_ptr, 0);
825 return;
826 }
827 int_x_blue = (png_fixed_point)uint_x;
828 int_y_blue = (png_fixed_point)uint_y;
829
830#ifdef PNG_FLOATING_POINT_SUPPORTED
831 white_x = (float)int_x_white / (float)100000.0;
832 white_y = (float)int_y_white / (float)100000.0;
833 red_x = (float)int_x_red / (float)100000.0;
834 red_y = (float)int_y_red / (float)100000.0;
835 green_x = (float)int_x_green / (float)100000.0;
836 green_y = (float)int_y_green / (float)100000.0;
837 blue_x = (float)int_x_blue / (float)100000.0;
838 blue_y = (float)int_y_blue / (float)100000.0;
839#endif
840
841#if defined(PNG_READ_sRGB_SUPPORTED)
842 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
843 {
844 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
845 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
846 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
847 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
848 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
849 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
850 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
851 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
852 {
853 png_warning(png_ptr,
854 "Ignoring incorrect cHRM value when sRGB is also present");
855#ifndef PNG_NO_CONSOLE_IO
856#ifdef PNG_FLOATING_POINT_SUPPORTED
857 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
858 white_x, white_y, red_x, red_y);
859 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
860 green_x, green_y, blue_x, blue_y);
861#else
862 fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
863 int_x_white, int_y_white, int_x_red, int_y_red);
864 fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
865 int_x_green, int_y_green, int_x_blue, int_y_blue);
866#endif
867#endif /* PNG_NO_CONSOLE_IO */
868 }
869 png_crc_finish(png_ptr, 0);
870 return;
871 }
872#endif /* PNG_READ_sRGB_SUPPORTED */
873
874#ifdef PNG_FLOATING_POINT_SUPPORTED
875 png_set_cHRM(png_ptr, info_ptr,
876 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
877#endif
878#ifdef PNG_FIXED_POINT_SUPPORTED
879 png_set_cHRM_fixed(png_ptr, info_ptr,
880 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
881 int_y_green, int_x_blue, int_y_blue);
882#endif
883 if (png_crc_finish(png_ptr, 0))
884 return;
885}
886#endif
887
888#if defined(PNG_READ_sRGB_SUPPORTED)
889void /* PRIVATE */
890png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
891{
892 int intent;
893 png_byte buf[1];
894
895 png_debug(1, "in png_handle_sRGB\n");
896
897 if (!(png_ptr->mode & PNG_HAVE_IHDR))
898 png_error(png_ptr, "Missing IHDR before sRGB");
899 else if (png_ptr->mode & PNG_HAVE_IDAT)
900 {
901 png_warning(png_ptr, "Invalid sRGB after IDAT");
902 png_crc_finish(png_ptr, length);
903 return;
904 }
905 else if (png_ptr->mode & PNG_HAVE_PLTE)
906 /* Should be an error, but we can cope with it */
907 png_warning(png_ptr, "Out of place sRGB chunk");
908
909 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
910 {
911 png_warning(png_ptr, "Duplicate sRGB chunk");
912 png_crc_finish(png_ptr, length);
913 return;
914 }
915
916 if (length != 1)
917 {
918 png_warning(png_ptr, "Incorrect sRGB chunk length");
919 png_crc_finish(png_ptr, length);
920 return;
921 }
922
923 png_crc_read(png_ptr, buf, 1);
924 if (png_crc_finish(png_ptr, 0))
925 return;
926
927 intent = buf[0];
928 /* check for bad intent */
929 if (intent >= PNG_sRGB_INTENT_LAST)
930 {
931 png_warning(png_ptr, "Unknown sRGB intent");
932 return;
933 }
934
935#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
936 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
937 {
938 png_fixed_point igamma;
939#ifdef PNG_FIXED_POINT_SUPPORTED
940 igamma=info_ptr->int_gamma;
941#else
942# ifdef PNG_FLOATING_POINT_SUPPORTED
943 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
944# endif
945#endif
946 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
947 {
948 png_warning(png_ptr,
949 "Ignoring incorrect gAMA value when sRGB is also present");
950#ifndef PNG_NO_CONSOLE_IO
951# ifdef PNG_FIXED_POINT_SUPPORTED
952 fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
953# else
954# ifdef PNG_FLOATING_POINT_SUPPORTED
955 fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
956# endif
957# endif
958#endif
959 }
960 }
961#endif /* PNG_READ_gAMA_SUPPORTED */
962
963#ifdef PNG_READ_cHRM_SUPPORTED
964#ifdef PNG_FIXED_POINT_SUPPORTED
965 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
966 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
967 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
968 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
969 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
970 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
971 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
972 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
973 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
974 {
975 png_warning(png_ptr,
976 "Ignoring incorrect cHRM value when sRGB is also present");
977 }
978#endif /* PNG_FIXED_POINT_SUPPORTED */
979#endif /* PNG_READ_cHRM_SUPPORTED */
980
981 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
982}
983#endif /* PNG_READ_sRGB_SUPPORTED */
984
985#if defined(PNG_READ_iCCP_SUPPORTED)
986void /* PRIVATE */
987png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
988/* Note: this does not properly handle chunks that are > 64K under DOS */
989{
990 png_charp chunkdata;
991 png_byte compression_type;
992 png_bytep pC;
993 png_charp profile;
994 png_uint_32 skip = 0;
995 png_uint_32 profile_size, profile_length;
996 png_size_t slength, prefix_length, data_length;
997
998 png_debug(1, "in png_handle_iCCP\n");
999
1000 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1001 png_error(png_ptr, "Missing IHDR before iCCP");
1002 else if (png_ptr->mode & PNG_HAVE_IDAT)
1003 {
1004 png_warning(png_ptr, "Invalid iCCP after IDAT");
1005 png_crc_finish(png_ptr, length);
1006 return;
1007 }
1008 else if (png_ptr->mode & PNG_HAVE_PLTE)
1009 /* Should be an error, but we can cope with it */
1010 png_warning(png_ptr, "Out of place iCCP chunk");
1011
1012 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1013 {
1014 png_warning(png_ptr, "Duplicate iCCP chunk");
1015 png_crc_finish(png_ptr, length);
1016 return;
1017 }
1018
1019#ifdef PNG_MAX_MALLOC_64K
1020 if (length > (png_uint_32)65535L)
1021 {
1022 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1023 skip = length - (png_uint_32)65535L;
1024 length = (png_uint_32)65535L;
1025 }
1026#endif
1027
1028 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1029 slength = (png_size_t)length;
1030 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1031
1032 if (png_crc_finish(png_ptr, skip))
1033 {
1034 png_free(png_ptr, chunkdata);
1035 return;
1036 }
1037
1038 chunkdata[slength] = 0x00;
1039
1040 for (profile = chunkdata; *profile; profile++)
1041 /* empty loop to find end of name */ ;
1042
1043 ++profile;
1044
1045 /* there should be at least one zero (the compression type byte)
1046 following the separator, and we should be on it */
1047 if ( profile >= chunkdata + slength - 1)
1048 {
1049 png_free(png_ptr, chunkdata);
1050 png_warning(png_ptr, "Malformed iCCP chunk");
1051 return;
1052 }
1053
1054 /* compression_type should always be zero */
1055 compression_type = *profile++;
1056 if (compression_type)
1057 {
1058 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1059 compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1060 wrote nonzero) */
1061 }
1062
1063 prefix_length = profile - chunkdata;
1064 chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
1065 slength, prefix_length, &data_length);
1066
1067 profile_length = data_length - prefix_length;
1068
1069 if ( prefix_length > data_length || profile_length < 4)
1070 {
1071 png_free(png_ptr, chunkdata);
1072 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1073 return;
1074 }
1075
1076 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1077 pC = (png_bytep)(chunkdata+prefix_length);
1078 profile_size = ((*(pC ))<<24) |
1079 ((*(pC+1))<<16) |
1080 ((*(pC+2))<< 8) |
1081 ((*(pC+3)) );
1082
1083 if(profile_size < profile_length)
1084 profile_length = profile_size;
1085
1086 if(profile_size > profile_length)
1087 {
1088 png_free(png_ptr, chunkdata);
1089 png_warning(png_ptr, "Ignoring truncated iCCP profile.");
1090 return;
1091 }
1092
1093 png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
1094 chunkdata + prefix_length, profile_length);
1095 png_free(png_ptr, chunkdata);
1096}
1097#endif /* PNG_READ_iCCP_SUPPORTED */
1098
1099#if defined(PNG_READ_sPLT_SUPPORTED)
1100void /* PRIVATE */
1101png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1102/* Note: this does not properly handle chunks that are > 64K under DOS */
1103{
1104 png_bytep chunkdata;
1105 png_bytep entry_start;
1106 png_sPLT_t new_palette;
1107#ifdef PNG_NO_POINTER_INDEXING
1108 png_sPLT_entryp pp;
1109#endif
1110 int data_length, entry_size, i;
1111 png_uint_32 skip = 0;
1112 png_size_t slength;
1113
1114 png_debug(1, "in png_handle_sPLT\n");
1115
1116 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1117 png_error(png_ptr, "Missing IHDR before sPLT");
1118 else if (png_ptr->mode & PNG_HAVE_IDAT)
1119 {
1120 png_warning(png_ptr, "Invalid sPLT after IDAT");
1121 png_crc_finish(png_ptr, length);
1122 return;
1123 }
1124
1125#ifdef PNG_MAX_MALLOC_64K
1126 if (length > (png_uint_32)65535L)
1127 {
1128 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1129 skip = length - (png_uint_32)65535L;
1130 length = (png_uint_32)65535L;
1131 }
1132#endif
1133
1134 chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
1135 slength = (png_size_t)length;
1136 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1137
1138 if (png_crc_finish(png_ptr, skip))
1139 {
1140 png_free(png_ptr, chunkdata);
1141 return;
1142 }
1143
1144 chunkdata[slength] = 0x00;
1145
1146 for (entry_start = chunkdata; *entry_start; entry_start++)
1147 /* empty loop to find end of name */ ;
1148 ++entry_start;
1149
1150 /* a sample depth should follow the separator, and we should be on it */
1151 if (entry_start > chunkdata + slength - 2)
1152 {
1153 png_free(png_ptr, chunkdata);
1154 png_warning(png_ptr, "malformed sPLT chunk");
1155 return;
1156 }
1157
1158 new_palette.depth = *entry_start++;
1159 entry_size = (new_palette.depth == 8 ? 6 : 10);
1160 data_length = (slength - (entry_start - chunkdata));
1161
1162 /* integrity-check the data length */
1163 if (data_length % entry_size)
1164 {
1165 png_free(png_ptr, chunkdata);
1166 png_warning(png_ptr, "sPLT chunk has bad length");
1167 return;
1168 }
1169
1170 new_palette.nentries = (png_int_32) ( data_length / entry_size);
1171 if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX /
1172 png_sizeof(png_sPLT_entry)))
1173 {
1174 png_warning(png_ptr, "sPLT chunk too long");
1175 return;
1176 }
1177 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1178 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1179 if (new_palette.entries == NULL)
1180 {
1181 png_warning(png_ptr, "sPLT chunk requires too much memory");
1182 return;
1183 }
1184
1185#ifndef PNG_NO_POINTER_INDEXING
1186 for (i = 0; i < new_palette.nentries; i++)
1187 {
1188 png_sPLT_entryp pp = new_palette.entries + i;
1189
1190 if (new_palette.depth == 8)
1191 {
1192 pp->red = *entry_start++;
1193 pp->green = *entry_start++;
1194 pp->blue = *entry_start++;
1195 pp->alpha = *entry_start++;
1196 }
1197 else
1198 {
1199 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1200 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1201 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1202 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1203 }
1204 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1205 }
1206#else
1207 pp = new_palette.entries;
1208 for (i = 0; i < new_palette.nentries; i++)
1209 {
1210
1211 if (new_palette.depth == 8)
1212 {
1213 pp[i].red = *entry_start++;
1214 pp[i].green = *entry_start++;
1215 pp[i].blue = *entry_start++;
1216 pp[i].alpha = *entry_start++;
1217 }
1218 else
1219 {
1220 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1221 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1222 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1223 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1224 }
1225 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1226 }
1227#endif
1228
1229 /* discard all chunk data except the name and stash that */
1230 new_palette.name = (png_charp)chunkdata;
1231
1232 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1233
1234 png_free(png_ptr, chunkdata);
1235 png_free(png_ptr, new_palette.entries);
1236}
1237#endif /* PNG_READ_sPLT_SUPPORTED */
1238
1239#if defined(PNG_READ_tRNS_SUPPORTED)
1240void /* PRIVATE */
1241png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1242{
1243 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1244
1245 png_debug(1, "in png_handle_tRNS\n");
1246
1247 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1248 png_error(png_ptr, "Missing IHDR before tRNS");
1249 else if (png_ptr->mode & PNG_HAVE_IDAT)
1250 {
1251 png_warning(png_ptr, "Invalid tRNS after IDAT");
1252 png_crc_finish(png_ptr, length);
1253 return;
1254 }
1255 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1256 {
1257 png_warning(png_ptr, "Duplicate tRNS chunk");
1258 png_crc_finish(png_ptr, length);
1259 return;
1260 }
1261
1262 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1263 {
1264 png_byte buf[2];
1265
1266 if (length != 2)
1267 {
1268 png_warning(png_ptr, "Incorrect tRNS chunk length");
1269 png_crc_finish(png_ptr, length);
1270 return;
1271 }
1272
1273 png_crc_read(png_ptr, buf, 2);
1274 png_ptr->num_trans = 1;
1275 png_ptr->trans_values.gray = png_get_uint_16(buf);
1276 }
1277 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1278 {
1279 png_byte buf[6];
1280
1281 if (length != 6)
1282 {
1283 png_warning(png_ptr, "Incorrect tRNS chunk length");
1284 png_crc_finish(png_ptr, length);
1285 return;
1286 }
1287 png_crc_read(png_ptr, buf, (png_size_t)length);
1288 png_ptr->num_trans = 1;
1289 png_ptr->trans_values.red = png_get_uint_16(buf);
1290 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1291 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1292 }
1293 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1294 {
1295 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1296 {
1297 /* Should be an error, but we can cope with it. */
1298 png_warning(png_ptr, "Missing PLTE before tRNS");
1299 }
1300 if (length > (png_uint_32)png_ptr->num_palette ||
1301 length > PNG_MAX_PALETTE_LENGTH)
1302 {
1303 png_warning(png_ptr, "Incorrect tRNS chunk length");
1304 png_crc_finish(png_ptr, length);
1305 return;
1306 }
1307 if (length == 0)
1308 {
1309 png_warning(png_ptr, "Zero length tRNS chunk");
1310 png_crc_finish(png_ptr, length);
1311 return;
1312 }
1313 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1314 png_ptr->num_trans = (png_uint_16)length;
1315 }
1316 else
1317 {
1318 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1319 png_crc_finish(png_ptr, length);
1320 return;
1321 }
1322
1323 if (png_crc_finish(png_ptr, 0))
1324 {
1325 png_ptr->num_trans = 0;
1326 return;
1327 }
1328
1329 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1330 &(png_ptr->trans_values));
1331}
1332#endif
1333
1334#if defined(PNG_READ_bKGD_SUPPORTED)
1335void /* PRIVATE */
1336png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1337{
1338 png_size_t truelen;
1339 png_byte buf[6];
1340
1341 png_debug(1, "in png_handle_bKGD\n");
1342
1343 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1344 png_error(png_ptr, "Missing IHDR before bKGD");
1345 else if (png_ptr->mode & PNG_HAVE_IDAT)
1346 {
1347 png_warning(png_ptr, "Invalid bKGD after IDAT");
1348 png_crc_finish(png_ptr, length);
1349 return;
1350 }
1351 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1352 !(png_ptr->mode & PNG_HAVE_PLTE))
1353 {
1354 png_warning(png_ptr, "Missing PLTE before bKGD");
1355 png_crc_finish(png_ptr, length);
1356 return;
1357 }
1358 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1359 {
1360 png_warning(png_ptr, "Duplicate bKGD chunk");
1361 png_crc_finish(png_ptr, length);
1362 return;
1363 }
1364
1365 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1366 truelen = 1;
1367 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1368 truelen = 6;
1369 else
1370 truelen = 2;
1371
1372 if (length != truelen)
1373 {
1374 png_warning(png_ptr, "Incorrect bKGD chunk length");
1375 png_crc_finish(png_ptr, length);
1376 return;
1377 }
1378
1379 png_crc_read(png_ptr, buf, truelen);
1380 if (png_crc_finish(png_ptr, 0))
1381 return;
1382
1383 /* We convert the index value into RGB components so that we can allow
1384 * arbitrary RGB values for background when we have transparency, and
1385 * so it is easy to determine the RGB values of the background color
1386 * from the info_ptr struct. */
1387 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1388 {
1389 png_ptr->background.index = buf[0];
1390 if (info_ptr && info_ptr->num_palette)
1391 {
1392 if(buf[0] > info_ptr->num_palette)
1393 {
1394 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1395 return;
1396 }
1397 png_ptr->background.red =
1398 (png_uint_16)png_ptr->palette[buf[0]].red;
1399 png_ptr->background.green =
1400 (png_uint_16)png_ptr->palette[buf[0]].green;
1401 png_ptr->background.blue =
1402 (png_uint_16)png_ptr->palette[buf[0]].blue;
1403 }
1404 }
1405 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1406 {
1407 png_ptr->background.red =
1408 png_ptr->background.green =
1409 png_ptr->background.blue =
1410 png_ptr->background.gray = png_get_uint_16(buf);
1411 }
1412 else
1413 {
1414 png_ptr->background.red = png_get_uint_16(buf);
1415 png_ptr->background.green = png_get_uint_16(buf + 2);
1416 png_ptr->background.blue = png_get_uint_16(buf + 4);
1417 }
1418
1419 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1420}
1421#endif
1422
1423#if defined(PNG_READ_hIST_SUPPORTED)
1424void /* PRIVATE */
1425png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1426{
1427 unsigned int num, i;
1428 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1429
1430 png_debug(1, "in png_handle_hIST\n");
1431
1432 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1433 png_error(png_ptr, "Missing IHDR before hIST");
1434 else if (png_ptr->mode & PNG_HAVE_IDAT)
1435 {
1436 png_warning(png_ptr, "Invalid hIST after IDAT");
1437 png_crc_finish(png_ptr, length);
1438 return;
1439 }
1440 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1441 {
1442 png_warning(png_ptr, "Missing PLTE before hIST");
1443 png_crc_finish(png_ptr, length);
1444 return;
1445 }
1446 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1447 {
1448 png_warning(png_ptr, "Duplicate hIST chunk");
1449 png_crc_finish(png_ptr, length);
1450 return;
1451 }
1452
1453 num = length / 2 ;
1454 if (num != (unsigned int) png_ptr->num_palette || num >
1455 (unsigned int) PNG_MAX_PALETTE_LENGTH)
1456 {
1457 png_warning(png_ptr, "Incorrect hIST chunk length");
1458 png_crc_finish(png_ptr, length);
1459 return;
1460 }
1461
1462 for (i = 0; i < num; i++)
1463 {
1464 png_byte buf[2];
1465
1466 png_crc_read(png_ptr, buf, 2);
1467 readbuf[i] = png_get_uint_16(buf);
1468 }
1469
1470 if (png_crc_finish(png_ptr, 0))
1471 return;
1472
1473 png_set_hIST(png_ptr, info_ptr, readbuf);
1474}
1475#endif
1476
1477#if defined(PNG_READ_pHYs_SUPPORTED)
1478void /* PRIVATE */
1479png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1480{
1481 png_byte buf[9];
1482 png_uint_32 res_x, res_y;
1483 int unit_type;
1484
1485 png_debug(1, "in png_handle_pHYs\n");
1486
1487 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1488 png_error(png_ptr, "Missing IHDR before pHYs");
1489 else if (png_ptr->mode & PNG_HAVE_IDAT)
1490 {
1491 png_warning(png_ptr, "Invalid pHYs after IDAT");
1492 png_crc_finish(png_ptr, length);
1493 return;
1494 }
1495 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1496 {
1497 png_warning(png_ptr, "Duplicate pHYs chunk");
1498 png_crc_finish(png_ptr, length);
1499 return;
1500 }
1501
1502 if (length != 9)
1503 {
1504 png_warning(png_ptr, "Incorrect pHYs chunk length");
1505 png_crc_finish(png_ptr, length);
1506 return;
1507 }
1508
1509 png_crc_read(png_ptr, buf, 9);
1510 if (png_crc_finish(png_ptr, 0))
1511 return;
1512
1513 res_x = png_get_uint_32(buf);
1514 res_y = png_get_uint_32(buf + 4);
1515 unit_type = buf[8];
1516 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1517}
1518#endif
1519
1520#if defined(PNG_READ_oFFs_SUPPORTED)
1521void /* PRIVATE */
1522png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1523{
1524 png_byte buf[9];
1525 png_int_32 offset_x, offset_y;
1526 int unit_type;
1527
1528 png_debug(1, "in png_handle_oFFs\n");
1529
1530 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1531 png_error(png_ptr, "Missing IHDR before oFFs");
1532 else if (png_ptr->mode & PNG_HAVE_IDAT)
1533 {
1534 png_warning(png_ptr, "Invalid oFFs after IDAT");
1535 png_crc_finish(png_ptr, length);
1536 return;
1537 }
1538 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1539 {
1540 png_warning(png_ptr, "Duplicate oFFs chunk");
1541 png_crc_finish(png_ptr, length);
1542 return;
1543 }
1544
1545 if (length != 9)
1546 {
1547 png_warning(png_ptr, "Incorrect oFFs chunk length");
1548 png_crc_finish(png_ptr, length);
1549 return;
1550 }
1551
1552 png_crc_read(png_ptr, buf, 9);
1553 if (png_crc_finish(png_ptr, 0))
1554 return;
1555
1556 offset_x = png_get_int_32(buf);
1557 offset_y = png_get_int_32(buf + 4);
1558 unit_type = buf[8];
1559 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1560}
1561#endif
1562
1563#if defined(PNG_READ_pCAL_SUPPORTED)
1564/* read the pCAL chunk (described in the PNG Extensions document) */
1565void /* PRIVATE */
1566png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1567{
1568 png_charp purpose;
1569 png_int_32 X0, X1;
1570 png_byte type, nparams;
1571 png_charp buf, units, endptr;
1572 png_charpp params;
1573 png_size_t slength;
1574 int i;
1575
1576 png_debug(1, "in png_handle_pCAL\n");
1577
1578 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1579 png_error(png_ptr, "Missing IHDR before pCAL");
1580 else if (png_ptr->mode & PNG_HAVE_IDAT)
1581 {
1582 png_warning(png_ptr, "Invalid pCAL after IDAT");
1583 png_crc_finish(png_ptr, length);
1584 return;
1585 }
1586 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1587 {
1588 png_warning(png_ptr, "Duplicate pCAL chunk");
1589 png_crc_finish(png_ptr, length);
1590 return;
1591 }
1592
1593 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
1594 length + 1);
1595 purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
1596 if (purpose == NULL)
1597 {
1598 png_warning(png_ptr, "No memory for pCAL purpose.");
1599 return;
1600 }
1601 slength = (png_size_t)length;
1602 png_crc_read(png_ptr, (png_bytep)purpose, slength);
1603
1604 if (png_crc_finish(png_ptr, 0))
1605 {
1606 png_free(png_ptr, purpose);
1607 return;
1608 }
1609
1610 purpose[slength] = 0x00; /* null terminate the last string */
1611
1612 png_debug(3, "Finding end of pCAL purpose string\n");
1613 for (buf = purpose; *buf; buf++)
1614 /* empty loop */ ;
1615
1616 endptr = purpose + slength;
1617
1618 /* We need to have at least 12 bytes after the purpose string
1619 in order to get the parameter information. */
1620 if (endptr <= buf + 12)
1621 {
1622 png_warning(png_ptr, "Invalid pCAL data");
1623 png_free(png_ptr, purpose);
1624 return;
1625 }
1626
1627 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1628 X0 = png_get_int_32((png_bytep)buf+1);
1629 X1 = png_get_int_32((png_bytep)buf+5);
1630 type = buf[9];
1631 nparams = buf[10];
1632 units = buf + 11;
1633
1634 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1635 /* Check that we have the right number of parameters for known
1636 equation types. */
1637 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1638 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1639 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1640 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1641 {
1642 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1643 png_free(png_ptr, purpose);
1644 return;
1645 }
1646 else if (type >= PNG_EQUATION_LAST)
1647 {
1648 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1649 }
1650
1651 for (buf = units; *buf; buf++)
1652 /* Empty loop to move past the units string. */ ;
1653
1654 png_debug(3, "Allocating pCAL parameters array\n");
1655 params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
1656 *png_sizeof(png_charp))) ;
1657 if (params == NULL)
1658 {
1659 png_free(png_ptr, purpose);
1660 png_warning(png_ptr, "No memory for pCAL params.");
1661 return;
1662 }
1663
1664 /* Get pointers to the start of each parameter string. */
1665 for (i = 0; i < (int)nparams; i++)
1666 {
1667 buf++; /* Skip the null string terminator from previous parameter. */
1668
1669 png_debug1(3, "Reading pCAL parameter %d\n", i);
1670 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
1671 /* Empty loop to move past each parameter string */ ;
1672
1673 /* Make sure we haven't run out of data yet */
1674 if (buf > endptr)
1675 {
1676 png_warning(png_ptr, "Invalid pCAL data");
1677 png_free(png_ptr, purpose);
1678 png_free(png_ptr, params);
1679 return;
1680 }
1681 }
1682
1683 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1684 units, params);
1685
1686 png_free(png_ptr, purpose);
1687 png_free(png_ptr, params);
1688}
1689#endif
1690
1691#if defined(PNG_READ_sCAL_SUPPORTED)
1692/* read the sCAL chunk */
1693void /* PRIVATE */
1694png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1695{
1696 png_charp buffer, ep;
1697#ifdef PNG_FLOATING_POINT_SUPPORTED
1698 double width, height;
1699 png_charp vp;
1700#else
1701#ifdef PNG_FIXED_POINT_SUPPORTED
1702 png_charp swidth, sheight;
1703#endif
1704#endif
1705 png_size_t slength;
1706
1707 png_debug(1, "in png_handle_sCAL\n");
1708
1709 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1710 png_error(png_ptr, "Missing IHDR before sCAL");
1711 else if (png_ptr->mode & PNG_HAVE_IDAT)
1712 {
1713 png_warning(png_ptr, "Invalid sCAL after IDAT");
1714 png_crc_finish(png_ptr, length);
1715 return;
1716 }
1717 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1718 {
1719 png_warning(png_ptr, "Duplicate sCAL chunk");
1720 png_crc_finish(png_ptr, length);
1721 return;
1722 }
1723
1724 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1725 length + 1);
1726 buffer = (png_charp)png_malloc_warn(png_ptr, length + 1);
1727 if (buffer == NULL)
1728 {
1729 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
1730 return;
1731 }
1732 slength = (png_size_t)length;
1733 png_crc_read(png_ptr, (png_bytep)buffer, slength);
1734
1735 if (png_crc_finish(png_ptr, 0))
1736 {
1737 png_free(png_ptr, buffer);
1738 return;
1739 }
1740
1741 buffer[slength] = 0x00; /* null terminate the last string */
1742
1743 ep = buffer + 1; /* skip unit byte */
1744
1745#ifdef PNG_FLOATING_POINT_SUPPORTED
1746 width = png_strtod(png_ptr, ep, &vp);
1747 if (*vp)
1748 {
1749 png_warning(png_ptr, "malformed width string in sCAL chunk");
1750 return;
1751 }
1752#else
1753#ifdef PNG_FIXED_POINT_SUPPORTED
1754 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1755 if (swidth == NULL)
1756 {
1757 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
1758 return;
1759 }
1760 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1761#endif
1762#endif
1763
1764 for (ep = buffer; *ep; ep++)
1765 /* empty loop */ ;
1766 ep++;
1767
1768 if (buffer + slength < ep)
1769 {
1770 png_warning(png_ptr, "Truncated sCAL chunk");
1771#if defined(PNG_FIXED_POINT_SUPPORTED) && \
1772 !defined(PNG_FLOATING_POINT_SUPPORTED)
1773 png_free(png_ptr, swidth);
1774#endif
1775 png_free(png_ptr, buffer);
1776 return;
1777 }
1778
1779#ifdef PNG_FLOATING_POINT_SUPPORTED
1780 height = png_strtod(png_ptr, ep, &vp);
1781 if (*vp)
1782 {
1783 png_warning(png_ptr, "malformed height string in sCAL chunk");
1784 return;
1785 }
1786#else
1787#ifdef PNG_FIXED_POINT_SUPPORTED
1788 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1789 if (sheight == NULL)
1790 {
1791 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
1792 return;
1793 }
1794 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1795#endif
1796#endif
1797
1798 if (buffer + slength < ep
1799#ifdef PNG_FLOATING_POINT_SUPPORTED
1800 || width <= 0. || height <= 0.
1801#endif
1802 )
1803 {
1804 png_warning(png_ptr, "Invalid sCAL data");
1805 png_free(png_ptr, buffer);
1806#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1807 png_free(png_ptr, swidth);
1808 png_free(png_ptr, sheight);
1809#endif
1810 return;
1811 }
1812
1813
1814#ifdef PNG_FLOATING_POINT_SUPPORTED
1815 png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1816#else
1817#ifdef PNG_FIXED_POINT_SUPPORTED
1818 png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1819#endif
1820#endif
1821
1822 png_free(png_ptr, buffer);
1823#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1824 png_free(png_ptr, swidth);
1825 png_free(png_ptr, sheight);
1826#endif
1827}
1828#endif
1829
1830#if defined(PNG_READ_tIME_SUPPORTED)
1831void /* PRIVATE */
1832png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1833{
1834 png_byte buf[7];
1835 png_time mod_time;
1836
1837 png_debug(1, "in png_handle_tIME\n");
1838
1839 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1840 png_error(png_ptr, "Out of place tIME chunk");
1841 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1842 {
1843 png_warning(png_ptr, "Duplicate tIME chunk");
1844 png_crc_finish(png_ptr, length);
1845 return;
1846 }
1847
1848 if (png_ptr->mode & PNG_HAVE_IDAT)
1849 png_ptr->mode |= PNG_AFTER_IDAT;
1850
1851 if (length != 7)
1852 {
1853 png_warning(png_ptr, "Incorrect tIME chunk length");
1854 png_crc_finish(png_ptr, length);
1855 return;
1856 }
1857
1858 png_crc_read(png_ptr, buf, 7);
1859 if (png_crc_finish(png_ptr, 0))
1860 return;
1861
1862 mod_time.second = buf[6];
1863 mod_time.minute = buf[5];
1864 mod_time.hour = buf[4];
1865 mod_time.day = buf[3];
1866 mod_time.month = buf[2];
1867 mod_time.year = png_get_uint_16(buf);
1868
1869 png_set_tIME(png_ptr, info_ptr, &mod_time);
1870}
1871#endif
1872
1873#if defined(PNG_READ_tEXt_SUPPORTED)
1874/* Note: this does not properly handle chunks that are > 64K under DOS */
1875void /* PRIVATE */
1876png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1877{
1878 png_textp text_ptr;
1879 png_charp key;
1880 png_charp text;
1881 png_uint_32 skip = 0;
1882 png_size_t slength;
1883 int ret;
1884
1885 png_debug(1, "in png_handle_tEXt\n");
1886
1887 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1888 png_error(png_ptr, "Missing IHDR before tEXt");
1889
1890 if (png_ptr->mode & PNG_HAVE_IDAT)
1891 png_ptr->mode |= PNG_AFTER_IDAT;
1892
1893#ifdef PNG_MAX_MALLOC_64K
1894 if (length > (png_uint_32)65535L)
1895 {
1896 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1897 skip = length - (png_uint_32)65535L;
1898 length = (png_uint_32)65535L;
1899 }
1900#endif
1901
1902 key = (png_charp)png_malloc_warn(png_ptr, length + 1);
1903 if (key == NULL)
1904 {
1905 png_warning(png_ptr, "No memory to process text chunk.");
1906 return;
1907 }
1908 slength = (png_size_t)length;
1909 png_crc_read(png_ptr, (png_bytep)key, slength);
1910
1911 if (png_crc_finish(png_ptr, skip))
1912 {
1913 png_free(png_ptr, key);
1914 return;
1915 }
1916
1917 key[slength] = 0x00;
1918
1919 for (text = key; *text; text++)
1920 /* empty loop to find end of key */ ;
1921
1922 if (text != key + slength)
1923 text++;
1924
1925 text_ptr = (png_textp)png_malloc_warn(png_ptr,
1926 (png_uint_32)png_sizeof(png_text));
1927 if (text_ptr == NULL)
1928 {
1929 png_warning(png_ptr, "Not enough memory to process text chunk.");
1930 png_free(png_ptr, key);
1931 return;
1932 }
1933 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1934 text_ptr->key = key;
1935#ifdef PNG_iTXt_SUPPORTED
1936 text_ptr->lang = NULL;
1937 text_ptr->lang_key = NULL;
1938 text_ptr->itxt_length = 0;
1939#endif
1940 text_ptr->text = text;
1941 text_ptr->text_length = png_strlen(text);
1942
1943 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
1944
1945 png_free(png_ptr, key);
1946 png_free(png_ptr, text_ptr);
1947 if (ret)
1948 png_warning(png_ptr, "Insufficient memory to process text chunk.");
1949}
1950#endif
1951
1952#if defined(PNG_READ_zTXt_SUPPORTED)
1953/* note: this does not correctly handle chunks that are > 64K under DOS */
1954void /* PRIVATE */
1955png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1956{
1957 png_textp text_ptr;
1958 png_charp chunkdata;
1959 png_charp text;
1960 int comp_type;
1961 int ret;
1962 png_size_t slength, prefix_len, data_len;
1963
1964 png_debug(1, "in png_handle_zTXt\n");
1965 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1966 png_error(png_ptr, "Missing IHDR before zTXt");
1967
1968 if (png_ptr->mode & PNG_HAVE_IDAT)
1969 png_ptr->mode |= PNG_AFTER_IDAT;
1970
1971#ifdef PNG_MAX_MALLOC_64K
1972 /* We will no doubt have problems with chunks even half this size, but
1973 there is no hard and fast rule to tell us where to stop. */
1974 if (length > (png_uint_32)65535L)
1975 {
1976 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1977 png_crc_finish(png_ptr, length);
1978 return;
1979 }
1980#endif
1981
1982 chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1983 if (chunkdata == NULL)
1984 {
1985 png_warning(png_ptr,"Out of memory processing zTXt chunk.");
1986 return;
1987 }
1988 slength = (png_size_t)length;
1989 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1990 if (png_crc_finish(png_ptr, 0))
1991 {
1992 png_free(png_ptr, chunkdata);
1993 return;
1994 }
1995
1996 chunkdata[slength] = 0x00;
1997
1998 for (text = chunkdata; *text; text++)
1999 /* empty loop */ ;
2000
2001 /* zTXt must have some text after the chunkdataword */
2002 if (text >= chunkdata + slength - 2)
2003 {
2004 png_warning(png_ptr, "Truncated zTXt chunk");
2005 png_free(png_ptr, chunkdata);
2006 return;
2007 }
2008 else
2009 {
2010 comp_type = *(++text);
2011 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2012 {
2013 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2014 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2015 }
2016 text++; /* skip the compression_method byte */
2017 }
2018 prefix_len = text - chunkdata;
2019
2020 chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
2021 (png_size_t)length, prefix_len, &data_len);
2022
2023 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2024 (png_uint_32)png_sizeof(png_text));
2025 if (text_ptr == NULL)
2026 {
2027 png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
2028 png_free(png_ptr, chunkdata);
2029 return;
2030 }
2031 text_ptr->compression = comp_type;
2032 text_ptr->key = chunkdata;
2033#ifdef PNG_iTXt_SUPPORTED
2034 text_ptr->lang = NULL;
2035 text_ptr->lang_key = NULL;
2036 text_ptr->itxt_length = 0;
2037#endif
2038 text_ptr->text = chunkdata + prefix_len;
2039 text_ptr->text_length = data_len;
2040
2041 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2042
2043 png_free(png_ptr, text_ptr);
2044 png_free(png_ptr, chunkdata);
2045 if (ret)
2046 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2047}
2048#endif
2049
2050#if defined(PNG_READ_iTXt_SUPPORTED)
2051/* note: this does not correctly handle chunks that are > 64K under DOS */
2052void /* PRIVATE */
2053png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2054{
2055 png_textp text_ptr;
2056 png_charp chunkdata;
2057 png_charp key, lang, text, lang_key;
2058 int comp_flag;
2059 int comp_type = 0;
2060 int ret;
2061 png_size_t slength, prefix_len, data_len;
2062
2063 png_debug(1, "in png_handle_iTXt\n");
2064
2065 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2066 png_error(png_ptr, "Missing IHDR before iTXt");
2067
2068 if (png_ptr->mode & PNG_HAVE_IDAT)
2069 png_ptr->mode |= PNG_AFTER_IDAT;
2070
2071#ifdef PNG_MAX_MALLOC_64K
2072 /* We will no doubt have problems with chunks even half this size, but
2073 there is no hard and fast rule to tell us where to stop. */
2074 if (length > (png_uint_32)65535L)
2075 {
2076 png_warning(png_ptr,"iTXt chunk too large to fit in memory");
2077 png_crc_finish(png_ptr, length);
2078 return;
2079 }
2080#endif
2081
2082 chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2083 if (chunkdata == NULL)
2084 {
2085 png_warning(png_ptr, "No memory to process iTXt chunk.");
2086 return;
2087 }
2088 slength = (png_size_t)length;
2089 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
2090 if (png_crc_finish(png_ptr, 0))
2091 {
2092 png_free(png_ptr, chunkdata);
2093 return;
2094 }
2095
2096 chunkdata[slength] = 0x00;
2097
2098 for (lang = chunkdata; *lang; lang++)
2099 /* empty loop */ ;
2100 lang++; /* skip NUL separator */
2101
2102 /* iTXt must have a language tag (possibly empty), two compression bytes,
2103 translated keyword (possibly empty), and possibly some text after the
2104 keyword */
2105
2106 if (lang >= chunkdata + slength - 3)
2107 {
2108 png_warning(png_ptr, "Truncated iTXt chunk");
2109 png_free(png_ptr, chunkdata);
2110 return;
2111 }
2112 else
2113 {
2114 comp_flag = *lang++;
2115 comp_type = *lang++;
2116 }
2117
2118 for (lang_key = lang; *lang_key; lang_key++)
2119 /* empty loop */ ;
2120 lang_key++; /* skip NUL separator */
2121
2122 if (lang_key >= chunkdata + slength)
2123 {
2124 png_warning(png_ptr, "Truncated iTXt chunk");
2125 png_free(png_ptr, chunkdata);
2126 return;
2127 }
2128
2129 for (text = lang_key; *text; text++)
2130 /* empty loop */ ;
2131 text++; /* skip NUL separator */
2132 if (text >= chunkdata + slength)
2133 {
2134 png_warning(png_ptr, "Malformed iTXt chunk");
2135 png_free(png_ptr, chunkdata);
2136 return;
2137 }
2138
2139 prefix_len = text - chunkdata;
2140
2141 key=chunkdata;
2142 if (comp_flag)
2143 chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
2144 (size_t)length, prefix_len, &data_len);
2145 else
2146 data_len=png_strlen(chunkdata + prefix_len);
2147 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2148 (png_uint_32)png_sizeof(png_text));
2149 if (text_ptr == NULL)
2150 {
2151 png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
2152 png_free(png_ptr, chunkdata);
2153 return;
2154 }
2155 text_ptr->compression = (int)comp_flag + 1;
2156 text_ptr->lang_key = chunkdata+(lang_key-key);
2157 text_ptr->lang = chunkdata+(lang-key);
2158 text_ptr->itxt_length = data_len;
2159 text_ptr->text_length = 0;
2160 text_ptr->key = chunkdata;
2161 text_ptr->text = chunkdata + prefix_len;
2162
2163 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2164
2165 png_free(png_ptr, text_ptr);
2166 png_free(png_ptr, chunkdata);
2167 if (ret)
2168 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
2169}
2170#endif
2171
2172/* This function is called when we haven't found a handler for a
2173 chunk. If there isn't a problem with the chunk itself (ie bad
2174 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2175 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2176 case it will be saved away to be written out later. */
2177void /* PRIVATE */
2178png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2179{
2180 png_uint_32 skip = 0;
2181
2182 png_debug(1, "in png_handle_unknown\n");
2183
2184 if (png_ptr->mode & PNG_HAVE_IDAT)
2185 {
2186#ifdef PNG_USE_LOCAL_ARRAYS
2187 PNG_CONST PNG_IDAT;
2188#endif
2189 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2190 png_ptr->mode |= PNG_AFTER_IDAT;
2191 }
2192
2193 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
2194
2195 if (!(png_ptr->chunk_name[0] & 0x20))
2196 {
2197#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2198 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2199 PNG_HANDLE_CHUNK_ALWAYS
2200#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2201 && png_ptr->read_user_chunk_fn == NULL
2202#endif
2203 )
2204#endif
2205 png_chunk_error(png_ptr, "unknown critical chunk");
2206 }
2207
2208#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2209 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
2210 (png_ptr->read_user_chunk_fn != NULL))
2211 {
2212#ifdef PNG_MAX_MALLOC_64K
2213 if (length > (png_uint_32)65535L)
2214 {
2215 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2216 skip = length - (png_uint_32)65535L;
2217 length = (png_uint_32)65535L;
2218 }
2219#endif
2220 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
2221 (png_charp)png_ptr->chunk_name,
2222 png_sizeof(png_ptr->unknown_chunk.name));
2223 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0';
2224 png_ptr->unknown_chunk.size = (png_size_t)length;
2225 if (length == 0)
2226 png_ptr->unknown_chunk.data = NULL;
2227 else
2228 {
2229 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2230 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2231 }
2232#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2233 if(png_ptr->read_user_chunk_fn != NULL)
2234 {
2235 /* callback to user unknown chunk handler */
2236 int ret;
2237 ret = (*(png_ptr->read_user_chunk_fn))
2238 (png_ptr, &png_ptr->unknown_chunk);
2239 if (ret < 0)
2240 png_chunk_error(png_ptr, "error in user chunk");
2241 if (ret == 0)
2242 {
2243 if (!(png_ptr->chunk_name[0] & 0x20))
2244 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2245 PNG_HANDLE_CHUNK_ALWAYS)
2246 png_chunk_error(png_ptr, "unknown critical chunk");
2247 png_set_unknown_chunks(png_ptr, info_ptr,
2248 &png_ptr->unknown_chunk, 1);
2249 }
2250 }
2251 else
2252#endif
2253 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
2254 png_free(png_ptr, png_ptr->unknown_chunk.data);
2255 png_ptr->unknown_chunk.data = NULL;
2256 }
2257 else
2258#endif
2259 skip = length;
2260
2261 png_crc_finish(png_ptr, skip);
2262
2263#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2264 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
2265#endif
2266}
2267
2268/* This function is called to verify that a chunk name is valid.
2269 This function can't have the "critical chunk check" incorporated
2270 into it, since in the future we will need to be able to call user
2271 functions to handle unknown critical chunks after we check that
2272 the chunk name itself is valid. */
2273
2274#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
2275
2276void /* PRIVATE */
2277png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2278{
2279 png_debug(1, "in png_check_chunk_name\n");
2280 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2281 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2282 {
2283 png_chunk_error(png_ptr, "invalid chunk type");
2284 }
2285}
2286
2287/* Combines the row recently read in with the existing pixels in the
2288 row. This routine takes care of alpha and transparency if requested.
2289 This routine also handles the two methods of progressive display
2290 of interlaced images, depending on the mask value.
2291 The mask value describes which pixels are to be combined with
2292 the row. The pattern always repeats every 8 pixels, so just 8
2293 bits are needed. A one indicates the pixel is to be combined,
2294 a zero indicates the pixel is to be skipped. This is in addition
2295 to any alpha or transparency value associated with the pixel. If
2296 you want all pixels to be combined, pass 0xff (255) in mask. */
2297
2298void /* PRIVATE */
2299png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2300{
2301 png_debug(1,"in png_combine_row\n");
2302 if (mask == 0xff)
2303 {
2304 png_memcpy(row, png_ptr->row_buf + 1,
2305 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
2306 }
2307 else
2308 {
2309 switch (png_ptr->row_info.pixel_depth)
2310 {
2311 case 1:
2312 {
2313 png_bytep sp = png_ptr->row_buf + 1;
2314 png_bytep dp = row;
2315 int s_inc, s_start, s_end;
2316 int m = 0x80;
2317 int shift;
2318 png_uint_32 i;
2319 png_uint_32 row_width = png_ptr->width;
2320
2321#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2322 if (png_ptr->transformations & PNG_PACKSWAP)
2323 {
2324 s_start = 0;
2325 s_end = 7;
2326 s_inc = 1;
2327 }
2328 else
2329#endif
2330 {
2331 s_start = 7;
2332 s_end = 0;
2333 s_inc = -1;
2334 }
2335
2336 shift = s_start;
2337
2338 for (i = 0; i < row_width; i++)
2339 {
2340 if (m & mask)
2341 {
2342 int value;
2343
2344 value = (*sp >> shift) & 0x01;
2345 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2346 *dp |= (png_byte)(value << shift);
2347 }
2348
2349 if (shift == s_end)
2350 {
2351 shift = s_start;
2352 sp++;
2353 dp++;
2354 }
2355 else
2356 shift += s_inc;
2357
2358 if (m == 1)
2359 m = 0x80;
2360 else
2361 m >>= 1;
2362 }
2363 break;
2364 }
2365 case 2:
2366 {
2367 png_bytep sp = png_ptr->row_buf + 1;
2368 png_bytep dp = row;
2369 int s_start, s_end, s_inc;
2370 int m = 0x80;
2371 int shift;
2372 png_uint_32 i;
2373 png_uint_32 row_width = png_ptr->width;
2374 int value;
2375
2376#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2377 if (png_ptr->transformations & PNG_PACKSWAP)
2378 {
2379 s_start = 0;
2380 s_end = 6;
2381 s_inc = 2;
2382 }
2383 else
2384#endif
2385 {
2386 s_start = 6;
2387 s_end = 0;
2388 s_inc = -2;
2389 }
2390
2391 shift = s_start;
2392
2393 for (i = 0; i < row_width; i++)
2394 {
2395 if (m & mask)
2396 {
2397 value = (*sp >> shift) & 0x03;
2398 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2399 *dp |= (png_byte)(value << shift);
2400 }
2401
2402 if (shift == s_end)
2403 {
2404 shift = s_start;
2405 sp++;
2406 dp++;
2407 }
2408 else
2409 shift += s_inc;
2410 if (m == 1)
2411 m = 0x80;
2412 else
2413 m >>= 1;
2414 }
2415 break;
2416 }
2417 case 4:
2418 {
2419 png_bytep sp = png_ptr->row_buf + 1;
2420 png_bytep dp = row;
2421 int s_start, s_end, s_inc;
2422 int m = 0x80;
2423 int shift;
2424 png_uint_32 i;
2425 png_uint_32 row_width = png_ptr->width;
2426 int value;
2427
2428#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2429 if (png_ptr->transformations & PNG_PACKSWAP)
2430 {
2431 s_start = 0;
2432 s_end = 4;
2433 s_inc = 4;
2434 }
2435 else
2436#endif
2437 {
2438 s_start = 4;
2439 s_end = 0;
2440 s_inc = -4;
2441 }
2442 shift = s_start;
2443
2444 for (i = 0; i < row_width; i++)
2445 {
2446 if (m & mask)
2447 {
2448 value = (*sp >> shift) & 0xf;
2449 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2450 *dp |= (png_byte)(value << shift);
2451 }
2452
2453 if (shift == s_end)
2454 {
2455 shift = s_start;
2456 sp++;
2457 dp++;
2458 }
2459 else
2460 shift += s_inc;
2461 if (m == 1)
2462 m = 0x80;
2463 else
2464 m >>= 1;
2465 }
2466 break;
2467 }
2468 default:
2469 {
2470 png_bytep sp = png_ptr->row_buf + 1;
2471 png_bytep dp = row;
2472 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2473 png_uint_32 i;
2474 png_uint_32 row_width = png_ptr->width;
2475 png_byte m = 0x80;
2476
2477
2478 for (i = 0; i < row_width; i++)
2479 {
2480 if (m & mask)
2481 {
2482 png_memcpy(dp, sp, pixel_bytes);
2483 }
2484
2485 sp += pixel_bytes;
2486 dp += pixel_bytes;
2487
2488 if (m == 1)
2489 m = 0x80;
2490 else
2491 m >>= 1;
2492 }
2493 break;
2494 }
2495 }
2496 }
2497}
2498
2499#ifdef PNG_READ_INTERLACING_SUPPORTED
2500/* OLD pre-1.0.9 interface:
2501void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2502 png_uint_32 transformations)
2503 */
2504void /* PRIVATE */
2505png_do_read_interlace(png_structp png_ptr)
2506{
2507 png_row_infop row_info = &(png_ptr->row_info);
2508 png_bytep row = png_ptr->row_buf + 1;
2509 int pass = png_ptr->pass;
2510 png_uint_32 transformations = png_ptr->transformations;
2511#ifdef PNG_USE_LOCAL_ARRAYS
2512 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2513 /* offset to next interlace block */
2514 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2515#endif
2516
2517 png_debug(1,"in png_do_read_interlace\n");
2518 if (row != NULL && row_info != NULL)
2519 {
2520 png_uint_32 final_width;
2521
2522 final_width = row_info->width * png_pass_inc[pass];
2523
2524 switch (row_info->pixel_depth)
2525 {
2526 case 1:
2527 {
2528 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2529 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2530 int sshift, dshift;
2531 int s_start, s_end, s_inc;
2532 int jstop = png_pass_inc[pass];
2533 png_byte v;
2534 png_uint_32 i;
2535 int j;
2536
2537#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2538 if (transformations & PNG_PACKSWAP)
2539 {
2540 sshift = (int)((row_info->width + 7) & 0x07);
2541 dshift = (int)((final_width + 7) & 0x07);
2542 s_start = 7;
2543 s_end = 0;
2544 s_inc = -1;
2545 }
2546 else
2547#endif
2548 {
2549 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2550 dshift = 7 - (int)((final_width + 7) & 0x07);
2551 s_start = 0;
2552 s_end = 7;
2553 s_inc = 1;
2554 }
2555
2556 for (i = 0; i < row_info->width; i++)
2557 {
2558 v = (png_byte)((*sp >> sshift) & 0x01);
2559 for (j = 0; j < jstop; j++)
2560 {
2561 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2562 *dp |= (png_byte)(v << dshift);
2563 if (dshift == s_end)
2564 {
2565 dshift = s_start;
2566 dp--;
2567 }
2568 else
2569 dshift += s_inc;
2570 }
2571 if (sshift == s_end)
2572 {
2573 sshift = s_start;
2574 sp--;
2575 }
2576 else
2577 sshift += s_inc;
2578 }
2579 break;
2580 }
2581 case 2:
2582 {
2583 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2584 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2585 int sshift, dshift;
2586 int s_start, s_end, s_inc;
2587 int jstop = png_pass_inc[pass];
2588 png_uint_32 i;
2589
2590#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2591 if (transformations & PNG_PACKSWAP)
2592 {
2593 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2594 dshift = (int)(((final_width + 3) & 0x03) << 1);
2595 s_start = 6;
2596 s_end = 0;
2597 s_inc = -2;
2598 }
2599 else
2600#endif
2601 {
2602 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2603 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2604 s_start = 0;
2605 s_end = 6;
2606 s_inc = 2;
2607 }
2608
2609 for (i = 0; i < row_info->width; i++)
2610 {
2611 png_byte v;
2612 int j;
2613
2614 v = (png_byte)((*sp >> sshift) & 0x03);
2615 for (j = 0; j < jstop; j++)
2616 {
2617 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2618 *dp |= (png_byte)(v << dshift);
2619 if (dshift == s_end)
2620 {
2621 dshift = s_start;
2622 dp--;
2623 }
2624 else
2625 dshift += s_inc;
2626 }
2627 if (sshift == s_end)
2628 {
2629 sshift = s_start;
2630 sp--;
2631 }
2632 else
2633 sshift += s_inc;
2634 }
2635 break;
2636 }
2637 case 4:
2638 {
2639 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2640 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2641 int sshift, dshift;
2642 int s_start, s_end, s_inc;
2643 png_uint_32 i;
2644 int jstop = png_pass_inc[pass];
2645
2646#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2647 if (transformations & PNG_PACKSWAP)
2648 {
2649 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2650 dshift = (int)(((final_width + 1) & 0x01) << 2);
2651 s_start = 4;
2652 s_end = 0;
2653 s_inc = -4;
2654 }
2655 else
2656#endif
2657 {
2658 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2659 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2660 s_start = 0;
2661 s_end = 4;
2662 s_inc = 4;
2663 }
2664
2665 for (i = 0; i < row_info->width; i++)
2666 {
2667 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2668 int j;
2669
2670 for (j = 0; j < jstop; j++)
2671 {
2672 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2673 *dp |= (png_byte)(v << dshift);
2674 if (dshift == s_end)
2675 {
2676 dshift = s_start;
2677 dp--;
2678 }
2679 else
2680 dshift += s_inc;
2681 }
2682 if (sshift == s_end)
2683 {
2684 sshift = s_start;
2685 sp--;
2686 }
2687 else
2688 sshift += s_inc;
2689 }
2690 break;
2691 }
2692 default:
2693 {
2694 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2695 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2696 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2697
2698 int jstop = png_pass_inc[pass];
2699 png_uint_32 i;
2700
2701 for (i = 0; i < row_info->width; i++)
2702 {
2703 png_byte v[8];
2704 int j;
2705
2706 png_memcpy(v, sp, pixel_bytes);
2707 for (j = 0; j < jstop; j++)
2708 {
2709 png_memcpy(dp, v, pixel_bytes);
2710 dp -= pixel_bytes;
2711 }
2712 sp -= pixel_bytes;
2713 }
2714 break;
2715 }
2716 }
2717 row_info->width = final_width;
2718 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
2719 }
2720#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2721 transformations = transformations; /* silence compiler warning */
2722#endif
2723}
2724#endif /* PNG_READ_INTERLACING_SUPPORTED */
2725
2726void /* PRIVATE */
2727png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2728 png_bytep prev_row, int filter)
2729{
2730 png_debug(1, "in png_read_filter_row\n");
2731 png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
2732 switch (filter)
2733 {
2734 case PNG_FILTER_VALUE_NONE:
2735 break;
2736 case PNG_FILTER_VALUE_SUB:
2737 {
2738 png_uint_32 i;
2739 png_uint_32 istop = row_info->rowbytes;
2740 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2741 png_bytep rp = row + bpp;
2742 png_bytep lp = row;
2743
2744 for (i = bpp; i < istop; i++)
2745 {
2746 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2747 rp++;
2748 }
2749 break;
2750 }
2751 case PNG_FILTER_VALUE_UP:
2752 {
2753 png_uint_32 i;
2754 png_uint_32 istop = row_info->rowbytes;
2755 png_bytep rp = row;
2756 png_bytep pp = prev_row;
2757
2758 for (i = 0; i < istop; i++)
2759 {
2760 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2761 rp++;
2762 }
2763 break;
2764 }
2765 case PNG_FILTER_VALUE_AVG:
2766 {
2767 png_uint_32 i;
2768 png_bytep rp = row;
2769 png_bytep pp = prev_row;
2770 png_bytep lp = row;
2771 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2772 png_uint_32 istop = row_info->rowbytes - bpp;
2773
2774 for (i = 0; i < bpp; i++)
2775 {
2776 *rp = (png_byte)(((int)(*rp) +
2777 ((int)(*pp++) / 2 )) & 0xff);
2778 rp++;
2779 }
2780
2781 for (i = 0; i < istop; i++)
2782 {
2783 *rp = (png_byte)(((int)(*rp) +
2784 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2785 rp++;
2786 }
2787 break;
2788 }
2789 case PNG_FILTER_VALUE_PAETH:
2790 {
2791 png_uint_32 i;
2792 png_bytep rp = row;
2793 png_bytep pp = prev_row;
2794 png_bytep lp = row;
2795 png_bytep cp = prev_row;
2796 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2797 png_uint_32 istop=row_info->rowbytes - bpp;
2798
2799 for (i = 0; i < bpp; i++)
2800 {
2801 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2802 rp++;
2803 }
2804
2805 for (i = 0; i < istop; i++) /* use leftover rp,pp */
2806 {
2807 int a, b, c, pa, pb, pc, p;
2808
2809 a = *lp++;
2810 b = *pp++;
2811 c = *cp++;
2812
2813 p = b - c;
2814 pc = a - c;
2815
2816#ifdef PNG_USE_ABS
2817 pa = abs(p);
2818 pb = abs(pc);
2819 pc = abs(p + pc);
2820#else
2821 pa = p < 0 ? -p : p;
2822 pb = pc < 0 ? -pc : pc;
2823 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2824#endif
2825
2826 /*
2827 if (pa <= pb && pa <= pc)
2828 p = a;
2829 else if (pb <= pc)
2830 p = b;
2831 else
2832 p = c;
2833 */
2834
2835 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2836
2837 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2838 rp++;
2839 }
2840 break;
2841 }
2842 default:
2843 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2844 *row=0;
2845 break;
2846 }
2847}
2848
2849void /* PRIVATE */
2850png_read_finish_row(png_structp png_ptr)
2851{
2852#ifdef PNG_USE_LOCAL_ARRAYS
2853#ifdef PNG_READ_INTERLACING_SUPPORTED
2854 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2855
2856 /* start of interlace block */
2857 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2858
2859 /* offset to next interlace block */
2860 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2861
2862 /* start of interlace block in the y direction */
2863 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2864
2865 /* offset to next interlace block in the y direction */
2866 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2867#endif /* PNG_READ_INTERLACING_SUPPORTED */
2868#endif
2869
2870 png_debug(1, "in png_read_finish_row\n");
2871 png_ptr->row_number++;
2872 if (png_ptr->row_number < png_ptr->num_rows)
2873 return;
2874
2875#ifdef PNG_READ_INTERLACING_SUPPORTED
2876 if (png_ptr->interlaced)
2877 {
2878 png_ptr->row_number = 0;
2879 png_memset_check(png_ptr, png_ptr->prev_row, 0,
2880 png_ptr->rowbytes + 1);
2881 do
2882 {
2883 png_ptr->pass++;
2884 if (png_ptr->pass >= 7)
2885 break;
2886 png_ptr->iwidth = (png_ptr->width +
2887 png_pass_inc[png_ptr->pass] - 1 -
2888 png_pass_start[png_ptr->pass]) /
2889 png_pass_inc[png_ptr->pass];
2890
2891 png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
2892 png_ptr->iwidth) + 1;
2893
2894 if (!(png_ptr->transformations & PNG_INTERLACE))
2895 {
2896 png_ptr->num_rows = (png_ptr->height +
2897 png_pass_yinc[png_ptr->pass] - 1 -
2898 png_pass_ystart[png_ptr->pass]) /
2899 png_pass_yinc[png_ptr->pass];
2900 if (!(png_ptr->num_rows))
2901 continue;
2902 }
2903 else /* if (png_ptr->transformations & PNG_INTERLACE) */
2904 break;
2905 } while (png_ptr->iwidth == 0);
2906
2907 if (png_ptr->pass < 7)
2908 return;
2909 }
2910#endif /* PNG_READ_INTERLACING_SUPPORTED */
2911
2912 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
2913 {
2914#ifdef PNG_USE_LOCAL_ARRAYS
2915 PNG_CONST PNG_IDAT;
2916#endif
2917 char extra;
2918 int ret;
2919
2920 png_ptr->zstream.next_out = (Byte *)&extra;
2921 png_ptr->zstream.avail_out = (uInt)1;
2922 for(;;)
2923 {
2924 if (!(png_ptr->zstream.avail_in))
2925 {
2926 while (!png_ptr->idat_size)
2927 {
2928 png_byte chunk_length[4];
2929
2930 png_crc_finish(png_ptr, 0);
2931
2932 png_read_data(png_ptr, chunk_length, 4);
2933 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
2934 png_reset_crc(png_ptr);
2935 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2936 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
2937 png_error(png_ptr, "Not enough image data");
2938
2939 }
2940 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2941 png_ptr->zstream.next_in = png_ptr->zbuf;
2942 if (png_ptr->zbuf_size > png_ptr->idat_size)
2943 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2944 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2945 png_ptr->idat_size -= png_ptr->zstream.avail_in;
2946 }
2947 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
2948 if (ret == Z_STREAM_END)
2949 {
2950 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
2951 png_ptr->idat_size)
2952 png_warning(png_ptr, "Extra compressed data");
2953 png_ptr->mode |= PNG_AFTER_IDAT;
2954 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2955 break;
2956 }
2957 if (ret != Z_OK)
2958 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
2959 "Decompression Error");
2960
2961 if (!(png_ptr->zstream.avail_out))
2962 {
2963 png_warning(png_ptr, "Extra compressed data.");
2964 png_ptr->mode |= PNG_AFTER_IDAT;
2965 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2966 break;
2967 }
2968
2969 }
2970 png_ptr->zstream.avail_out = 0;
2971 }
2972
2973 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
2974 png_warning(png_ptr, "Extra compression data");
2975
2976 inflateReset(&png_ptr->zstream);
2977
2978 png_ptr->mode |= PNG_AFTER_IDAT;
2979}
2980
2981void /* PRIVATE */
2982png_read_start_row(png_structp png_ptr)
2983{
2984#ifdef PNG_USE_LOCAL_ARRAYS
2985#ifdef PNG_READ_INTERLACING_SUPPORTED
2986 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2987
2988 /* start of interlace block */
2989 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2990
2991 /* offset to next interlace block */
2992 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2993
2994 /* start of interlace block in the y direction */
2995 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2996
2997 /* offset to next interlace block in the y direction */
2998 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2999#endif
3000#endif
3001
3002 int max_pixel_depth;
3003 png_uint_32 row_bytes;
3004
3005 png_debug(1, "in png_read_start_row\n");
3006 png_ptr->zstream.avail_in = 0;
3007 png_init_read_transformations(png_ptr);
3008#ifdef PNG_READ_INTERLACING_SUPPORTED
3009 if (png_ptr->interlaced)
3010 {
3011 if (!(png_ptr->transformations & PNG_INTERLACE))
3012 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
3013 png_pass_ystart[0]) / png_pass_yinc[0];
3014 else
3015 png_ptr->num_rows = png_ptr->height;
3016
3017 png_ptr->iwidth = (png_ptr->width +
3018 png_pass_inc[png_ptr->pass] - 1 -
3019 png_pass_start[png_ptr->pass]) /
3020 png_pass_inc[png_ptr->pass];
3021
3022 row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;
3023
3024 png_ptr->irowbytes = (png_size_t)row_bytes;
3025 if((png_uint_32)png_ptr->irowbytes != row_bytes)
3026 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
3027 }
3028 else
3029#endif /* PNG_READ_INTERLACING_SUPPORTED */
3030 {
3031 png_ptr->num_rows = png_ptr->height;
3032 png_ptr->iwidth = png_ptr->width;
3033 png_ptr->irowbytes = png_ptr->rowbytes + 1;
3034 }
3035 max_pixel_depth = png_ptr->pixel_depth;
3036
3037#if defined(PNG_READ_PACK_SUPPORTED)
3038 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
3039 max_pixel_depth = 8;
3040#endif
3041
3042#if defined(PNG_READ_EXPAND_SUPPORTED)
3043 if (png_ptr->transformations & PNG_EXPAND)
3044 {
3045 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3046 {
3047 if (png_ptr->num_trans)
3048 max_pixel_depth = 32;
3049 else
3050 max_pixel_depth = 24;
3051 }
3052 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3053 {
3054 if (max_pixel_depth < 8)
3055 max_pixel_depth = 8;
3056 if (png_ptr->num_trans)
3057 max_pixel_depth *= 2;
3058 }
3059 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3060 {
3061 if (png_ptr->num_trans)
3062 {
3063 max_pixel_depth *= 4;
3064 max_pixel_depth /= 3;
3065 }
3066 }
3067 }
3068#endif
3069
3070#if defined(PNG_READ_FILLER_SUPPORTED)
3071 if (png_ptr->transformations & (PNG_FILLER))
3072 {
3073 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3074 max_pixel_depth = 32;
3075 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3076 {
3077 if (max_pixel_depth <= 8)
3078 max_pixel_depth = 16;
3079 else
3080 max_pixel_depth = 32;
3081 }
3082 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3083 {
3084 if (max_pixel_depth <= 32)
3085 max_pixel_depth = 32;
3086 else
3087 max_pixel_depth = 64;
3088 }
3089 }
3090#endif
3091
3092#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
3093 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3094 {
3095 if (
3096#if defined(PNG_READ_EXPAND_SUPPORTED)
3097 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3098#endif
3099#if defined(PNG_READ_FILLER_SUPPORTED)
3100 (png_ptr->transformations & (PNG_FILLER)) ||
3101#endif
3102 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3103 {
3104 if (max_pixel_depth <= 16)
3105 max_pixel_depth = 32;
3106 else
3107 max_pixel_depth = 64;
3108 }
3109 else
3110 {
3111 if (max_pixel_depth <= 8)
3112 {
3113 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3114 max_pixel_depth = 32;
3115 else
3116 max_pixel_depth = 24;
3117 }
3118 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3119 max_pixel_depth = 64;
3120 else
3121 max_pixel_depth = 48;
3122 }
3123 }
3124#endif
3125
3126#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3127defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
3128 if(png_ptr->transformations & PNG_USER_TRANSFORM)
3129 {
3130 int user_pixel_depth=png_ptr->user_transform_depth*
3131 png_ptr->user_transform_channels;
3132 if(user_pixel_depth > max_pixel_depth)
3133 max_pixel_depth=user_pixel_depth;
3134 }
3135#endif
3136
3137 /* align the width on the next larger 8 pixels. Mainly used
3138 for interlacing */
3139 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
3140 /* calculate the maximum bytes needed, adding a byte and a pixel
3141 for safety's sake */
3142 row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) +
3143 1 + ((max_pixel_depth + 7) >> 3);
3144#ifdef PNG_MAX_MALLOC_64K
3145 if (row_bytes > (png_uint_32)65536L)
3146 png_error(png_ptr, "This image requires a row greater than 64KB");
3147#endif
3148
3149 if(row_bytes + 64 > png_ptr->old_big_row_buf_size)
3150 {
3151 png_free(png_ptr,png_ptr->big_row_buf);
3152 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
3153 png_ptr->row_buf = png_ptr->big_row_buf+32;
3154 png_ptr->old_big_row_buf_size = row_bytes+64;
3155 }
3156
3157#ifdef PNG_MAX_MALLOC_64K
3158 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
3159 png_error(png_ptr, "This image requires a row greater than 64KB");
3160#endif
3161 if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
3162 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
3163
3164 if(png_ptr->rowbytes+1 > png_ptr->old_prev_row_size)
3165 {
3166 png_free(png_ptr,png_ptr->prev_row);
3167 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3168 png_ptr->rowbytes + 1));
3169 png_ptr->old_prev_row_size = png_ptr->rowbytes+1;
3170 }
3171
3172 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
3173
3174 png_debug1(3, "width = %lu,\n", png_ptr->width);
3175 png_debug1(3, "height = %lu,\n", png_ptr->height);
3176 png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
3177 png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
3178 png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
3179 png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
3180
3181 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3182}
3183#endif /* PNG_READ_SUPPORTED */