Code

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