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