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