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