VirtualBox

source: vbox/trunk/src/libs/libpng-1.2.54/pngrutil.c@ 64529

最後變更 在這個檔案從64529是 58796,由 vboxsync 提交於 9 年 前

libpng 1.2.54 unmodified

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette