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