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