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