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