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