source: liacs/MIR2010/SourceCode/cximage/png/pngrutil.c@ 193

Last change on this file since 193 was 95, checked in by Rick van der Zwet, 15 years ago

Bad boy, improper move of directory

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