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