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