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