blob: 79841faffcf031b74e8da4b5de096d4ebaa19e81 [file] [log] [blame]
Glenn Randers-Pehrsone6474622006-03-04 16:50:47 -06001
Andreas Dilger47a0c421997-05-16 02:46:07 -05002/* pngrutil.c - utilities to read a PNG file
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003 *
Glenn Randers-Pehrson65a24d02011-04-01 20:41:53 -05004 * Last changed in libpng 1.5.3 [(PENDING RELEASE)]
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06005 * Copyright (c) 1998-2011 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06008 *
Glenn Randers-Pehrsonbfbf8652009-06-26 21:46:52 -05009 * This code is released under the libpng license.
Glenn Randers-Pehrsonc332bbc2009-06-25 13:43:50 -050010 * For conditions of distribution and use, see the disclaimer
Glenn Randers-Pehrson037023b2009-06-24 10:27:36 -050011 * and license in png.h
Glenn Randers-Pehrson3e61d792009-06-24 09:31:28 -050012 *
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050013 * This file contains routines that are only called from within
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060014 * libpng itself during the course of reading an image.
15 */
Guy Schalnat0d580581995-07-20 02:43:20 -050016
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050017#include "pngpriv.h"
Guy Schalnat0d580581995-07-20 02:43:20 -050018
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -060019#ifdef PNG_READ_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -050020
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -060021#define png_strtod(p,a,b) strtod(a,b)
22
23png_uint_32 PNGAPI
24png_get_uint_31(png_structp png_ptr, png_const_bytep buf)
25{
26 png_uint_32 uval = png_get_uint_32(buf);
27
28 if (uval > PNG_UINT_31_MAX)
29 png_error(png_ptr, "PNG unsigned integer out of range");
30
31 return (uval);
32}
33
34#if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED)
35/* The following is a variation on the above for use with the fixed
36 * point values used for gAMA and cHRM. Instead of png_error it
37 * issues a warning and returns (-1) - an invalid value because both
38 * gAMA and cHRM use *unsigned* integers for fixed point values.
39 */
40#define PNG_FIXED_ERROR (-1)
41
42static png_fixed_point /* PRIVATE */
43png_get_fixed_point(png_structp png_ptr, png_const_bytep buf)
44{
45 png_uint_32 uval = png_get_uint_32(buf);
46
47 if (uval <= PNG_UINT_31_MAX)
48 return (png_fixed_point)uval; /* known to be in range */
49
50 /* The caller can turn off the warning by passing NULL. */
51 if (png_ptr != NULL)
52 png_warning(png_ptr, "PNG fixed point integer out of range");
53
54 return PNG_FIXED_ERROR;
55}
56#endif
57
58#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
59/* NOTE: the read macros will obscure these definitions, so that if
60 * PNG_USE_READ_MACROS is set the library will not use them internally,
61 * but the APIs will still be available externally.
62 *
63 * The parentheses around "PNGAPI function_name" in the following three
64 * functions are necessary because they allow the macros to co-exist with
65 * these (unused but exported) functions.
66 */
67
68/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
69png_uint_32 (PNGAPI
70png_get_uint_32)(png_const_bytep buf)
71{
72 png_uint_32 uval =
73 ((png_uint_32)(*(buf )) << 24) +
74 ((png_uint_32)(*(buf + 1)) << 16) +
75 ((png_uint_32)(*(buf + 2)) << 8) +
76 ((png_uint_32)(*(buf + 3)) ) ;
77
78 return uval;
Guy Schalnat0d580581995-07-20 02:43:20 -050079}
80
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050081/* Grab a signed 32-bit integer from a buffer in big-endian format. The
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -060082 * data is stored in the PNG file in two's complement format and there
83 * is no guarantee that a 'png_int_32' is exactly 32 bits, therefore
84 * the following code does a two's complement to native conversion.
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050085 */
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -060086png_int_32 (PNGAPI
87png_get_int_32)(png_const_bytep buf)
Andreas Dilger47a0c421997-05-16 02:46:07 -050088{
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -060089 png_uint_32 uval = png_get_uint_32(buf);
90 if ((uval & 0x80000000L) == 0) /* non-negative */
91 return uval;
Andreas Dilger47a0c421997-05-16 02:46:07 -050092
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -060093 uval = (uval ^ 0xffffffffL) + 1; /* 2's complement: -x = ~x+1 */
94 return -(png_int_32)uval;
Andreas Dilger47a0c421997-05-16 02:46:07 -050095}
Andreas Dilger47a0c421997-05-16 02:46:07 -050096
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050097/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -060098png_uint_16 (PNGAPI
99png_get_uint_16)(png_const_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -0500100{
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600101 /* ANSI-C requires an int value to accomodate at least 16 bits so this
102 * works and allows the compiler not to worry about possible narrowing
103 * on 32 bit systems. (Pre-ANSI systems did not make integers smaller
104 * than 16 bits either.)
105 */
106 unsigned int val =
107 ((unsigned int)(*buf) << 8) +
108 ((unsigned int)(*(buf + 1)));
Guy Schalnat0d580581995-07-20 02:43:20 -0500109
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600110 return (png_uint_16)val;
Guy Schalnat0d580581995-07-20 02:43:20 -0500111}
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600112
113#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */
114
115/* Read and check the PNG file signature */
116void /* PRIVATE */
117png_read_sig(png_structp png_ptr, png_infop info_ptr)
118{
119 png_size_t num_checked, num_to_check;
120
121 /* Exit if the user application does not expect a signature. */
122 if (png_ptr->sig_bytes >= 8)
123 return;
124
125 num_checked = png_ptr->sig_bytes;
126 num_to_check = 8 - num_checked;
127
128#ifdef PNG_IO_STATE_SUPPORTED
129 png_ptr->io_state = PNG_IO_READING | PNG_IO_SIGNATURE;
130#endif
131
132 /* The signature must be serialized in a single I/O call. */
133 png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
134 png_ptr->sig_bytes = 8;
135
136 if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
137 {
138 if (num_checked < 4 &&
139 png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
140 png_error(png_ptr, "Not a PNG file");
141 else
142 png_error(png_ptr, "PNG file corrupted by ASCII conversion");
143 }
144 if (num_checked < 3)
145 png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
146}
Glenn Randers-Pehrsona5815562010-11-20 21:48:29 -0600147
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500148/* Read the chunk header (length + type name).
149 * Put the type name into png_ptr->chunk_name, and return the length.
150 */
151png_uint_32 /* PRIVATE */
152png_read_chunk_header(png_structp png_ptr)
153{
154 png_byte buf[8];
155 png_uint_32 length;
156
157#ifdef PNG_IO_STATE_SUPPORTED
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500158 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR;
159#endif
160
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600161 /* Read the length and the chunk name.
162 * This must be performed in a single I/O call.
163 */
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500164 png_read_data(png_ptr, buf, 8);
165 length = png_get_uint_31(png_ptr, buf);
166
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600167 /* Put the chunk name into png_ptr->chunk_name. */
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500168 png_memcpy(png_ptr->chunk_name, buf + 4, 4);
169
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600170 png_debug2(0, "Reading %s chunk, length = %u",
171 png_ptr->chunk_name, length);
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500172
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600173 /* Reset the crc and run it over the chunk name. */
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500174 png_reset_crc(png_ptr);
175 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
176
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600177 /* Check to see if chunk name is valid. */
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500178 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
179
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500180#ifdef PNG_IO_STATE_SUPPORTED
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500181 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
182#endif
183
184 return length;
185}
186
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500187/* Read data, and (optionally) run it through the CRC. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500188void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500189png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500190{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500191 if (png_ptr == NULL)
192 return;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600193
Guy Schalnat6d764711995-12-19 03:22:19 -0600194 png_read_data(png_ptr, buf, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500195 png_calculate_crc(png_ptr, buf, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500196}
197
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600198/* Optionally skip data and then check the CRC. Depending on whether we
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500199 * are reading a ancillary or critical chunk, and how the program has set
200 * things up, we may calculate the CRC on the data and print a message.
201 * Returns '1' if there was a CRC error, '0' otherwise.
202 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500203int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600204png_crc_finish(png_structp png_ptr, png_uint_32 skip)
Guy Schalnat0d580581995-07-20 02:43:20 -0500205{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500206 png_size_t i;
207 png_size_t istop = png_ptr->zbuf_size;
Guy Schalnat0d580581995-07-20 02:43:20 -0500208
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -0500209 for (i = (png_size_t)skip; i > istop; i -= istop)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600210 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500211 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
Guy Schalnat0d580581995-07-20 02:43:20 -0500212 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600213
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500214 if (i)
Guy Schalnat0d580581995-07-20 02:43:20 -0500215 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500216 png_crc_read(png_ptr, png_ptr->zbuf, i);
Guy Schalnat0d580581995-07-20 02:43:20 -0500217 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600218
Andreas Dilger47a0c421997-05-16 02:46:07 -0500219 if (png_crc_error(png_ptr))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600220 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500221 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500222 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500223 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600224 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600225 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600226 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600227 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600228
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600229 else
230 {
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500231 png_chunk_benign_error(png_ptr, "CRC error");
232 return (0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600233 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600234
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600235 return (1);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600236 }
237
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600238 return (0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500239}
240
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600241/* Compare the CRC stored in the PNG file with that calculated by libpng from
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500242 * the data it has read thus far.
243 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500244int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600245png_crc_error(png_structp png_ptr)
246{
247 png_byte crc_bytes[4];
248 png_uint_32 crc;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500249 int need_crc = 1;
250
251 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
252 {
253 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
254 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
255 need_crc = 0;
256 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600257
Andreas Dilger47a0c421997-05-16 02:46:07 -0500258 else /* critical */
259 {
260 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
261 need_crc = 0;
262 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600263
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500264#ifdef PNG_IO_STATE_SUPPORTED
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500265 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
266#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500267
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600268 /* The chunk CRC must be serialized in a single I/O call. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600269 png_read_data(png_ptr, crc_bytes, 4);
270
Andreas Dilger47a0c421997-05-16 02:46:07 -0500271 if (need_crc)
272 {
273 crc = png_get_uint_32(crc_bytes);
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600274 return ((int)(crc != png_ptr->crc));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500275 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600276
Andreas Dilger47a0c421997-05-16 02:46:07 -0500277 else
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600278 return (0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600279}
280
Glenn Randers-Pehrson5975f312011-04-01 13:15:36 -0500281#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600282static png_size_t
283png_inflate(png_structp png_ptr, png_bytep data, png_size_t size,
284 png_bytep output, png_size_t output_size)
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600285{
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600286 png_size_t count = 0;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600287
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600288 /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it can't
289 * even necessarily handle 65536 bytes) because the type uInt is "16 bits or
290 * more". Consequently it is necessary to chunk the input to zlib. This
291 * code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the maximum value
292 * that can be stored in a uInt.) It is possible to set ZLIB_IO_MAX to a
293 * lower value in pngpriv.h and this may sometimes have a performance
294 * advantage, because it forces access of the input data to be separated from
295 * at least some of the use by some period of time.
296 */
297 png_ptr->zstream.next_in = data;
298 /* avail_in is set below from 'size' */
299 png_ptr->zstream.avail_in = 0;
300
301 while (1)
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600302 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600303 int ret, avail;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600304
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600305 /* The setting of 'avail_in' used to be outside the loop, by setting it
306 * inside it is possible to chunk the input to zlib and simply rely on
307 * zlib to advance the 'next_in' pointer. This allows arbitrary amounts o
308 * data to be passed through zlib at the unavoidable cost of requiring a
309 * window save (memcpy of up to 32768 output bytes) every ZLIB_IO_MAX
310 * input bytes.
311 */
312 if (png_ptr->zstream.avail_in == 0 && size > 0)
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600313 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600314 if (size <= ZLIB_IO_MAX)
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600315 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600316 /* The value is less than ZLIB_IO_MAX so the cast is safe: */
317 png_ptr->zstream.avail_in = (uInt)size;
318 size = 0;
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600319 }
Glenn Randers-Pehrson33893092010-10-23 13:20:18 -0500320
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600321 else
322 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600323 png_ptr->zstream.avail_in = ZLIB_IO_MAX;
324 size -= ZLIB_IO_MAX;
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600325 }
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600326 }
327
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600328 /* Reset the output buffer each time round - we empty it
329 * after every inflate call.
330 */
331 png_ptr->zstream.next_out = png_ptr->zbuf;
332 png_ptr->zstream.avail_out = png_ptr->zbuf_size;
333
334 ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
335 avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
336
337 /* First copy/count any new output - but only if we didn't
338 * get an error code.
339 */
340 if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
341 {
342 png_size_t space = avail; /* > 0, see above */
343
344 if (output != 0 && output_size > count)
345 {
346 png_size_t copy = output_size - count;
347
348 if (space < copy)
349 copy = space;
350
351 png_memcpy(output + count, png_ptr->zbuf, copy);
352 }
353 count += space;
354 }
355
356 if (ret == Z_OK)
357 continue;
358
359 /* Termination conditions - always reset the zstream, it
360 * must be left in inflateInit state.
361 */
Glenn Randers-Pehrson20788d32011-01-06 09:01:04 -0600362 png_ptr->zstream.avail_in = 0;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600363 inflateReset(&png_ptr->zstream);
364
365 if (ret == Z_STREAM_END)
366 return count; /* NOTE: may be zero. */
367
368 /* Now handle the error codes - the API always returns 0
369 * and the error message is dumped into the uncompressed
370 * buffer if available.
371 */
372 {
373 PNG_CONST char *msg;
374#ifdef PNG_CONSOLE_IO_SUPPORTED
375 char umsg[52];
376#endif
377 if (png_ptr->zstream.msg != 0)
378 msg = png_ptr->zstream.msg;
379
380 else
381 {
382#ifdef PNG_CONSOLE_IO_SUPPORTED
383 switch (ret)
384 {
385 case Z_BUF_ERROR:
386 msg = "Buffer error in compressed datastream in %s chunk";
387 break;
388
389 case Z_DATA_ERROR:
390 msg = "Data error in compressed datastream in %s chunk";
391 break;
392
393 default:
394 msg = "Incomplete compressed datastream in %s chunk";
395 break;
396 }
397
398 png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
399 msg = umsg;
400#else
401 msg = "Damaged compressed datastream in chunk other than IDAT";
402#endif
403 }
404
405 png_warning(png_ptr, msg);
406 }
407
408 /* 0 means an error - notice that this code simply ignores
409 * zero length compressed chunks as a result.
410 */
411 return 0;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600412 }
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600413}
414
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600415/*
416 * Decompress trailing data in a chunk. The assumption is that chunkdata
417 * points at an allocated area holding the contents of a chunk with a
418 * trailing compressed part. What we get back is an allocated area
419 * holding the original prefix part and an uncompressed version of the
420 * trailing part (the malloc area passed in is freed).
421 */
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500422void /* PRIVATE */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500423png_decompress_chunk(png_structp png_ptr, int comp_type,
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600424 png_size_t chunklength,
425 png_size_t prefix_size, png_size_t *newlength)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600426{
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600427 /* The caller should guarantee this */
428 if (prefix_size > chunklength)
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600429 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600430 /* The recovery is to delete the chunk. */
431 png_warning(png_ptr, "invalid chunklength");
432 prefix_size = 0; /* To delete everything */
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600433 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600434
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600435 else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600436 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600437 png_size_t expanded_size = png_inflate(png_ptr,
438 (png_bytep)(png_ptr->chunkdata + prefix_size),
439 chunklength - prefix_size,
440 0, /*output*/
441 0); /*output size*/
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600442
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600443 /* Now check the limits on this chunk - if the limit fails the
444 * compressed data will be removed, the prefix will remain.
445 */
446#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
447 if (png_ptr->user_chunk_malloc_max &&
448 (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
Glenn Randers-Pehrson20788d32011-01-06 09:01:04 -0600449#else
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600450# ifdef PNG_USER_CHUNK_MALLOC_MAX
451 if ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
452 prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
453# endif
Glenn Randers-Pehrson20788d32011-01-06 09:01:04 -0600454#endif
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600455 png_warning(png_ptr, "Exceeded size limit while expanding chunk");
456
457 /* If the size is zero either there was an error and a message
458 * has already been output (warning) or the size really is zero
459 * and we have nothing to do - the code will exit through the
460 * error case below.
461 */
462#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \
463 defined(PNG_USER_CHUNK_MALLOC_MAX)
464 else if (expanded_size > 0)
465#else
466 if (expanded_size > 0)
467#endif
468 {
469 /* Success (maybe) - really uncompress the chunk. */
470 png_size_t new_size = 0;
471 png_charp text = png_malloc_warn(png_ptr,
472 prefix_size + expanded_size + 1);
473
474 if (text != NULL)
Glenn Randers-Pehrson20788d32011-01-06 09:01:04 -0600475 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600476 png_memcpy(text, png_ptr->chunkdata, prefix_size);
477 new_size = png_inflate(png_ptr,
478 (png_bytep)(png_ptr->chunkdata + prefix_size),
479 chunklength - prefix_size,
480 (png_bytep)(text + prefix_size), expanded_size);
481 text[prefix_size + expanded_size] = 0; /* just in case */
482
483 if (new_size == expanded_size)
Glenn Randers-Pehrson20788d32011-01-06 09:01:04 -0600484 {
485 png_free(png_ptr, png_ptr->chunkdata);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600486 png_ptr->chunkdata = text;
487 *newlength = prefix_size + expanded_size;
488 return; /* The success return! */
Glenn Randers-Pehrson20788d32011-01-06 09:01:04 -0600489 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600490
491 png_warning(png_ptr, "png_inflate logic error");
492 png_free(png_ptr, text);
Glenn Randers-Pehrson20788d32011-01-06 09:01:04 -0600493 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600494
495 else
496 png_warning(png_ptr, "Not enough memory to decompress chunk");
Glenn Randers-Pehrson20788d32011-01-06 09:01:04 -0600497 }
Glenn Randers-Pehrson20788d32011-01-06 09:01:04 -0600498 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600499
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600500 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
501 {
Glenn Randers-Pehrsond7da8bb2010-03-13 20:30:10 -0600502#ifdef PNG_STDIO_SUPPORTED
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600503 char umsg[50];
504
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600505 png_snprintf(umsg, sizeof umsg,
506 "Unknown zTXt compression type %d", comp_type);
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600507 png_warning(png_ptr, umsg);
508#else
509 png_warning(png_ptr, "Unknown zTXt compression type");
510#endif
511
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600512 /* The recovery is to simply drop the data. */
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600513 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600514
515 /* Generic error return - leave the prefix, delete the compressed
516 * data, reallocate the chunkdata to remove the potentially large
517 * amount of compressed data.
518 */
519 {
520 png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
521
522 if (text != NULL)
523 {
524 if (prefix_size > 0)
525 png_memcpy(text, png_ptr->chunkdata, prefix_size);
526
527 png_free(png_ptr, png_ptr->chunkdata);
528 png_ptr->chunkdata = text;
529
530 /* This is an extra zero in the 'uncompressed' part. */
531 *(png_ptr->chunkdata + prefix_size) = 0x00;
532 }
533 /* Ignore a malloc error here - it is safe. */
534 }
535
536 *newlength = prefix_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600537}
Glenn Randers-Pehrson5975f312011-04-01 13:15:36 -0500538#endif /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600539
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500540/* Read and check the IDHR chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500541void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600542png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500543{
544 png_byte buf[13];
545 png_uint_32 width, height;
546 int bit_depth, color_type, compression_type, filter_type;
547 int interlace_type;
548
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500549 png_debug(1, "in png_handle_IHDR");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500550
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600551 if (png_ptr->mode & PNG_HAVE_IHDR)
Guy Schalnate5a37791996-06-05 15:50:50 -0500552 png_error(png_ptr, "Out of place IHDR");
553
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500554 /* Check the length */
Guy Schalnat0d580581995-07-20 02:43:20 -0500555 if (length != 13)
Guy Schalnat6d764711995-12-19 03:22:19 -0600556 png_error(png_ptr, "Invalid IHDR chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -0500557
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600558 png_ptr->mode |= PNG_HAVE_IHDR;
559
Guy Schalnat0d580581995-07-20 02:43:20 -0500560 png_crc_read(png_ptr, buf, 13);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600561 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500562
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500563 width = png_get_uint_31(png_ptr, buf);
564 height = png_get_uint_31(png_ptr, buf + 4);
Guy Schalnat0d580581995-07-20 02:43:20 -0500565 bit_depth = buf[8];
566 color_type = buf[9];
567 compression_type = buf[10];
568 filter_type = buf[11];
569 interlace_type = buf[12];
570
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500571 /* Set internal variables */
Guy Schalnat0d580581995-07-20 02:43:20 -0500572 png_ptr->width = width;
573 png_ptr->height = height;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600574 png_ptr->bit_depth = (png_byte)bit_depth;
575 png_ptr->interlaced = (png_byte)interlace_type;
576 png_ptr->color_type = (png_byte)color_type;
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500577#ifdef PNG_MNG_FEATURES_SUPPORTED
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -0600578 png_ptr->filter_type = (png_byte)filter_type;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500579#endif
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500580 png_ptr->compression_type = (png_byte)compression_type;
Guy Schalnat0d580581995-07-20 02:43:20 -0500581
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500582 /* Find number of channels */
Guy Schalnat0d580581995-07-20 02:43:20 -0500583 switch (png_ptr->color_type)
584 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600585 default: /* invalid, png_set_IHDR calls png_error */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500586 case PNG_COLOR_TYPE_GRAY:
587 case PNG_COLOR_TYPE_PALETTE:
Guy Schalnat0d580581995-07-20 02:43:20 -0500588 png_ptr->channels = 1;
589 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500590
Andreas Dilger47a0c421997-05-16 02:46:07 -0500591 case PNG_COLOR_TYPE_RGB:
Guy Schalnat0d580581995-07-20 02:43:20 -0500592 png_ptr->channels = 3;
593 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500594
Andreas Dilger47a0c421997-05-16 02:46:07 -0500595 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500596 png_ptr->channels = 2;
597 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500598
Andreas Dilger47a0c421997-05-16 02:46:07 -0500599 case PNG_COLOR_TYPE_RGB_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500600 png_ptr->channels = 4;
601 break;
602 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600603
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500604 /* Set up other useful info */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600605 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600606 png_ptr->channels);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500607 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500608 png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
609 png_debug1(3, "channels = %d", png_ptr->channels);
Glenn Randers-Pehrsonb764c602011-01-14 21:18:37 -0600610 png_debug1(3, "rowbytes = %lu", (unsigned long)png_ptr->rowbytes);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500611 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600612 color_type, interlace_type, compression_type, filter_type);
Guy Schalnat0d580581995-07-20 02:43:20 -0500613}
614
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500615/* Read and check the palette */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500616void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600617png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500618{
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600619 png_color palette[PNG_MAX_PALETTE_LENGTH];
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600620 int num, i;
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500621#ifdef PNG_POINTER_INDEXING_SUPPORTED
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500622 png_colorp pal_ptr;
623#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500624
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500625 png_debug(1, "in png_handle_PLTE");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500626
Guy Schalnate5a37791996-06-05 15:50:50 -0500627 if (!(png_ptr->mode & PNG_HAVE_IHDR))
628 png_error(png_ptr, "Missing IHDR before PLTE");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500629
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600630 else if (png_ptr->mode & PNG_HAVE_IDAT)
631 {
632 png_warning(png_ptr, "Invalid PLTE after IDAT");
633 png_crc_finish(png_ptr, length);
634 return;
635 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500636
Guy Schalnate5a37791996-06-05 15:50:50 -0500637 else if (png_ptr->mode & PNG_HAVE_PLTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600638 png_error(png_ptr, "Duplicate PLTE chunk");
639
640 png_ptr->mode |= PNG_HAVE_PLTE;
Guy Schalnate5a37791996-06-05 15:50:50 -0500641
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500642 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
643 {
644 png_warning(png_ptr,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600645 "Ignoring PLTE chunk in grayscale PNG");
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500646 png_crc_finish(png_ptr, length);
647 return;
648 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600649
Glenn Randers-Pehrsonb2aca212009-09-23 11:32:37 -0500650#ifndef PNG_READ_OPT_PLTE_SUPPORTED
Guy Schalnate5a37791996-06-05 15:50:50 -0500651 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
652 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600653 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500654 return;
655 }
656#endif
657
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600658 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
Guy Schalnate5a37791996-06-05 15:50:50 -0500659 {
660 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
661 {
662 png_warning(png_ptr, "Invalid palette chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600663 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500664 return;
665 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500666
Guy Schalnate5a37791996-06-05 15:50:50 -0500667 else
668 {
669 png_error(png_ptr, "Invalid palette chunk");
670 }
671 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500672
673 num = (int)length / 3;
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500674
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500675#ifdef PNG_POINTER_INDEXING_SUPPORTED
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500676 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
677 {
678 png_byte buf[3];
679
680 png_crc_read(png_ptr, buf, 3);
681 pal_ptr->red = buf[0];
682 pal_ptr->green = buf[1];
683 pal_ptr->blue = buf[2];
684 }
685#else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600686 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500687 {
688 png_byte buf[3];
689
690 png_crc_read(png_ptr, buf, 3);
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500691 /* Don't depend upon png_color being any order */
Guy Schalnat0d580581995-07-20 02:43:20 -0500692 palette[i].red = buf[0];
693 palette[i].green = buf[1];
694 palette[i].blue = buf[2];
695 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500696#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600697
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600698 /* If we actually need the PLTE chunk (ie for a paletted image), we do
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500699 * whatever the normal CRC configuration tells us. However, if we
700 * have an RGB image, the PLTE can be considered ancillary, so
701 * we will act as though it is.
702 */
Glenn Randers-Pehrsonb2aca212009-09-23 11:32:37 -0500703#ifndef PNG_READ_OPT_PLTE_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600704 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600705#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600706 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500707 png_crc_finish(png_ptr, 0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600708 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600709
Glenn Randers-Pehrsonb2aca212009-09-23 11:32:37 -0500710#ifndef PNG_READ_OPT_PLTE_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600711 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
712 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600713 /* If we don't want to use the data from an ancillary chunk,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600714 * we have two options: an error abort, or a warning and we
715 * ignore the data in this chunk (which should be OK, since
716 * it's considered ancillary for a RGB or RGBA image).
717 */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600718 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
719 {
720 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
721 {
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500722 png_chunk_benign_error(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600723 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600724
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600725 else
726 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600727 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600728 return;
729 }
730 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600731
Andreas Dilger47a0c421997-05-16 02:46:07 -0500732 /* Otherwise, we (optionally) emit a warning and use the chunk. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600733 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
734 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600735 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600736 }
737 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600738#endif
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500739
Andreas Dilger47a0c421997-05-16 02:46:07 -0500740 png_set_PLTE(png_ptr, info_ptr, palette, num);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500741
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500742#ifdef PNG_READ_tRNS_SUPPORTED
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500743 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
744 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600745 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500746 {
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500747 if (png_ptr->num_trans > (png_uint_16)num)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500748 {
749 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500750 png_ptr->num_trans = (png_uint_16)num;
751 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600752
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500753 if (info_ptr->num_trans > (png_uint_16)num)
754 {
755 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
756 info_ptr->num_trans = (png_uint_16)num;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500757 }
758 }
759 }
760#endif
761
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600762}
Guy Schalnate5a37791996-06-05 15:50:50 -0500763
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500764void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600765png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
766{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500767 png_debug(1, "in png_handle_IEND");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500768
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600769 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
770 {
771 png_error(png_ptr, "No image in file");
772 }
773
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600774 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600775
776 if (length != 0)
777 {
778 png_warning(png_ptr, "Incorrect IEND chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600779 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600780
Andreas Dilger47a0c421997-05-16 02:46:07 -0500781 png_crc_finish(png_ptr, length);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500782
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600783 PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
Guy Schalnat0d580581995-07-20 02:43:20 -0500784}
785
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500786#ifdef PNG_READ_gAMA_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500787void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600788png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500789{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600790 png_fixed_point igamma;
Guy Schalnat0d580581995-07-20 02:43:20 -0500791 png_byte buf[4];
792
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500793 png_debug(1, "in png_handle_gAMA");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500794
Guy Schalnate5a37791996-06-05 15:50:50 -0500795 if (!(png_ptr->mode & PNG_HAVE_IHDR))
796 png_error(png_ptr, "Missing IHDR before gAMA");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600797
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600798 else if (png_ptr->mode & PNG_HAVE_IDAT)
799 {
800 png_warning(png_ptr, "Invalid gAMA after IDAT");
801 png_crc_finish(png_ptr, length);
802 return;
803 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600804
Guy Schalnate5a37791996-06-05 15:50:50 -0500805 else if (png_ptr->mode & PNG_HAVE_PLTE)
806 /* Should be an error, but we can cope with it */
807 png_warning(png_ptr, "Out of place gAMA chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600808
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500809 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500810#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600811 && !(info_ptr->valid & PNG_INFO_sRGB)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600812#endif
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600813 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600814 {
815 png_warning(png_ptr, "Duplicate gAMA chunk");
816 png_crc_finish(png_ptr, length);
817 return;
818 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500819
Guy Schalnat0d580581995-07-20 02:43:20 -0500820 if (length != 4)
821 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600822 png_warning(png_ptr, "Incorrect gAMA chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600823 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500824 return;
825 }
826
827 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600828
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600829 if (png_crc_finish(png_ptr, 0))
830 return;
831
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600832 igamma = png_get_fixed_point(NULL, buf);
Glenn Randers-Pehrson33893092010-10-23 13:20:18 -0500833
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600834 /* Check for zero gamma or an error. */
835 if (igamma <= 0)
836 {
837 png_warning(png_ptr,
838 "Ignoring gAMA chunk with out of range gamma");
839
840 return;
841 }
842
843# ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600844 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600845 {
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500846 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600847 {
848 png_warning(png_ptr,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600849 "Ignoring incorrect gAMA value when sRGB is also present");
850
851# ifdef PNG_CONSOLE_IO_SUPPORTED
Glenn Randers-Pehrson79134c62009-02-14 10:32:18 -0600852 fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600853# endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600854 return;
855 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600856 }
857# endif /* PNG_READ_sRGB_SUPPORTED */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600858
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600859# ifdef PNG_READ_GAMMA_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600860 /* Gamma correction on read is supported. */
861 png_ptr->gamma = igamma;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600862# endif
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600863 /* And set the 'info' structure members. */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600864 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500865}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500866#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500867
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500868#ifdef PNG_READ_sBIT_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500869void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600870png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500871{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500872 png_size_t truelen;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600873 png_byte buf[4];
Guy Schalnat69b14481996-01-10 02:56:49 -0600874
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500875 png_debug(1, "in png_handle_sBIT");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500876
Guy Schalnat69b14481996-01-10 02:56:49 -0600877 buf[0] = buf[1] = buf[2] = buf[3] = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500878
Guy Schalnate5a37791996-06-05 15:50:50 -0500879 if (!(png_ptr->mode & PNG_HAVE_IHDR))
880 png_error(png_ptr, "Missing IHDR before sBIT");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600881
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600882 else if (png_ptr->mode & PNG_HAVE_IDAT)
883 {
884 png_warning(png_ptr, "Invalid sBIT after IDAT");
885 png_crc_finish(png_ptr, length);
886 return;
887 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600888
Guy Schalnate5a37791996-06-05 15:50:50 -0500889 else if (png_ptr->mode & PNG_HAVE_PLTE)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600890 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500891 /* Should be an error, but we can cope with it */
892 png_warning(png_ptr, "Out of place sBIT chunk");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600893 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600894
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500895 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600896 {
897 png_warning(png_ptr, "Duplicate sBIT chunk");
898 png_crc_finish(png_ptr, length);
899 return;
900 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500901
Guy Schalnat0d580581995-07-20 02:43:20 -0500902 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600903 truelen = 3;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600904
Guy Schalnat0d580581995-07-20 02:43:20 -0500905 else
Andreas Dilger47a0c421997-05-16 02:46:07 -0500906 truelen = (png_size_t)png_ptr->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500907
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500908 if (length != truelen || length > 4)
Guy Schalnat0d580581995-07-20 02:43:20 -0500909 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600910 png_warning(png_ptr, "Incorrect sBIT chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600911 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600912 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500913 }
914
Andreas Dilger47a0c421997-05-16 02:46:07 -0500915 png_crc_read(png_ptr, buf, truelen);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600916
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600917 if (png_crc_finish(png_ptr, 0))
918 return;
919
Guy Schalnat0d580581995-07-20 02:43:20 -0500920 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
921 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600922 png_ptr->sig_bit.red = buf[0];
923 png_ptr->sig_bit.green = buf[1];
924 png_ptr->sig_bit.blue = buf[2];
925 png_ptr->sig_bit.alpha = buf[3];
Guy Schalnat0d580581995-07-20 02:43:20 -0500926 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600927
Guy Schalnat0d580581995-07-20 02:43:20 -0500928 else
929 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600930 png_ptr->sig_bit.gray = buf[0];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600931 png_ptr->sig_bit.red = buf[0];
932 png_ptr->sig_bit.green = buf[0];
933 png_ptr->sig_bit.blue = buf[0];
Guy Schalnat6d764711995-12-19 03:22:19 -0600934 png_ptr->sig_bit.alpha = buf[1];
Guy Schalnat0d580581995-07-20 02:43:20 -0500935 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600936
Andreas Dilger47a0c421997-05-16 02:46:07 -0500937 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
Guy Schalnat0d580581995-07-20 02:43:20 -0500938}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500939#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500940
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500941#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500942void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600943png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500944{
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500945 png_byte buf[32];
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600946 png_fixed_point x_white, y_white, x_red, y_red, x_green, y_green, x_blue,
947 y_blue;
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600948
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500949 png_debug(1, "in png_handle_cHRM");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500950
Guy Schalnate5a37791996-06-05 15:50:50 -0500951 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600952 png_error(png_ptr, "Missing IHDR before cHRM");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600953
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600954 else if (png_ptr->mode & PNG_HAVE_IDAT)
955 {
956 png_warning(png_ptr, "Invalid cHRM after IDAT");
957 png_crc_finish(png_ptr, length);
958 return;
959 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600960
Guy Schalnate5a37791996-06-05 15:50:50 -0500961 else if (png_ptr->mode & PNG_HAVE_PLTE)
962 /* Should be an error, but we can cope with it */
963 png_warning(png_ptr, "Missing PLTE before cHRM");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600964
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500965 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600966# ifdef PNG_READ_sRGB_SUPPORTED
967 && !(info_ptr->valid & PNG_INFO_sRGB)
968# endif
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600969 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600970 {
971 png_warning(png_ptr, "Duplicate cHRM chunk");
972 png_crc_finish(png_ptr, length);
973 return;
974 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500975
Guy Schalnat0d580581995-07-20 02:43:20 -0500976 if (length != 32)
977 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600978 png_warning(png_ptr, "Incorrect cHRM chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600979 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600980 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500981 }
982
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500983 png_crc_read(png_ptr, buf, 32);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600984
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500985 if (png_crc_finish(png_ptr, 0))
986 return;
987
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600988 x_white = png_get_fixed_point(NULL, buf);
989 y_white = png_get_fixed_point(NULL, buf + 4);
990 x_red = png_get_fixed_point(NULL, buf + 8);
991 y_red = png_get_fixed_point(NULL, buf + 12);
992 x_green = png_get_fixed_point(NULL, buf + 16);
993 y_green = png_get_fixed_point(NULL, buf + 20);
994 x_blue = png_get_fixed_point(NULL, buf + 24);
995 y_blue = png_get_fixed_point(NULL, buf + 28);
Glenn Randers-Pehrson33893092010-10-23 13:20:18 -0500996
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -0600997 if (x_white == PNG_FIXED_ERROR ||
998 y_white == PNG_FIXED_ERROR ||
999 x_red == PNG_FIXED_ERROR ||
1000 y_red == PNG_FIXED_ERROR ||
1001 x_green == PNG_FIXED_ERROR ||
1002 y_green == PNG_FIXED_ERROR ||
1003 x_blue == PNG_FIXED_ERROR ||
1004 y_blue == PNG_FIXED_ERROR)
1005 {
1006 png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities");
1007 return;
1008 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001009
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001010#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -05001011 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001012 {
1013 if (PNG_OUT_OF_RANGE(x_white, 31270, 1000) ||
1014 PNG_OUT_OF_RANGE(y_white, 32900, 1000) ||
1015 PNG_OUT_OF_RANGE(x_red, 64000L, 1000) ||
1016 PNG_OUT_OF_RANGE(y_red, 33000, 1000) ||
1017 PNG_OUT_OF_RANGE(x_green, 30000, 1000) ||
1018 PNG_OUT_OF_RANGE(y_green, 60000L, 1000) ||
1019 PNG_OUT_OF_RANGE(x_blue, 15000, 1000) ||
1020 PNG_OUT_OF_RANGE(y_blue, 6000, 1000))
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001021 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001022 png_warning(png_ptr,
1023 "Ignoring incorrect cHRM value when sRGB is also present");
1024
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05001025#ifdef PNG_CONSOLE_IO_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001026 fprintf(stderr, "wx=%d, wy=%d, rx=%d, ry=%d\n",
1027 x_white, y_white, x_red, y_red);
1028
1029 fprintf(stderr, "gx=%d, gy=%d, bx=%d, by=%d\n",
1030 x_green, y_green, x_blue, y_blue);
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05001031#endif /* PNG_CONSOLE_IO_SUPPORTED */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001032 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001033 return;
1034 }
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001035#endif /* PNG_READ_sRGB_SUPPORTED */
1036
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001037 png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red,
1038 x_green, y_green, x_blue, y_blue);
Guy Schalnat0d580581995-07-20 02:43:20 -05001039}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001040#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001041
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001042#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001043void /* PRIVATE */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001044png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1045{
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001046 int intent;
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001047 png_byte buf[1];
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001048
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001049 png_debug(1, "in png_handle_sRGB");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001050
1051 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1052 png_error(png_ptr, "Missing IHDR before sRGB");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001053
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001054 else if (png_ptr->mode & PNG_HAVE_IDAT)
1055 {
1056 png_warning(png_ptr, "Invalid sRGB after IDAT");
1057 png_crc_finish(png_ptr, length);
1058 return;
1059 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001060
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001061 else if (png_ptr->mode & PNG_HAVE_PLTE)
1062 /* Should be an error, but we can cope with it */
1063 png_warning(png_ptr, "Out of place sRGB chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06001064
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001065 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001066 {
1067 png_warning(png_ptr, "Duplicate sRGB chunk");
1068 png_crc_finish(png_ptr, length);
1069 return;
1070 }
1071
1072 if (length != 1)
1073 {
1074 png_warning(png_ptr, "Incorrect sRGB chunk length");
1075 png_crc_finish(png_ptr, length);
1076 return;
1077 }
1078
1079 png_crc_read(png_ptr, buf, 1);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001080
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001081 if (png_crc_finish(png_ptr, 0))
1082 return;
1083
1084 intent = buf[0];
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001085
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001086 /* Check for bad intent */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -06001087 if (intent >= PNG_sRGB_INTENT_LAST)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001088 {
1089 png_warning(png_ptr, "Unknown sRGB intent");
1090 return;
1091 }
1092
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -06001093#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -06001094 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001095 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001096 if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500L, 500))
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06001097 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -05001098 png_warning(png_ptr,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001099 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05001100#ifdef PNG_CONSOLE_IO_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001101 fprintf(stderr, "incorrect gamma=(%d/100000)\n", info_ptr->gamma);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001102#endif
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06001103 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001104 }
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06001105#endif /* PNG_READ_gAMA_SUPPORTED */
1106
1107#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -06001108 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001109 if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) ||
1110 PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) ||
1111 PNG_OUT_OF_RANGE(info_ptr->x_red, 64000L, 1000) ||
1112 PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) ||
1113 PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) ||
1114 PNG_OUT_OF_RANGE(info_ptr->y_green, 60000L, 1000) ||
1115 PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) ||
1116 PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000))
1117 {
1118 png_warning(png_ptr,
1119 "Ignoring incorrect cHRM value when sRGB is also present");
1120 }
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06001121#endif /* PNG_READ_cHRM_SUPPORTED */
1122
1123 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
1124}
1125#endif /* PNG_READ_sRGB_SUPPORTED */
1126
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001127#ifdef PNG_READ_iCCP_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001128void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001129png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1130/* Note: this does not properly handle chunks that are > 64K under DOS */
1131{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001132 png_byte compression_type;
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -06001133 png_bytep pC;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001134 png_charp profile;
1135 png_uint_32 skip = 0;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001136 png_uint_32 profile_size;
1137 png_alloc_size_t profile_length;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001138 png_size_t slength, prefix_length, data_length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001139
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001140 png_debug(1, "in png_handle_iCCP");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001141
1142 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1143 png_error(png_ptr, "Missing IHDR before iCCP");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001144
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001145 else if (png_ptr->mode & PNG_HAVE_IDAT)
1146 {
1147 png_warning(png_ptr, "Invalid iCCP after IDAT");
1148 png_crc_finish(png_ptr, length);
1149 return;
1150 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001151
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001152 else if (png_ptr->mode & PNG_HAVE_PLTE)
1153 /* Should be an error, but we can cope with it */
1154 png_warning(png_ptr, "Out of place iCCP chunk");
1155
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001156 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001157 {
1158 png_warning(png_ptr, "Duplicate iCCP chunk");
1159 png_crc_finish(png_ptr, length);
1160 return;
1161 }
1162
1163#ifdef PNG_MAX_MALLOC_64K
1164 if (length > (png_uint_32)65535L)
1165 {
1166 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1167 skip = length - (png_uint_32)65535L;
1168 length = (png_uint_32)65535L;
1169 }
1170#endif
1171
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001172 png_free(png_ptr, png_ptr->chunkdata);
1173 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001174 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001175 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001176
1177 if (png_crc_finish(png_ptr, skip))
1178 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001179 png_free(png_ptr, png_ptr->chunkdata);
1180 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001181 return;
1182 }
1183
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001184 png_ptr->chunkdata[slength] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001185
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001186 for (profile = png_ptr->chunkdata; *profile; profile++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001187 /* Empty loop to find end of name */ ;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001188
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001189 ++profile;
1190
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001191 /* There should be at least one zero (the compression type byte)
1192 * following the separator, and we should be on it
1193 */
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001194 if (profile >= png_ptr->chunkdata + slength - 1)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001195 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001196 png_free(png_ptr, png_ptr->chunkdata);
1197 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001198 png_warning(png_ptr, "Malformed iCCP chunk");
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001199 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001200 }
1201
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001202 /* Compression_type should always be zero */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001203 compression_type = *profile++;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001204
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001205 if (compression_type)
1206 {
1207 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001208 compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001209 wrote nonzero) */
1210 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001211
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001212 prefix_length = profile - png_ptr->chunkdata;
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -05001213 png_decompress_chunk(png_ptr, compression_type,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001214 slength, prefix_length, &data_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001215
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001216 profile_length = data_length - prefix_length;
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06001217
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001218 if (prefix_length > data_length || profile_length < 4)
Glenn Randers-Pehrsonb1828932001-06-23 08:03:17 -05001219 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001220 png_free(png_ptr, png_ptr->chunkdata);
1221 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrsonb1828932001-06-23 08:03:17 -05001222 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1223 return;
1224 }
1225
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06001226 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001227 pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001228 profile_size = ((*(pC )) << 24) |
1229 ((*(pC + 1)) << 16) |
1230 ((*(pC + 2)) << 8) |
1231 ((*(pC + 3)) );
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001232
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001233 /* NOTE: the following guarantees that 'profile_length' fits into 32 bits,
1234 * because profile_size is a 32 bit value.
1235 */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001236 if (profile_size < profile_length)
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001237 profile_length = profile_size;
1238
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001239 /* And the following guarantees that profile_size == profile_length. */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001240 if (profile_size > profile_length)
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001241 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001242 png_free(png_ptr, png_ptr->chunkdata);
1243 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001244#ifdef PNG_STDIO_SUPPORTED
1245 {
1246 char umsg[80];
1247
1248 png_snprintf2(umsg, 80,
1249 "Ignoring iCCP chunk with declared size = %u "
1250 "and actual length = %u",
1251 (unsigned int) profile_size,
1252 (unsigned int) profile_length);
1253 png_warning(png_ptr, umsg);
1254 }
1255#else
1256 png_warning(png_ptr,
1257 "Ignoring iCCP chunk with uncompressed size mismatch");
1258#endif
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001259 return;
1260 }
1261
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001262 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001263 compression_type, (png_bytep)png_ptr->chunkdata + prefix_length,
1264 profile_size);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001265 png_free(png_ptr, png_ptr->chunkdata);
1266 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001267}
1268#endif /* PNG_READ_iCCP_SUPPORTED */
1269
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001270#ifdef PNG_READ_sPLT_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001271void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001272png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1273/* Note: this does not properly handle chunks that are > 64K under DOS */
1274{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001275 png_bytep entry_start;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001276 png_sPLT_t new_palette;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001277 png_sPLT_entryp pp;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001278 png_uint_32 data_length;
1279 int entry_size, i;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001280 png_uint_32 skip = 0;
1281 png_size_t slength;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001282 png_uint_32 dl;
1283 png_size_t max_dl;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001284
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001285 png_debug(1, "in png_handle_sPLT");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001286
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06001287#ifdef PNG_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrson7824a702009-06-13 10:05:05 -05001288
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05001289 if (png_ptr->user_chunk_cache_max != 0)
1290 {
1291 if (png_ptr->user_chunk_cache_max == 1)
1292 {
1293 png_crc_finish(png_ptr, length);
1294 return;
1295 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001296
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05001297 if (--png_ptr->user_chunk_cache_max == 1)
1298 {
1299 png_warning(png_ptr, "No space in chunk cache for sPLT");
1300 png_crc_finish(png_ptr, length);
1301 return;
1302 }
1303 }
1304#endif
1305
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001306 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1307 png_error(png_ptr, "Missing IHDR before sPLT");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001308
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001309 else if (png_ptr->mode & PNG_HAVE_IDAT)
1310 {
1311 png_warning(png_ptr, "Invalid sPLT after IDAT");
1312 png_crc_finish(png_ptr, length);
1313 return;
1314 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001315
1316#ifdef PNG_MAX_MALLOC_64K
1317 if (length > (png_uint_32)65535L)
1318 {
1319 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1320 skip = length - (png_uint_32)65535L;
1321 length = (png_uint_32)65535L;
1322 }
1323#endif
1324
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001325 png_free(png_ptr, png_ptr->chunkdata);
1326 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001327
1328 /* WARNING: this may break if size_t is less than 32 bits; it is assumed
1329 * that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a
1330 * potential breakage point if the types in pngconf.h aren't exactly right.
1331 */
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001332 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001333 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001334
1335 if (png_crc_finish(png_ptr, skip))
1336 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001337 png_free(png_ptr, png_ptr->chunkdata);
1338 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001339 return;
1340 }
1341
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001342 png_ptr->chunkdata[slength] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001343
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06001344 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
1345 entry_start++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001346 /* Empty loop to find end of name */ ;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001347
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001348 ++entry_start;
1349
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001350 /* A sample depth should follow the separator, and we should be on it */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001351 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001352 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001353 png_free(png_ptr, png_ptr->chunkdata);
1354 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001355 png_warning(png_ptr, "malformed sPLT chunk");
1356 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001357 }
1358
1359 new_palette.depth = *entry_start++;
Glenn Randers-Pehrsona565f0e2010-03-06 08:24:45 -06001360 entry_size = (new_palette.depth == 8 ? 6 : 10);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001361 /* This must fit in a png_uint_32 because it is derived from the original
1362 * chunk data length (and use 'length', not 'slength' here for clarity -
1363 * they are guaranteed to be the same, see the tests above.)
1364 */
1365 data_length = length - (png_uint_32)(entry_start -
1366 (png_bytep)png_ptr->chunkdata);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001367
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001368 /* Integrity-check the data length */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001369 if (data_length % entry_size)
1370 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001371 png_free(png_ptr, png_ptr->chunkdata);
1372 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001373 png_warning(png_ptr, "sPLT chunk has bad length");
1374 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001375 }
1376
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001377 dl = (png_int_32)(data_length / entry_size);
1378 max_dl = PNG_SIZE_MAX / png_sizeof(png_sPLT_entry);
1379
1380 if (dl > max_dl)
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001381 {
1382 png_warning(png_ptr, "sPLT chunk too long");
1383 return;
1384 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001385
1386 new_palette.nentries = (png_int_32)(data_length / entry_size);
1387
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001388 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001389 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001390
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001391 if (new_palette.entries == NULL)
1392 {
1393 png_warning(png_ptr, "sPLT chunk requires too much memory");
1394 return;
1395 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001396
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05001397#ifdef PNG_POINTER_INDEXING_SUPPORTED
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001398 for (i = 0; i < new_palette.nentries; i++)
1399 {
Glenn Randers-Pehrson90b878c2009-10-07 12:44:35 -05001400 pp = new_palette.entries + i;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001401
1402 if (new_palette.depth == 8)
1403 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001404 pp->red = *entry_start++;
1405 pp->green = *entry_start++;
1406 pp->blue = *entry_start++;
1407 pp->alpha = *entry_start++;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001408 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001409
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001410 else
1411 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001412 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1413 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1414 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1415 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001416 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001417
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001418 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1419 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001420#else
1421 pp = new_palette.entries;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001422
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001423 for (i = 0; i < new_palette.nentries; i++)
1424 {
1425
1426 if (new_palette.depth == 8)
1427 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001428 pp[i].red = *entry_start++;
1429 pp[i].green = *entry_start++;
1430 pp[i].blue = *entry_start++;
1431 pp[i].alpha = *entry_start++;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001432 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001433
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001434 else
1435 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001436 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1437 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1438 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1439 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001440 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001441
Glenn Randers-Pehrsonf27592a2011-03-21 18:05:40 -05001442 pp[i].frequency = png_get_uint_16(entry_start); entry_start += 2;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001443 }
1444#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001445
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001446 /* Discard all chunk data except the name and stash that */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001447 new_palette.name = png_ptr->chunkdata;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001448
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001449 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001450
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001451 png_free(png_ptr, png_ptr->chunkdata);
1452 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001453 png_free(png_ptr, new_palette.entries);
1454}
1455#endif /* PNG_READ_sPLT_SUPPORTED */
1456
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001457#ifdef PNG_READ_tRNS_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001458void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001459png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001460{
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001461 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001462
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001463 png_debug(1, "in png_handle_tRNS");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001464
Guy Schalnate5a37791996-06-05 15:50:50 -05001465 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1466 png_error(png_ptr, "Missing IHDR before tRNS");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001467
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001468 else if (png_ptr->mode & PNG_HAVE_IDAT)
1469 {
1470 png_warning(png_ptr, "Invalid tRNS after IDAT");
1471 png_crc_finish(png_ptr, length);
1472 return;
1473 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001474
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001475 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001476 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001477 png_warning(png_ptr, "Duplicate tRNS chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001478 png_crc_finish(png_ptr, length);
1479 return;
1480 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001481
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001482 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001483 {
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001484 png_byte buf[2];
Guy Schalnat0d580581995-07-20 02:43:20 -05001485
1486 if (length != 2)
1487 {
Guy Schalnat69b14481996-01-10 02:56:49 -06001488 png_warning(png_ptr, "Incorrect tRNS chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001489 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001490 return;
1491 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001492
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001493 png_crc_read(png_ptr, buf, 2);
1494 png_ptr->num_trans = 1;
Glenn Randers-Pehrson56f63962008-10-06 10:16:17 -05001495 png_ptr->trans_color.gray = png_get_uint_16(buf);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001496 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001497
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001498 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1499 {
1500 png_byte buf[6];
1501
1502 if (length != 6)
1503 {
1504 png_warning(png_ptr, "Incorrect tRNS chunk length");
1505 png_crc_finish(png_ptr, length);
1506 return;
1507 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001508
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001509 png_crc_read(png_ptr, buf, (png_size_t)length);
1510 png_ptr->num_trans = 1;
Glenn Randers-Pehrson56f63962008-10-06 10:16:17 -05001511 png_ptr->trans_color.red = png_get_uint_16(buf);
1512 png_ptr->trans_color.green = png_get_uint_16(buf + 2);
1513 png_ptr->trans_color.blue = png_get_uint_16(buf + 4);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001514 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001515
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001516 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1517 {
1518 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1519 {
1520 /* Should be an error, but we can cope with it. */
1521 png_warning(png_ptr, "Missing PLTE before tRNS");
1522 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001523
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001524 if (length > (png_uint_32)png_ptr->num_palette ||
1525 length > PNG_MAX_PALETTE_LENGTH)
1526 {
1527 png_warning(png_ptr, "Incorrect tRNS chunk length");
1528 png_crc_finish(png_ptr, length);
1529 return;
1530 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001531
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001532 if (length == 0)
1533 {
1534 png_warning(png_ptr, "Zero length tRNS chunk");
1535 png_crc_finish(png_ptr, length);
1536 return;
1537 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001538
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001539 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1540 png_ptr->num_trans = (png_uint_16)length;
1541 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001542
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001543 else
Guy Schalnate5a37791996-06-05 15:50:50 -05001544 {
1545 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001546 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001547 return;
1548 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001549
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001550 if (png_crc_finish(png_ptr, 0))
Glenn Randers-Pehrsona7dbcba2007-05-15 16:16:34 -05001551 {
1552 png_ptr->num_trans = 0;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001553 return;
Glenn Randers-Pehrsona7dbcba2007-05-15 16:16:34 -05001554 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001555
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001556 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001557 &(png_ptr->trans_color));
Guy Schalnat0d580581995-07-20 02:43:20 -05001558}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001559#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001560
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001561#ifdef PNG_READ_bKGD_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001562void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001563png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001564{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001565 png_size_t truelen;
Guy Schalnat0d580581995-07-20 02:43:20 -05001566 png_byte buf[6];
1567
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001568 png_debug(1, "in png_handle_bKGD");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001569
Guy Schalnate5a37791996-06-05 15:50:50 -05001570 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1571 png_error(png_ptr, "Missing IHDR before bKGD");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001572
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001573 else if (png_ptr->mode & PNG_HAVE_IDAT)
1574 {
1575 png_warning(png_ptr, "Invalid bKGD after IDAT");
1576 png_crc_finish(png_ptr, length);
1577 return;
1578 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001579
Guy Schalnate5a37791996-06-05 15:50:50 -05001580 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001581 !(png_ptr->mode & PNG_HAVE_PLTE))
Guy Schalnate5a37791996-06-05 15:50:50 -05001582 {
1583 png_warning(png_ptr, "Missing PLTE before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001584 png_crc_finish(png_ptr, length);
1585 return;
1586 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001587
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001588 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001589 {
1590 png_warning(png_ptr, "Duplicate bKGD chunk");
1591 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001592 return;
1593 }
1594
Guy Schalnat0d580581995-07-20 02:43:20 -05001595 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1596 truelen = 1;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001597
Guy Schalnat0d580581995-07-20 02:43:20 -05001598 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1599 truelen = 6;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001600
Guy Schalnat0d580581995-07-20 02:43:20 -05001601 else
1602 truelen = 2;
1603
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001604 if (length != truelen)
Guy Schalnat0d580581995-07-20 02:43:20 -05001605 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001606 png_warning(png_ptr, "Incorrect bKGD chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001607 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001608 return;
1609 }
1610
Andreas Dilger47a0c421997-05-16 02:46:07 -05001611 png_crc_read(png_ptr, buf, truelen);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001612
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001613 if (png_crc_finish(png_ptr, 0))
1614 return;
1615
Guy Schalnate5a37791996-06-05 15:50:50 -05001616 /* We convert the index value into RGB components so that we can allow
1617 * arbitrary RGB values for background when we have transparency, and
1618 * so it is easy to determine the RGB values of the background color
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001619 * from the info_ptr struct.
1620 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001621 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnate5a37791996-06-05 15:50:50 -05001622 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001623 png_ptr->background.index = buf[0];
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001624
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001625 if (info_ptr && info_ptr->num_palette)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001626 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001627 if (buf[0] >= info_ptr->num_palette)
1628 {
1629 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1630 return;
1631 }
1632
1633 png_ptr->background.red =
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001634 (png_uint_16)png_ptr->palette[buf[0]].red;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001635
1636 png_ptr->background.green =
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001637 (png_uint_16)png_ptr->palette[buf[0]].green;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001638
1639 png_ptr->background.blue =
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001640 (png_uint_16)png_ptr->palette[buf[0]].blue;
1641 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001642 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001643
Andreas Dilger47a0c421997-05-16 02:46:07 -05001644 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
Guy Schalnate5a37791996-06-05 15:50:50 -05001645 {
1646 png_ptr->background.red =
1647 png_ptr->background.green =
1648 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -05001649 png_ptr->background.gray = png_get_uint_16(buf);
Guy Schalnate5a37791996-06-05 15:50:50 -05001650 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001651
Guy Schalnat0d580581995-07-20 02:43:20 -05001652 else
1653 {
1654 png_ptr->background.red = png_get_uint_16(buf);
1655 png_ptr->background.green = png_get_uint_16(buf + 2);
1656 png_ptr->background.blue = png_get_uint_16(buf + 4);
1657 }
1658
Andreas Dilger47a0c421997-05-16 02:46:07 -05001659 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
Guy Schalnat0d580581995-07-20 02:43:20 -05001660}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001661#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001662
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001663#ifdef PNG_READ_hIST_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001664void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001665png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001666{
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001667 unsigned int num, i;
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001668 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
Guy Schalnat0d580581995-07-20 02:43:20 -05001669
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001670 png_debug(1, "in png_handle_hIST");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001671
Guy Schalnate5a37791996-06-05 15:50:50 -05001672 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1673 png_error(png_ptr, "Missing IHDR before hIST");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001674
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001675 else if (png_ptr->mode & PNG_HAVE_IDAT)
1676 {
1677 png_warning(png_ptr, "Invalid hIST after IDAT");
1678 png_crc_finish(png_ptr, length);
1679 return;
1680 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001681
Guy Schalnate5a37791996-06-05 15:50:50 -05001682 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1683 {
1684 png_warning(png_ptr, "Missing PLTE before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001685 png_crc_finish(png_ptr, length);
1686 return;
1687 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001688
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001689 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001690 {
1691 png_warning(png_ptr, "Duplicate hIST chunk");
1692 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001693 return;
1694 }
1695
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001696 num = length / 2 ;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001697
1698 if (num != (unsigned int)png_ptr->num_palette || num >
1699 (unsigned int)PNG_MAX_PALETTE_LENGTH)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001700 {
1701 png_warning(png_ptr, "Incorrect hIST chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001702 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001703 return;
1704 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001705
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001706 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001707 {
1708 png_byte buf[2];
1709
1710 png_crc_read(png_ptr, buf, 2);
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001711 readbuf[i] = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001712 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001713
1714 if (png_crc_finish(png_ptr, 0))
1715 return;
1716
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001717 png_set_hIST(png_ptr, info_ptr, readbuf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001718}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001719#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001720
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001721#ifdef PNG_READ_pHYs_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001722void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001723png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001724{
1725 png_byte buf[9];
1726 png_uint_32 res_x, res_y;
1727 int unit_type;
1728
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001729 png_debug(1, "in png_handle_pHYs");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001730
Guy Schalnate5a37791996-06-05 15:50:50 -05001731 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001732 png_error(png_ptr, "Missing IHDR before pHYs");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001733
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001734 else if (png_ptr->mode & PNG_HAVE_IDAT)
1735 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001736 png_warning(png_ptr, "Invalid pHYs after IDAT");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001737 png_crc_finish(png_ptr, length);
1738 return;
1739 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001740
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001741 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001742 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001743 png_warning(png_ptr, "Duplicate pHYs chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001744 png_crc_finish(png_ptr, length);
1745 return;
1746 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001747
Guy Schalnat0d580581995-07-20 02:43:20 -05001748 if (length != 9)
1749 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001750 png_warning(png_ptr, "Incorrect pHYs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001751 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001752 return;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001753 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001754
1755 png_crc_read(png_ptr, buf, 9);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001756
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001757 if (png_crc_finish(png_ptr, 0))
1758 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001759
1760 res_x = png_get_uint_32(buf);
1761 res_y = png_get_uint_32(buf + 4);
1762 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001763 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
Guy Schalnat0d580581995-07-20 02:43:20 -05001764}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001765#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001766
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001767#ifdef PNG_READ_oFFs_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001768void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001769png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001770{
1771 png_byte buf[9];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001772 png_int_32 offset_x, offset_y;
Guy Schalnat0d580581995-07-20 02:43:20 -05001773 int unit_type;
1774
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001775 png_debug(1, "in png_handle_oFFs");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001776
Guy Schalnate5a37791996-06-05 15:50:50 -05001777 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1778 png_error(png_ptr, "Missing IHDR before oFFs");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001779
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001780 else if (png_ptr->mode & PNG_HAVE_IDAT)
1781 {
1782 png_warning(png_ptr, "Invalid oFFs after IDAT");
1783 png_crc_finish(png_ptr, length);
1784 return;
1785 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001786
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001787 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001788 {
1789 png_warning(png_ptr, "Duplicate oFFs chunk");
1790 png_crc_finish(png_ptr, length);
1791 return;
1792 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001793
Guy Schalnat0d580581995-07-20 02:43:20 -05001794 if (length != 9)
1795 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001796 png_warning(png_ptr, "Incorrect oFFs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001797 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001798 return;
1799 }
1800
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001801 png_crc_read(png_ptr, buf, 9);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001802
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001803 if (png_crc_finish(png_ptr, 0))
1804 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001805
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001806 offset_x = png_get_int_32(buf);
1807 offset_y = png_get_int_32(buf + 4);
Guy Schalnat0d580581995-07-20 02:43:20 -05001808 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001809 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1810}
1811#endif
1812
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001813#ifdef PNG_READ_pCAL_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001814/* Read the pCAL chunk (described in the PNG Extensions document) */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001815void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001816png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1817{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001818 png_int_32 X0, X1;
1819 png_byte type, nparams;
1820 png_charp buf, units, endptr;
1821 png_charpp params;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001822 png_size_t slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001823 int i;
1824
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001825 png_debug(1, "in png_handle_pCAL");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001826
1827 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1828 png_error(png_ptr, "Missing IHDR before pCAL");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001829
Andreas Dilger47a0c421997-05-16 02:46:07 -05001830 else if (png_ptr->mode & PNG_HAVE_IDAT)
1831 {
1832 png_warning(png_ptr, "Invalid pCAL after IDAT");
1833 png_crc_finish(png_ptr, length);
1834 return;
1835 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001836
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001837 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
Andreas Dilger47a0c421997-05-16 02:46:07 -05001838 {
1839 png_warning(png_ptr, "Duplicate pCAL chunk");
1840 png_crc_finish(png_ptr, length);
1841 return;
1842 }
1843
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001844 png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)",
1845 length + 1);
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001846 png_free(png_ptr, png_ptr->chunkdata);
1847 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001848
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001849 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001850 {
1851 png_warning(png_ptr, "No memory for pCAL purpose");
1852 return;
1853 }
1854
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001855 slength = (png_size_t)length;
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001856 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001857
1858 if (png_crc_finish(png_ptr, 0))
1859 {
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001860 png_free(png_ptr, png_ptr->chunkdata);
1861 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001862 return;
1863 }
1864
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001865 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001866
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001867 png_debug(3, "Finding end of pCAL purpose string");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001868 for (buf = png_ptr->chunkdata; *buf; buf++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001869 /* Empty loop */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001870
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001871 endptr = png_ptr->chunkdata + slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001872
1873 /* We need to have at least 12 bytes after the purpose string
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001874 * in order to get the parameter information.
1875 */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001876 if (endptr <= buf + 12)
1877 {
1878 png_warning(png_ptr, "Invalid pCAL data");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001879 png_free(png_ptr, png_ptr->chunkdata);
1880 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001881 return;
1882 }
1883
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001884 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001885 X0 = png_get_int_32((png_bytep)buf+1);
1886 X1 = png_get_int_32((png_bytep)buf+5);
1887 type = buf[9];
1888 nparams = buf[10];
1889 units = buf + 11;
1890
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001891 png_debug(3, "Checking pCAL equation type and number of parameters");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001892 /* Check that we have the right number of parameters for known
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001893 * equation types.
1894 */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001895 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1896 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1897 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1898 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1899 {
1900 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001901 png_free(png_ptr, png_ptr->chunkdata);
1902 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001903 return;
1904 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001905
Andreas Dilger47a0c421997-05-16 02:46:07 -05001906 else if (type >= PNG_EQUATION_LAST)
1907 {
1908 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1909 }
1910
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001911 for (buf = units; *buf; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001912 /* Empty loop to move past the units string. */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001913
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001914 png_debug(3, "Allocating pCAL parameters array");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001915
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001916 params = (png_charpp)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001917 (png_size_t)(nparams * png_sizeof(png_charp)));
1918
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001919 if (params == NULL)
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001920 {
1921 png_free(png_ptr, png_ptr->chunkdata);
1922 png_ptr->chunkdata = NULL;
1923 png_warning(png_ptr, "No memory for pCAL params");
1924 return;
1925 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001926
1927 /* Get pointers to the start of each parameter string. */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001928 for (i = 0; i < (int)nparams; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001929 {
1930 buf++; /* Skip the null string terminator from previous parameter. */
1931
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001932 png_debug1(3, "Reading pCAL parameter %d", i);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001933
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001934 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001935 /* Empty loop to move past each parameter string */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001936
1937 /* Make sure we haven't run out of data yet */
1938 if (buf > endptr)
1939 {
1940 png_warning(png_ptr, "Invalid pCAL data");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001941 png_free(png_ptr, png_ptr->chunkdata);
1942 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001943 png_free(png_ptr, params);
1944 return;
1945 }
1946 }
1947
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001948 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001949 units, params);
1950
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001951 png_free(png_ptr, png_ptr->chunkdata);
1952 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001953 png_free(png_ptr, params);
Guy Schalnat0d580581995-07-20 02:43:20 -05001954}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001955#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001956
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001957#ifdef PNG_READ_sCAL_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001958/* Read the sCAL chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001959void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001960png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1961{
John Bowler168a4332011-01-16 19:32:22 -06001962 png_size_t slength, i;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001963 int state;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001964
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001965 png_debug(1, "in png_handle_sCAL");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001966
1967 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1968 png_error(png_ptr, "Missing IHDR before sCAL");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001969
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001970 else if (png_ptr->mode & PNG_HAVE_IDAT)
1971 {
1972 png_warning(png_ptr, "Invalid sCAL after IDAT");
1973 png_crc_finish(png_ptr, length);
1974 return;
1975 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001976
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001977 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001978 {
1979 png_warning(png_ptr, "Duplicate sCAL chunk");
1980 png_crc_finish(png_ptr, length);
1981 return;
1982 }
1983
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001984 png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)",
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001985 length + 1);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001986
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001987 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001988
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001989 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001990 {
1991 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001992 png_crc_finish(png_ptr, length);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001993 return;
1994 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001995
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001996 slength = (png_size_t)length;
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001997 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06001998 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001999
2000 if (png_crc_finish(png_ptr, 0))
2001 {
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05002002 png_free(png_ptr, png_ptr->chunkdata);
2003 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002004 return;
2005 }
2006
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002007 /* Validate the unit. */
2008 if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2)
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05002009 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002010 png_warning(png_ptr, "Invalid sCAL ignored: invalid unit");
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -05002011 png_free(png_ptr, png_ptr->chunkdata);
2012 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05002013 return;
2014 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002015
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002016 /* Validate the ASCII numbers, need two ASCII numbers separated by
2017 * a '\0' and they need to fit exactly in the chunk data.
2018 */
John Bowler168a4332011-01-16 19:32:22 -06002019 i = 0;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002020 state = 0;
Glenn Randers-Pehrsonccadcae2010-10-23 17:29:13 -05002021
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002022 if (png_ptr->chunkdata[1] == 45 /* negative width */ ||
John Bowler168a4332011-01-16 19:32:22 -06002023 !png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) ||
2024 i >= slength || png_ptr->chunkdata[i++] != 0)
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002025 png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format");
2026
2027 else
Glenn Randers-Pehrson20788d32011-01-06 09:01:04 -06002028 {
John Bowler168a4332011-01-16 19:32:22 -06002029 png_size_t heighti = i;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002030
John Bowler168a4332011-01-16 19:32:22 -06002031 if (png_ptr->chunkdata[i] == 45 /* negative height */ ||
2032 !png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) ||
2033 i != slength)
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002034 png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format");
2035
2036 else
2037 /* This is the (only) success case. */
2038 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0],
2039 png_ptr->chunkdata+1, png_ptr->chunkdata+heighti);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002040 }
2041
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002042 /* Clean up - just free the temporarily allocated buffer. */
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05002043 png_free(png_ptr, png_ptr->chunkdata);
2044 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002045}
2046#endif
2047
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002048#ifdef PNG_READ_tIME_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002049void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002050png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05002051{
2052 png_byte buf[7];
2053 png_time mod_time;
2054
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002055 png_debug(1, "in png_handle_tIME");
Andreas Dilger47a0c421997-05-16 02:46:07 -05002056
Guy Schalnate5a37791996-06-05 15:50:50 -05002057 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002058 png_error(png_ptr, "Out of place tIME chunk");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002059
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002060 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002061 {
2062 png_warning(png_ptr, "Duplicate tIME chunk");
2063 png_crc_finish(png_ptr, length);
2064 return;
2065 }
2066
2067 if (png_ptr->mode & PNG_HAVE_IDAT)
2068 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnate5a37791996-06-05 15:50:50 -05002069
Guy Schalnat0d580581995-07-20 02:43:20 -05002070 if (length != 7)
2071 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002072 png_warning(png_ptr, "Incorrect tIME chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002073 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05002074 return;
2075 }
2076
2077 png_crc_read(png_ptr, buf, 7);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002078
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002079 if (png_crc_finish(png_ptr, 0))
2080 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05002081
2082 mod_time.second = buf[6];
2083 mod_time.minute = buf[5];
2084 mod_time.hour = buf[4];
2085 mod_time.day = buf[3];
2086 mod_time.month = buf[2];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002087 mod_time.year = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05002088
Andreas Dilger47a0c421997-05-16 02:46:07 -05002089 png_set_tIME(png_ptr, info_ptr, &mod_time);
Guy Schalnat0d580581995-07-20 02:43:20 -05002090}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002091#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002092
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002093#ifdef PNG_READ_tEXt_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002094/* Note: this does not properly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002095void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002096png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05002097{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002098 png_textp text_ptr;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002099 png_charp key;
Guy Schalnat6d764711995-12-19 03:22:19 -06002100 png_charp text;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002101 png_uint_32 skip = 0;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002102 png_size_t slength;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002103 int ret;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002104
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002105 png_debug(1, "in png_handle_tEXt");
Guy Schalnat0d580581995-07-20 02:43:20 -05002106
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06002107#ifdef PNG_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002108 if (png_ptr->user_chunk_cache_max != 0)
2109 {
2110 if (png_ptr->user_chunk_cache_max == 1)
2111 {
2112 png_crc_finish(png_ptr, length);
2113 return;
2114 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002115
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002116 if (--png_ptr->user_chunk_cache_max == 1)
2117 {
2118 png_warning(png_ptr, "No space in chunk cache for tEXt");
2119 png_crc_finish(png_ptr, length);
2120 return;
2121 }
2122 }
2123#endif
2124
Guy Schalnate5a37791996-06-05 15:50:50 -05002125 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2126 png_error(png_ptr, "Missing IHDR before tEXt");
2127
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002128 if (png_ptr->mode & PNG_HAVE_IDAT)
2129 png_ptr->mode |= PNG_AFTER_IDAT;
2130
Andreas Dilger47a0c421997-05-16 02:46:07 -05002131#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002132 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002133 {
2134 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002135 skip = length - (png_uint_32)65535L;
2136 length = (png_uint_32)65535L;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002137 }
2138#endif
2139
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002140 png_free(png_ptr, png_ptr->chunkdata);
2141
2142 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002143
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002144 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002145 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05002146 png_warning(png_ptr, "No memory to process text chunk");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002147 return;
2148 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002149
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002150 slength = (png_size_t)length;
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002151 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002152
2153 if (png_crc_finish(png_ptr, skip))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002154 {
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002155 png_free(png_ptr, png_ptr->chunkdata);
2156 png_ptr->chunkdata = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002157 return;
2158 }
2159
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002160 key = png_ptr->chunkdata;
2161
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002162 key[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05002163
2164 for (text = key; *text; text++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002165 /* Empty loop to find end of key */ ;
Guy Schalnat0d580581995-07-20 02:43:20 -05002166
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002167 if (text != key + slength)
Guy Schalnat0d580581995-07-20 02:43:20 -05002168 text++;
2169
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002170 text_ptr = (png_textp)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002171 png_sizeof(png_text));
2172
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002173 if (text_ptr == NULL)
2174 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002175 png_warning(png_ptr, "Not enough memory to process text chunk");
2176 png_free(png_ptr, png_ptr->chunkdata);
2177 png_ptr->chunkdata = NULL;
2178 return;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002179 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002180
Andreas Dilger47a0c421997-05-16 02:46:07 -05002181 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
2182 text_ptr->key = key;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002183 text_ptr->lang = NULL;
2184 text_ptr->lang_key = NULL;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002185 text_ptr->itxt_length = 0;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002186 text_ptr->text = text;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002187 text_ptr->text_length = png_strlen(text);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002188
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002189 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002190
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002191 png_free(png_ptr, png_ptr->chunkdata);
2192 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002193 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002194
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002195 if (ret)
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002196 png_warning(png_ptr, "Insufficient memory to process text chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -05002197}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002198#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002199
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002200#ifdef PNG_READ_zTXt_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002201/* Note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002202void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002203png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05002204{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002205 png_textp text_ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -06002206 png_charp text;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002207 int comp_type;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002208 int ret;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002209 png_size_t slength, prefix_len, data_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002210
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002211 png_debug(1, "in png_handle_zTXt");
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002212
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06002213#ifdef PNG_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002214 if (png_ptr->user_chunk_cache_max != 0)
2215 {
2216 if (png_ptr->user_chunk_cache_max == 1)
2217 {
2218 png_crc_finish(png_ptr, length);
2219 return;
2220 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002221
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002222 if (--png_ptr->user_chunk_cache_max == 1)
2223 {
2224 png_warning(png_ptr, "No space in chunk cache for zTXt");
2225 png_crc_finish(png_ptr, length);
2226 return;
2227 }
2228 }
2229#endif
2230
Guy Schalnate5a37791996-06-05 15:50:50 -05002231 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2232 png_error(png_ptr, "Missing IHDR before zTXt");
2233
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002234 if (png_ptr->mode & PNG_HAVE_IDAT)
2235 png_ptr->mode |= PNG_AFTER_IDAT;
2236
Andreas Dilger47a0c421997-05-16 02:46:07 -05002237#ifdef PNG_MAX_MALLOC_64K
2238 /* We will no doubt have problems with chunks even half this size, but
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002239 * there is no hard and fast rule to tell us where to stop.
2240 */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002241 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002242 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002243 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
2244 png_crc_finish(png_ptr, length);
2245 return;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002246 }
2247#endif
2248
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002249 png_free(png_ptr, png_ptr->chunkdata);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002250 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002251
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002252 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002253 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002254 png_warning(png_ptr, "Out of memory processing zTXt chunk");
2255 return;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002256 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002257
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002258 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002259 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002260
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002261 if (png_crc_finish(png_ptr, 0))
2262 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002263 png_free(png_ptr, png_ptr->chunkdata);
2264 png_ptr->chunkdata = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002265 return;
2266 }
2267
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002268 png_ptr->chunkdata[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05002269
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002270 for (text = png_ptr->chunkdata; *text; text++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002271 /* Empty loop */ ;
Guy Schalnat0d580581995-07-20 02:43:20 -05002272
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002273 /* zTXt must have some text after the chunkdataword */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002274 if (text >= png_ptr->chunkdata + slength - 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002275 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002276 png_warning(png_ptr, "Truncated zTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002277 png_free(png_ptr, png_ptr->chunkdata);
2278 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002279 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05002280 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002281
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002282 else
Guy Schalnat0d580581995-07-20 02:43:20 -05002283 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002284 comp_type = *(++text);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002285
Glenn Randers-Pehrsonf05f8032000-12-23 14:27:39 -06002286 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2287 {
2288 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2289 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2290 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002291
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002292 text++; /* Skip the compression_method byte */
Guy Schalnat0d580581995-07-20 02:43:20 -05002293 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002294
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002295 prefix_len = text - png_ptr->chunkdata;
Guy Schalnat0d580581995-07-20 02:43:20 -05002296
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -05002297 png_decompress_chunk(png_ptr, comp_type,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002298 (png_size_t)length, prefix_len, &data_len);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002299
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002300 text_ptr = (png_textp)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002301 png_sizeof(png_text));
2302
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002303 if (text_ptr == NULL)
2304 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002305 png_warning(png_ptr, "Not enough memory to process zTXt chunk");
2306 png_free(png_ptr, png_ptr->chunkdata);
2307 png_ptr->chunkdata = NULL;
2308 return;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002309 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002310
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002311 text_ptr->compression = comp_type;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002312 text_ptr->key = png_ptr->chunkdata;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002313 text_ptr->lang = NULL;
2314 text_ptr->lang_key = NULL;
2315 text_ptr->itxt_length = 0;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002316 text_ptr->text = png_ptr->chunkdata + prefix_len;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002317 text_ptr->text_length = data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002318
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002319 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002320
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002321 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002322 png_free(png_ptr, png_ptr->chunkdata);
2323 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002324
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002325 if (ret)
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002326 png_error(png_ptr, "Insufficient memory to store zTXt chunk");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002327}
2328#endif
2329
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002330#ifdef PNG_READ_iTXt_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002331/* Note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002332void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002333png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2334{
2335 png_textp text_ptr;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002336 png_charp key, lang, text, lang_key;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002337 int comp_flag;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002338 int comp_type = 0;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002339 int ret;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002340 png_size_t slength, prefix_len, data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002341
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002342 png_debug(1, "in png_handle_iTXt");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002343
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06002344#ifdef PNG_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002345 if (png_ptr->user_chunk_cache_max != 0)
2346 {
2347 if (png_ptr->user_chunk_cache_max == 1)
2348 {
2349 png_crc_finish(png_ptr, length);
2350 return;
2351 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002352
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002353 if (--png_ptr->user_chunk_cache_max == 1)
2354 {
2355 png_warning(png_ptr, "No space in chunk cache for iTXt");
2356 png_crc_finish(png_ptr, length);
2357 return;
2358 }
2359 }
2360#endif
2361
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002362 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2363 png_error(png_ptr, "Missing IHDR before iTXt");
2364
2365 if (png_ptr->mode & PNG_HAVE_IDAT)
2366 png_ptr->mode |= PNG_AFTER_IDAT;
2367
2368#ifdef PNG_MAX_MALLOC_64K
2369 /* We will no doubt have problems with chunks even half this size, but
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002370 * there is no hard and fast rule to tell us where to stop.
2371 */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002372 if (length > (png_uint_32)65535L)
2373 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002374 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
2375 png_crc_finish(png_ptr, length);
2376 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002377 }
2378#endif
2379
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002380 png_free(png_ptr, png_ptr->chunkdata);
2381 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002382
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002383 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002384 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002385 png_warning(png_ptr, "No memory to process iTXt chunk");
2386 return;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002387 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002388
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002389 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002390 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002391
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002392 if (png_crc_finish(png_ptr, 0))
2393 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002394 png_free(png_ptr, png_ptr->chunkdata);
2395 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002396 return;
2397 }
2398
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002399 png_ptr->chunkdata[slength] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002400
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002401 for (lang = png_ptr->chunkdata; *lang; lang++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002402 /* Empty loop */ ;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002403
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002404 lang++; /* Skip NUL separator */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002405
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002406 /* iTXt must have a language tag (possibly empty), two compression bytes,
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002407 * translated keyword (possibly empty), and possibly some text after the
2408 * keyword
2409 */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002410
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002411 if (lang >= png_ptr->chunkdata + slength - 3)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002412 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002413 png_warning(png_ptr, "Truncated iTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002414 png_free(png_ptr, png_ptr->chunkdata);
2415 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002416 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002417 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002418
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002419 else
2420 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002421 comp_flag = *lang++;
2422 comp_type = *lang++;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002423 }
2424
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002425 for (lang_key = lang; *lang_key; lang_key++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002426 /* Empty loop */ ;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002427
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002428 lang_key++; /* Skip NUL separator */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002429
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002430 if (lang_key >= png_ptr->chunkdata + slength)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002431 {
2432 png_warning(png_ptr, "Truncated iTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002433 png_free(png_ptr, png_ptr->chunkdata);
2434 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002435 return;
2436 }
2437
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002438 for (text = lang_key; *text; text++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002439 /* Empty loop */ ;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002440
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002441 text++; /* Skip NUL separator */
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002442
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002443 if (text >= png_ptr->chunkdata + slength)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002444 {
2445 png_warning(png_ptr, "Malformed iTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002446 png_free(png_ptr, png_ptr->chunkdata);
2447 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002448 return;
2449 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002450
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002451 prefix_len = text - png_ptr->chunkdata;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002452
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002453 key=png_ptr->chunkdata;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002454
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002455 if (comp_flag)
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002456 png_decompress_chunk(png_ptr, comp_type,
2457 (size_t)length, prefix_len, &data_len);
2458
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002459 else
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002460 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
2461
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002462 text_ptr = (png_textp)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002463 png_sizeof(png_text));
2464
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002465 if (text_ptr == NULL)
2466 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002467 png_warning(png_ptr, "Not enough memory to process iTXt chunk");
2468 png_free(png_ptr, png_ptr->chunkdata);
2469 png_ptr->chunkdata = NULL;
2470 return;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002471 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002472
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002473 text_ptr->compression = (int)comp_flag + 1;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002474 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
2475 text_ptr->lang = png_ptr->chunkdata + (lang - key);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002476 text_ptr->itxt_length = data_len;
2477 text_ptr->text_length = 0;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002478 text_ptr->key = png_ptr->chunkdata;
2479 text_ptr->text = png_ptr->chunkdata + prefix_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002480
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002481 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002482
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002483 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002484 png_free(png_ptr, png_ptr->chunkdata);
2485 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002486
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002487 if (ret)
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002488 png_error(png_ptr, "Insufficient memory to store iTXt chunk");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002489}
2490#endif
2491
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002492/* This function is called when we haven't found a handler for a
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002493 * chunk. If there isn't a problem with the chunk itself (ie bad
2494 * chunk name, CRC, or a critical chunk), the chunk is silently ignored
2495 * -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2496 * case it will be saved away to be written out later.
2497 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002498void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002499png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2500{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002501 png_uint_32 skip = 0;
2502
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002503 png_debug(1, "in png_handle_unknown");
Andreas Dilger47a0c421997-05-16 02:46:07 -05002504
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06002505#ifdef PNG_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002506 if (png_ptr->user_chunk_cache_max != 0)
2507 {
2508 if (png_ptr->user_chunk_cache_max == 1)
2509 {
2510 png_crc_finish(png_ptr, length);
2511 return;
2512 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002513
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002514 if (--png_ptr->user_chunk_cache_max == 1)
2515 {
2516 png_warning(png_ptr, "No space in chunk cache for unknown chunk");
2517 png_crc_finish(png_ptr, length);
2518 return;
2519 }
2520 }
2521#endif
2522
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002523 if (png_ptr->mode & PNG_HAVE_IDAT)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002524 {
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002525 PNG_IDAT;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002526
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002527 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002528 png_ptr->mode |= PNG_AFTER_IDAT;
2529 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002530
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002531 if (!(png_ptr->chunk_name[0] & 0x20))
2532 {
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002533#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002534 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002535 PNG_HANDLE_CHUNK_ALWAYS
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002536#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002537 && png_ptr->read_user_chunk_fn == NULL
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002538#endif
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002539 )
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05002540#endif
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002541 png_chunk_error(png_ptr, "unknown critical chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002542 }
2543
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002544#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
Glenn Randers-Pehrson7824a702009-06-13 10:05:05 -05002545 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002546#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Glenn Randers-Pehrson7824a702009-06-13 10:05:05 -05002547 || (png_ptr->read_user_chunk_fn != NULL)
2548#endif
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002549 )
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002550 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002551#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002552 if (length > (png_uint_32)65535L)
2553 {
2554 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2555 skip = length - (png_uint_32)65535L;
2556 length = (png_uint_32)65535L;
2557 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002558#endif
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002559
2560 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
2561 (png_charp)png_ptr->chunk_name,
2562 png_sizeof(png_ptr->unknown_chunk.name));
2563
2564 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
2565 = '\0';
2566
2567 png_ptr->unknown_chunk.size = (png_size_t)length;
2568
2569 if (length == 0)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002570 png_ptr->unknown_chunk.data = NULL;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002571
2572 else
2573 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002574 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2575 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002576 }
2577
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002578#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002579 if (png_ptr->read_user_chunk_fn != NULL)
2580 {
2581 /* Callback to user unknown chunk handler */
2582 int ret;
2583
2584 ret = (*(png_ptr->read_user_chunk_fn))
2585 (png_ptr, &png_ptr->unknown_chunk);
2586
2587 if (ret < 0)
2588 png_chunk_error(png_ptr, "error in user chunk");
2589
2590 if (ret == 0)
2591 {
2592 if (!(png_ptr->chunk_name[0] & 0x20))
2593 {
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002594#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002595 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2596 PNG_HANDLE_CHUNK_ALWAYS)
Glenn Randers-Pehrson7824a702009-06-13 10:05:05 -05002597#endif
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002598 png_chunk_error(png_ptr, "unknown critical chunk");
2599 }
2600
2601 png_set_unknown_chunks(png_ptr, info_ptr,
2602 &png_ptr->unknown_chunk, 1);
2603 }
2604 }
2605
2606 else
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002607#endif
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002608 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
2609
2610 png_free(png_ptr, png_ptr->unknown_chunk.data);
2611 png_ptr->unknown_chunk.data = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002612 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002613
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002614 else
2615#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002616 skip = length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002617
2618 png_crc_finish(png_ptr, skip);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002619
Glenn Randers-Pehrsonb2aca212009-09-23 11:32:37 -05002620#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002621 PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002622#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002623}
2624
2625/* This function is called to verify that a chunk name is valid.
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002626 * This function can't have the "critical chunk check" incorporated
2627 * into it, since in the future we will need to be able to call user
2628 * functions to handle unknown critical chunks after we check that
2629 * the chunk name itself is valid.
2630 */
Andreas Dilger47a0c421997-05-16 02:46:07 -05002631
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05002632#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
Andreas Dilger47a0c421997-05-16 02:46:07 -05002633
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002634void /* PRIVATE */
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002635png_check_chunk_name(png_structp png_ptr, png_const_bytep chunk_name)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002636{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002637 png_debug(1, "in png_check_chunk_name");
Andreas Dilger47a0c421997-05-16 02:46:07 -05002638 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -05002639 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002640 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06002641 png_chunk_error(png_ptr, "invalid chunk type");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002642 }
2643}
2644
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002645/* Combines the row recently read in with the existing pixels in the
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002646 * row. This routine takes care of alpha and transparency if requested.
2647 * This routine also handles the two methods of progressive display
2648 * of interlaced images, depending on the mask value.
2649 * The mask value describes which pixels are to be combined with
2650 * the row. The pattern always repeats every 8 pixels, so just 8
2651 * bits are needed. A one indicates the pixel is to be combined,
2652 * a zero indicates the pixel is to be skipped. This is in addition
2653 * to any alpha or transparency value associated with the pixel. If
2654 * you want all pixels to be combined, pass 0xff (255) in mask.
2655 */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002656
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002657void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002658png_combine_row(png_structp png_ptr, png_bytep row, int mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002659{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002660 png_debug(1, "in png_combine_row");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002661
Guy Schalnat0d580581995-07-20 02:43:20 -05002662 if (mask == 0xff)
2663 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002664 png_memcpy(row, png_ptr->row_buf + 1,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002665 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
Guy Schalnat0d580581995-07-20 02:43:20 -05002666 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002667
Guy Schalnat0d580581995-07-20 02:43:20 -05002668 else
2669 {
2670 switch (png_ptr->row_info.pixel_depth)
2671 {
2672 case 1:
2673 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002674 png_bytep sp = png_ptr->row_buf + 1;
2675 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002676 int s_inc, s_start, s_end;
2677 int m = 0x80;
2678 int shift;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002679 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002680 png_uint_32 row_width = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05002681
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002682#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002683 if (png_ptr->transformations & PNG_PACKSWAP)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002684 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002685 s_start = 0;
2686 s_end = 7;
2687 s_inc = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002688 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002689
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002690 else
2691#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002692 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002693 s_start = 7;
2694 s_end = 0;
2695 s_inc = -1;
2696 }
2697
2698 shift = s_start;
2699
2700 for (i = 0; i < row_width; i++)
2701 {
2702 if (m & mask)
2703 {
2704 int value;
2705
2706 value = (*sp >> shift) & 0x01;
2707 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2708 *dp |= (png_byte)(value << shift);
2709 }
2710
2711 if (shift == s_end)
2712 {
2713 shift = s_start;
2714 sp++;
2715 dp++;
2716 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002717
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002718 else
2719 shift += s_inc;
2720
2721 if (m == 1)
2722 m = 0x80;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002723
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002724 else
2725 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002726 }
2727 break;
2728 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002729
Guy Schalnat0d580581995-07-20 02:43:20 -05002730 case 2:
2731 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002732 png_bytep sp = png_ptr->row_buf + 1;
2733 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002734 int s_start, s_end, s_inc;
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002735 int m = 0x80;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002736 int shift;
2737 png_uint_32 i;
2738 png_uint_32 row_width = png_ptr->width;
2739 int value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002740
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002741#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002742 if (png_ptr->transformations & PNG_PACKSWAP)
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002743 {
2744 s_start = 0;
2745 s_end = 6;
2746 s_inc = 2;
2747 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002748
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002749 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002750#endif
2751 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002752 s_start = 6;
2753 s_end = 0;
2754 s_inc = -2;
2755 }
2756
2757 shift = s_start;
2758
2759 for (i = 0; i < row_width; i++)
2760 {
2761 if (m & mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002762 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002763 value = (*sp >> shift) & 0x03;
2764 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2765 *dp |= (png_byte)(value << shift);
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002766 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002767
2768 if (shift == s_end)
2769 {
2770 shift = s_start;
2771 sp++;
2772 dp++;
2773 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002774
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002775 else
2776 shift += s_inc;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002777
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002778 if (m == 1)
2779 m = 0x80;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002780
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002781 else
2782 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002783 }
2784 break;
2785 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002786
Guy Schalnat0d580581995-07-20 02:43:20 -05002787 case 4:
2788 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002789 png_bytep sp = png_ptr->row_buf + 1;
2790 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002791 int s_start, s_end, s_inc;
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002792 int m = 0x80;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002793 int shift;
2794 png_uint_32 i;
2795 png_uint_32 row_width = png_ptr->width;
2796 int value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002797
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002798#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002799 if (png_ptr->transformations & PNG_PACKSWAP)
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002800 {
2801 s_start = 0;
2802 s_end = 4;
2803 s_inc = 4;
2804 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002805
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002806 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002807#endif
2808 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002809 s_start = 4;
2810 s_end = 0;
2811 s_inc = -4;
2812 }
2813 shift = s_start;
2814
2815 for (i = 0; i < row_width; i++)
2816 {
2817 if (m & mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002818 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002819 value = (*sp >> shift) & 0xf;
2820 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2821 *dp |= (png_byte)(value << shift);
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002822 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002823
2824 if (shift == s_end)
2825 {
2826 shift = s_start;
2827 sp++;
2828 dp++;
2829 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002830
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002831 else
2832 shift += s_inc;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002833
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002834 if (m == 1)
2835 m = 0x80;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002836
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002837 else
2838 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002839 }
2840 break;
2841 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002842
Guy Schalnat0d580581995-07-20 02:43:20 -05002843 default:
2844 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002845 png_bytep sp = png_ptr->row_buf + 1;
2846 png_bytep dp = row;
2847 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2848 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002849 png_uint_32 row_width = png_ptr->width;
2850 png_byte m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05002851
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002852 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002853 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002854 if (m & mask)
2855 {
2856 png_memcpy(dp, sp, pixel_bytes);
2857 }
2858
2859 sp += pixel_bytes;
2860 dp += pixel_bytes;
2861
2862 if (m == 1)
2863 m = 0x80;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002864
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002865 else
2866 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002867 }
2868 break;
2869 }
2870 }
2871 }
2872}
2873
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002874#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002875void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002876png_do_read_interlace(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002877{
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002878 png_row_infop row_info = &(png_ptr->row_info);
2879 png_bytep row = png_ptr->row_buf + 1;
2880 int pass = png_ptr->pass;
2881 png_uint_32 transformations = png_ptr->transformations;
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002882 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2883 /* Offset to next interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002884 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002885
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002886 png_debug(1, "in png_do_read_interlace");
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002887 if (row != NULL && row_info != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002888 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002889 png_uint_32 final_width;
2890
2891 final_width = row_info->width * png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05002892
2893 switch (row_info->pixel_depth)
2894 {
2895 case 1:
2896 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002897 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2898 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002899 int sshift, dshift;
2900 int s_start, s_end, s_inc;
2901 int jstop = png_pass_inc[pass];
2902 png_byte v;
Guy Schalnat0d580581995-07-20 02:43:20 -05002903 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002904 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -05002905
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002906#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002907 if (transformations & PNG_PACKSWAP)
2908 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002909 sshift = (int)((row_info->width + 7) & 0x07);
2910 dshift = (int)((final_width + 7) & 0x07);
2911 s_start = 7;
2912 s_end = 0;
2913 s_inc = -1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002914 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002915
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002916 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002917#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002918 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002919 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2920 dshift = 7 - (int)((final_width + 7) & 0x07);
2921 s_start = 0;
2922 s_end = 7;
2923 s_inc = 1;
2924 }
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002925
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002926 for (i = 0; i < row_info->width; i++)
2927 {
2928 v = (png_byte)((*sp >> sshift) & 0x01);
2929 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002930 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002931 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2932 *dp |= (png_byte)(v << dshift);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002933
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002934 if (dshift == s_end)
2935 {
2936 dshift = s_start;
2937 dp--;
2938 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002939
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002940 else
2941 dshift += s_inc;
2942 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002943
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002944 if (sshift == s_end)
2945 {
2946 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002947 sp--;
2948 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002949
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002950 else
2951 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002952 }
2953 break;
2954 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002955
Guy Schalnat0d580581995-07-20 02:43:20 -05002956 case 2:
2957 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002958 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2959 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2960 int sshift, dshift;
2961 int s_start, s_end, s_inc;
2962 int jstop = png_pass_inc[pass];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002963 png_uint_32 i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002964
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002965#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002966 if (transformations & PNG_PACKSWAP)
2967 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002968 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2969 dshift = (int)(((final_width + 3) & 0x03) << 1);
2970 s_start = 6;
2971 s_end = 0;
2972 s_inc = -2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002973 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002974
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002975 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002976#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002977 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002978 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2979 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2980 s_start = 0;
2981 s_end = 6;
2982 s_inc = 2;
2983 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002984
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002985 for (i = 0; i < row_info->width; i++)
2986 {
2987 png_byte v;
2988 int j;
2989
2990 v = (png_byte)((*sp >> sshift) & 0x03);
2991 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002992 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002993 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2994 *dp |= (png_byte)(v << dshift);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06002995
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002996 if (dshift == s_end)
2997 {
2998 dshift = s_start;
2999 dp--;
3000 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003001
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003002 else
3003 dshift += s_inc;
3004 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003005
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003006 if (sshift == s_end)
3007 {
3008 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05003009 sp--;
3010 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003011
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003012 else
3013 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05003014 }
3015 break;
3016 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003017
Guy Schalnat0d580581995-07-20 02:43:20 -05003018 case 4:
3019 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003020 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
3021 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003022 int sshift, dshift;
3023 int s_start, s_end, s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05003024 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003025 int jstop = png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05003026
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003027#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05003028 if (transformations & PNG_PACKSWAP)
3029 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003030 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
3031 dshift = (int)(((final_width + 1) & 0x01) << 2);
3032 s_start = 4;
3033 s_end = 0;
3034 s_inc = -4;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003035 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003036
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003037 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05003038#endif
3039 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003040 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
3041 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
3042 s_start = 0;
3043 s_end = 4;
3044 s_inc = 4;
3045 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003046
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003047 for (i = 0; i < row_info->width; i++)
3048 {
3049 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
3050 int j;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003051
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003052 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003053 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003054 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
3055 *dp |= (png_byte)(v << dshift);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003056
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003057 if (dshift == s_end)
3058 {
3059 dshift = s_start;
3060 dp--;
3061 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003062
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003063 else
3064 dshift += s_inc;
3065 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003066
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003067 if (sshift == s_end)
3068 {
3069 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05003070 sp--;
3071 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003072
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003073 else
3074 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05003075 }
3076 break;
3077 }
3078 default:
3079 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003080 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003081
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06003082 png_bytep sp = row + (png_size_t)(row_info->width - 1)
3083 * pixel_bytes;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003084
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003085 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05003086
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003087 int jstop = png_pass_inc[pass];
3088 png_uint_32 i;
3089
3090 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003091 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003092 png_byte v[8];
3093 int j;
3094
3095 png_memcpy(v, sp, pixel_bytes);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003096
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003097 for (j = 0; j < jstop; j++)
3098 {
3099 png_memcpy(dp, v, pixel_bytes);
3100 dp -= pixel_bytes;
3101 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003102
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003103 sp -= pixel_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05003104 }
3105 break;
3106 }
3107 }
3108 row_info->width = final_width;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003109 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
Guy Schalnat0d580581995-07-20 02:43:20 -05003110 }
Glenn Randers-Pehrsonb2aca212009-09-23 11:32:37 -05003111#ifndef PNG_READ_PACKSWAP_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003112 PNG_UNUSED(transformations) /* Silence compiler warning */
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05003113#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003114}
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06003115#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003116
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003117void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06003118png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003119 png_const_bytep prev_row, int filter)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003120{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05003121 png_debug(1, "in png_read_filter_row");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003122 png_debug2(2, "row = %u, filter = %d", png_ptr->row_number, filter);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003123 switch (filter)
3124 {
3125 case PNG_FILTER_VALUE_NONE:
3126 break;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003127
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003128 case PNG_FILTER_VALUE_SUB:
3129 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003130 png_size_t i;
3131 png_size_t istop = row_info->rowbytes;
3132 unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003133 png_bytep rp = row + bpp;
3134 png_bytep lp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003135
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003136 for (i = bpp; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003137 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003138 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
3139 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003140 }
3141 break;
3142 }
3143 case PNG_FILTER_VALUE_UP:
3144 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003145 png_size_t i;
3146 png_size_t istop = row_info->rowbytes;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003147 png_bytep rp = row;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003148 png_const_bytep pp = prev_row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003149
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003150 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003151 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003152 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3153 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003154 }
3155 break;
3156 }
3157 case PNG_FILTER_VALUE_AVG:
3158 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003159 png_size_t i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003160 png_bytep rp = row;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003161 png_const_bytep pp = prev_row;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003162 png_bytep lp = row;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003163 unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
3164 png_size_t istop = row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003165
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003166 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003167 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003168 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003169 ((int)(*pp++) / 2 )) & 0xff);
3170
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003171 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003172 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003173
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003174 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003175 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003176 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003177 (int)(*pp++ + *lp++) / 2 ) & 0xff);
3178
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003179 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003180 }
3181 break;
3182 }
3183 case PNG_FILTER_VALUE_PAETH:
3184 {
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003185 png_size_t i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003186 png_bytep rp = row;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003187 png_const_bytep pp = prev_row;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003188 png_bytep lp = row;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003189 png_const_bytep cp = prev_row;
3190 unsigned int bpp = (row_info->pixel_depth + 7) >> 3;
3191 png_size_t istop=row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003192
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003193 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003194 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003195 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3196 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003197 }
3198
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003199 for (i = 0; i < istop; i++) /* Use leftover rp,pp */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003200 {
3201 int a, b, c, pa, pb, pc, p;
3202
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003203 a = *lp++;
3204 b = *pp++;
3205 c = *cp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003206
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003207 p = b - c;
3208 pc = a - c;
3209
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003210#ifdef PNG_USE_ABS
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003211 pa = abs(p);
3212 pb = abs(pc);
3213 pc = abs(p + pc);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003214#else
Glenn Randers-Pehrsona565f0e2010-03-06 08:24:45 -06003215 pa = p < 0 ? -p : p;
3216 pb = pc < 0 ? -pc : pc;
3217 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003218#endif
3219
3220 /*
3221 if (pa <= pb && pa <= pc)
3222 p = a;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003223
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003224 else if (pb <= pc)
3225 p = b;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003226
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003227 else
3228 p = c;
3229 */
3230
Glenn Randers-Pehrsona565f0e2010-03-06 08:24:45 -06003231 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003232
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003233 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
3234 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003235 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003236 break;
3237 }
3238 default:
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003239 png_error(png_ptr, "Ignoring bad adaptive filter type");
3240 /*NOT REACHED */
Glenn Randers-Pehrson3df324d2010-07-31 13:45:04 -05003241 break;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003242 }
3243}
Guy Schalnat0d580581995-07-20 02:43:20 -05003244
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05003245#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003246void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003247png_read_finish_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05003248{
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003249#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003250 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003251
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003252 /* Start of interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003253 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003254
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003255 /* Offset to next interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003256 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003257
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003258 /* Start of interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003259 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003260
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003261 /* Offset to next interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003262 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3263#endif /* PNG_READ_INTERLACING_SUPPORTED */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003264
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05003265 png_debug(1, "in png_read_finish_row");
Guy Schalnat0d580581995-07-20 02:43:20 -05003266 png_ptr->row_number++;
3267 if (png_ptr->row_number < png_ptr->num_rows)
3268 return;
3269
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003270#ifdef PNG_READ_INTERLACING_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05003271 if (png_ptr->interlaced)
3272 {
3273 png_ptr->row_number = 0;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003274
3275 png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
3276
Guy Schalnat0d580581995-07-20 02:43:20 -05003277 do
3278 {
3279 png_ptr->pass++;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003280
Guy Schalnat0d580581995-07-20 02:43:20 -05003281 if (png_ptr->pass >= 7)
3282 break;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003283
Guy Schalnat0d580581995-07-20 02:43:20 -05003284 png_ptr->iwidth = (png_ptr->width +
3285 png_pass_inc[png_ptr->pass] - 1 -
3286 png_pass_start[png_ptr->pass]) /
3287 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05003288
Guy Schalnat0d580581995-07-20 02:43:20 -05003289 if (!(png_ptr->transformations & PNG_INTERLACE))
3290 {
3291 png_ptr->num_rows = (png_ptr->height +
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003292 png_pass_yinc[png_ptr->pass] - 1 -
3293 png_pass_ystart[png_ptr->pass]) /
3294 png_pass_yinc[png_ptr->pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05003295 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003296
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05003297 else /* if (png_ptr->transformations & PNG_INTERLACE) */
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003298 break; /* libpng deinterlacing sees every row */
3299
3300 } while (png_ptr->num_rows == 0 || png_ptr->iwidth == 0);
Guy Schalnat0d580581995-07-20 02:43:20 -05003301
3302 if (png_ptr->pass < 7)
3303 return;
3304 }
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003305#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003306
Guy Schalnate5a37791996-06-05 15:50:50 -05003307 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
Guy Schalnat0d580581995-07-20 02:43:20 -05003308 {
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003309 PNG_IDAT;
Guy Schalnat0d580581995-07-20 02:43:20 -05003310 char extra;
3311 int ret;
3312
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003313 png_ptr->zstream.next_out = (Byte *)&extra;
3314 png_ptr->zstream.avail_out = (uInt)1;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003315
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003316 for (;;)
Guy Schalnat0d580581995-07-20 02:43:20 -05003317 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003318 if (!(png_ptr->zstream.avail_in))
Guy Schalnat0d580581995-07-20 02:43:20 -05003319 {
3320 while (!png_ptr->idat_size)
3321 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003322 png_crc_finish(png_ptr, 0);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003323 png_ptr->idat_size = png_read_chunk_header(png_ptr);
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003324 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Guy Schalnat6d764711995-12-19 03:22:19 -06003325 png_error(png_ptr, "Not enough image data");
Glenn Randers-Pehrson20788d32011-01-06 09:01:04 -06003326 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003327
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003328 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
3329 png_ptr->zstream.next_in = png_ptr->zbuf;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003330
Guy Schalnat0d580581995-07-20 02:43:20 -05003331 if (png_ptr->zbuf_size > png_ptr->idat_size)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003332 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003333
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003334 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
3335 png_ptr->idat_size -= png_ptr->zstream.avail_in;
Guy Schalnat0d580581995-07-20 02:43:20 -05003336 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003337
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003338 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003339
Guy Schalnat0d580581995-07-20 02:43:20 -05003340 if (ret == Z_STREAM_END)
3341 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003342 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003343 png_ptr->idat_size)
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003344 png_warning(png_ptr, "Extra compressed data");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003345
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003346 png_ptr->mode |= PNG_AFTER_IDAT;
3347 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Guy Schalnat0d580581995-07-20 02:43:20 -05003348 break;
3349 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003350
Guy Schalnat0d580581995-07-20 02:43:20 -05003351 if (ret != Z_OK)
Glenn Randers-Pehrsona565f0e2010-03-06 08:24:45 -06003352 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003353 "Decompression Error");
Guy Schalnat0d580581995-07-20 02:43:20 -05003354
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003355 if (!(png_ptr->zstream.avail_out))
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003356 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003357 png_warning(png_ptr, "Extra compressed data");
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003358 png_ptr->mode |= PNG_AFTER_IDAT;
3359 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3360 break;
3361 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003362
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -06003363 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003364 png_ptr->zstream.avail_out = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003365 }
3366
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003367 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003368 png_warning(png_ptr, "Extra compression data");
Guy Schalnat0d580581995-07-20 02:43:20 -05003369
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003370 inflateReset(&png_ptr->zstream);
Guy Schalnat0d580581995-07-20 02:43:20 -05003371
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003372 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnat0d580581995-07-20 02:43:20 -05003373}
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05003374#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003375
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003376void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003377png_read_start_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05003378{
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003379#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003380 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003381
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003382 /* Start of interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003383 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003384
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003385 /* Offset to next interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003386 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003387
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003388 /* Start of interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003389 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003390
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003391 /* Offset to next interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003392 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3393#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003394
Guy Schalnat0d580581995-07-20 02:43:20 -05003395 int max_pixel_depth;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003396 png_size_t row_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05003397
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05003398 png_debug(1, "in png_read_start_row");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003399 png_ptr->zstream.avail_in = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003400 png_init_read_transformations(png_ptr);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003401#ifdef PNG_READ_INTERLACING_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05003402 if (png_ptr->interlaced)
3403 {
3404 if (!(png_ptr->transformations & PNG_INTERLACE))
3405 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003406 png_pass_ystart[0]) / png_pass_yinc[0];
3407
Guy Schalnat0d580581995-07-20 02:43:20 -05003408 else
3409 png_ptr->num_rows = png_ptr->height;
3410
3411 png_ptr->iwidth = (png_ptr->width +
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003412 png_pass_inc[png_ptr->pass] - 1 -
3413 png_pass_start[png_ptr->pass]) /
3414 png_pass_inc[png_ptr->pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05003415 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003416
Guy Schalnat0d580581995-07-20 02:43:20 -05003417 else
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003418#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003419 {
3420 png_ptr->num_rows = png_ptr->height;
3421 png_ptr->iwidth = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05003422 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003423
Guy Schalnat0d580581995-07-20 02:43:20 -05003424 max_pixel_depth = png_ptr->pixel_depth;
3425
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003426#ifdef PNG_READ_PACK_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05003427 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003428 max_pixel_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003429#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003430
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003431#ifdef PNG_READ_EXPAND_SUPPORTED
Guy Schalnate5a37791996-06-05 15:50:50 -05003432 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05003433 {
3434 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3435 {
3436 if (png_ptr->num_trans)
3437 max_pixel_depth = 32;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003438
Guy Schalnat0d580581995-07-20 02:43:20 -05003439 else
3440 max_pixel_depth = 24;
3441 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003442
Guy Schalnat0d580581995-07-20 02:43:20 -05003443 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3444 {
3445 if (max_pixel_depth < 8)
3446 max_pixel_depth = 8;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003447
Guy Schalnat0d580581995-07-20 02:43:20 -05003448 if (png_ptr->num_trans)
3449 max_pixel_depth *= 2;
3450 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003451
Guy Schalnat0d580581995-07-20 02:43:20 -05003452 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3453 {
3454 if (png_ptr->num_trans)
3455 {
3456 max_pixel_depth *= 4;
3457 max_pixel_depth /= 3;
3458 }
3459 }
3460 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003461#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003462
John Bowler4d562962011-02-12 09:01:20 -06003463#ifdef PNG_READ_EXPAND_16_SUPPORTED
3464 if (png_ptr->transformations & PNG_EXPAND_16)
3465 {
3466# ifdef PNG_READ_EXPAND_SUPPORTED
3467 /* In fact it is an error if it isn't supported, but checking is
3468 * the safe way.
3469 */
3470 if (png_ptr->transformations & PNG_EXPAND)
3471 {
3472 if (png_ptr->bit_depth < 16)
3473 max_pixel_depth *= 2;
3474 }
3475 else
3476# endif
3477 png_ptr->transformations &= ~PNG_EXPAND_16;
3478 }
3479#endif
3480
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003481#ifdef PNG_READ_FILLER_SUPPORTED
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003482 if (png_ptr->transformations & (PNG_FILLER))
Guy Schalnat0d580581995-07-20 02:43:20 -05003483 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003484 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3485 max_pixel_depth = 32;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003486
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003487 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003488 {
3489 if (max_pixel_depth <= 8)
3490 max_pixel_depth = 16;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003491
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003492 else
3493 max_pixel_depth = 32;
3494 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003495
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003496 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3497 {
3498 if (max_pixel_depth <= 32)
3499 max_pixel_depth = 32;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003500
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003501 else
3502 max_pixel_depth = 64;
3503 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003504 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003505#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003506
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003507#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05003508 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3509 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003510 if (
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003511#ifdef PNG_READ_EXPAND_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003512 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003513#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003514#ifdef PNG_READ_FILLER_SUPPORTED
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003515 (png_ptr->transformations & (PNG_FILLER)) ||
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003516#endif
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003517 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
Guy Schalnat0d580581995-07-20 02:43:20 -05003518 {
3519 if (max_pixel_depth <= 16)
3520 max_pixel_depth = 32;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003521
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003522 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003523 max_pixel_depth = 64;
3524 }
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003525
Guy Schalnat0d580581995-07-20 02:43:20 -05003526 else
3527 {
3528 if (max_pixel_depth <= 8)
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003529 {
3530 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06003531 max_pixel_depth = 32;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003532
3533 else
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06003534 max_pixel_depth = 24;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003535 }
3536
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06003537 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3538 max_pixel_depth = 64;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003539
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003540 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003541 max_pixel_depth = 48;
3542 }
3543 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003544#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003545
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05003546#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3547defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003548 if (png_ptr->transformations & PNG_USER_TRANSFORM)
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003549 {
3550 int user_pixel_depth = png_ptr->user_transform_depth*
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003551 png_ptr->user_transform_channels;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003552
3553 if (user_pixel_depth > max_pixel_depth)
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003554 max_pixel_depth=user_pixel_depth;
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003555 }
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003556#endif
3557
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003558 /* Align the width on the next larger 8 pixels. Mainly used
3559 * for interlacing
3560 */
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003561 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003562 /* Calculate the maximum bytes needed, adding a byte and a pixel
3563 * for safety's sake
3564 */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003565 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003566 1 + ((max_pixel_depth + 7) >> 3);
3567
Guy Schalnat0d580581995-07-20 02:43:20 -05003568#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003569 if (row_bytes > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05003570 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05003571#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003572
Glenn Randers-Pehrsoneddc5af2009-11-20 21:15:06 -06003573 if (row_bytes + 48 > png_ptr->old_big_row_buf_size)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003574 {
3575 png_free(png_ptr, png_ptr->big_row_buf);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003576
Glenn Randers-Pehrson6917b512009-03-09 15:31:08 -05003577 if (png_ptr->interlaced)
Glenn Randers-Pehrsona515d302010-01-01 10:24:25 -06003578 png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
3579 row_bytes + 48);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003580
Glenn Randers-Pehrsona515d302010-01-01 10:24:25 -06003581 else
3582 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
3583 row_bytes + 48);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003584
Glenn Randers-Pehrsoneddc5af2009-11-20 21:15:06 -06003585 png_ptr->old_big_row_buf_size = row_bytes + 48;
3586
3587#ifdef PNG_ALIGNED_MEMORY_SUPPORTED
3588 /* Use 16-byte aligned memory for row_buf with at least 16 bytes
3589 * of padding before and after row_buf.
3590 */
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003591 png_ptr->row_buf = png_ptr->big_row_buf + 32 -
3592 (((png_alloc_size_t)png_ptr->big_row_buf + 15) & 0x0F);
3593
Glenn Randers-Pehrsoneddc5af2009-11-20 21:15:06 -06003594 png_ptr->old_big_row_buf_size = row_bytes + 48;
3595#else
3596 /* Use 32 bytes of padding before and 16 bytes after row_buf. */
Glenn Randers-Pehrson8fb550c2009-03-21 08:15:32 -05003597 png_ptr->row_buf = png_ptr->big_row_buf + 32;
Glenn Randers-Pehrsoneddc5af2009-11-20 21:15:06 -06003598#endif
3599 png_ptr->old_big_row_buf_size = row_bytes + 48;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003600 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003601
3602#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003603 if (png_ptr->rowbytes > 65535)
Guy Schalnate5a37791996-06-05 15:50:50 -05003604 png_error(png_ptr, "This image requires a row greater than 64KB");
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003605
Guy Schalnat0d580581995-07-20 02:43:20 -05003606#endif
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003607 if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1))
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003608 png_error(png_ptr, "Row has too many bytes to allocate in memory");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003609
Glenn Randers-Pehrsona98aa482009-10-13 09:23:39 -05003610 if (png_ptr->rowbytes + 1 > png_ptr->old_prev_row_size)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003611 {
Glenn Randers-Pehrsona98aa482009-10-13 09:23:39 -05003612 png_free(png_ptr, png_ptr->prev_row);
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003613
3614 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1);
3615
Glenn Randers-Pehrsona98aa482009-10-13 09:23:39 -05003616 png_ptr->old_prev_row_size = png_ptr->rowbytes + 1;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003617 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003618
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003619 png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003620
Glenn Randers-Pehrson5c92dec2011-01-07 18:28:47 -06003621 png_debug1(3, "width = %u,", png_ptr->width);
3622 png_debug1(3, "height = %u,", png_ptr->height);
3623 png_debug1(3, "iwidth = %u,", png_ptr->iwidth);
3624 png_debug1(3, "num_rows = %u,", png_ptr->num_rows);
Glenn Randers-Pehrsonb764c602011-01-14 21:18:37 -06003625 png_debug1(3, "rowbytes = %lu,", (unsigned long)png_ptr->rowbytes);
3626 png_debug1(3, "irowbytes = %lu",
3627 (unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05003628
Guy Schalnate5a37791996-06-05 15:50:50 -05003629 png_ptr->flags |= PNG_FLAG_ROW_INIT;
Guy Schalnat0d580581995-07-20 02:43:20 -05003630}
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06003631#endif /* PNG_READ_SUPPORTED */