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