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