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