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