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