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