blob: 31669c88b2ed40dfd6c3485b209ea8cff11f56d6 [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-Pehrson289500a2010-06-28 20:14:31 -05004 * Last changed in libpng 1.4.1 [June 29, 2010]
Glenn Randers-Pehrsona515d302010-01-01 10:24:25 -06005 * Copyright (c) 1998-2010 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-Pehrsonc3cd22b2010-03-08 21:10:25 -060019#ifdef PNG_READ_SUPPORTED
20
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -050021# define png_strtod(p,a,b) strtod(a,b)
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060022png_uint_32 PNGAPI
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050023png_get_uint_31(png_structp png_ptr, png_bytep buf)
24{
25 png_uint_32 i = png_get_uint_32(buf);
26 if (i > PNG_UINT_31_MAX)
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -060027 png_error(png_ptr, "PNG unsigned integer out of range");
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050028 return (i);
29}
Glenn Randers-Pehrson34713ce2010-04-28 07:49:28 -050030#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
31/* NOTE: the read macros will obscure these definitions, so that if
32 * PNG_USE_READ_MACROS is set the library will not use them internally,
33 * but the APIs will still be available externally.
34 */
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050035/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
Glenn Randers-Pehrson5eb5cce2010-04-17 08:45:57 -050036png_uint_32 (PNGAPI
37png_get_uint_32)(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050038{
Glenn Randers-Pehrsond7da8bb2010-03-13 20:30:10 -060039 png_uint_32 i =
40 ((png_uint_32)(*(buf )) << 24) +
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -060041 ((png_uint_32)(*(buf + 1)) << 16) +
Glenn Randers-Pehrsond7da8bb2010-03-13 20:30:10 -060042 ((png_uint_32)(*(buf + 2)) << 8) +
43 ((png_uint_32)(*(buf + 3)) ) ;
Guy Schalnat0d580581995-07-20 02:43:20 -050044
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060045 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050046}
47
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050048/* Grab a signed 32-bit integer from a buffer in big-endian format. The
Andreas Dilger47a0c421997-05-16 02:46:07 -050049 * data is stored in the PNG file in two's complement format, and it is
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050050 * assumed that the machine format for signed integers is the same.
Glenn Randers-Pehrson34713ce2010-04-28 07:49:28 -050051 * Only used internally in this file.
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050052 */
Glenn Randers-Pehrson34713ce2010-04-28 07:49:28 -050053#if defined(PNG_GET_INT_32_SUPPORTED)
Glenn Randers-Pehrson5eb5cce2010-04-17 08:45:57 -050054png_int_32 (PNGAPI
55png_get_int_32)(png_bytep buf)
Andreas Dilger47a0c421997-05-16 02:46:07 -050056{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050057 png_int_32 i = ((png_int_32)(*buf) << 24) +
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -060058 ((png_int_32)(*(buf + 1)) << 16) +
59 ((png_int_32)(*(buf + 2)) << 8) +
60 (png_int_32)(*(buf + 3));
Andreas Dilger47a0c421997-05-16 02:46:07 -050061
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060062 return (i);
Andreas Dilger47a0c421997-05-16 02:46:07 -050063}
Glenn Randers-Pehrson34713ce2010-04-28 07:49:28 -050064#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -050065
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050066/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
Glenn Randers-Pehrson5eb5cce2010-04-17 08:45:57 -050067png_uint_16 (PNGAPI
68png_get_uint_16)(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050069{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050070 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -060071 (png_uint_16)(*(buf + 1)));
Guy Schalnat0d580581995-07-20 02:43:20 -050072
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060073 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050074}
Glenn Randers-Pehrson34713ce2010-04-28 07:49:28 -050075#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -050076
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050077/* Read the chunk header (length + type name).
78 * Put the type name into png_ptr->chunk_name, and return the length.
79 */
80png_uint_32 /* PRIVATE */
81png_read_chunk_header(png_structp png_ptr)
82{
83 png_byte buf[8];
84 png_uint_32 length;
85
86#ifdef PNG_IO_STATE_SUPPORTED
87 /* Inform the I/O callback that the chunk header is being read.
88 * PNG_IO_CHUNK_HDR requires a single I/O call.
89 */
90 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR;
91#endif
92
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050093 /* Read the length and the chunk name */
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050094 png_read_data(png_ptr, buf, 8);
95 length = png_get_uint_31(png_ptr, buf);
96
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050097 /* Put the chunk name into png_ptr->chunk_name */
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050098 png_memcpy(png_ptr->chunk_name, buf + 4, 4);
99
Glenn Randers-Pehrson632a84e2010-03-09 22:28:33 -0600100 png_debug2(0, "Reading %s chunk, length = %u",
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600101 png_ptr->chunk_name, length);
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500102
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500103 /* Reset the crc and run it over the chunk name */
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500104 png_reset_crc(png_ptr);
105 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
106
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500107 /* Check to see if chunk name is valid */
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500108 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
109
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500110#ifdef PNG_IO_STATE_SUPPORTED
111 /* Inform the I/O callback that chunk data will (possibly) be read.
112 * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
113 */
114 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
115#endif
116
117 return length;
118}
119
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500120/* Read data, and (optionally) run it through the CRC. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500121void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500122png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500123{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500124 if (png_ptr == NULL)
125 return;
Guy Schalnat6d764711995-12-19 03:22:19 -0600126 png_read_data(png_ptr, buf, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500127 png_calculate_crc(png_ptr, buf, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500128}
129
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600130/* Optionally skip data and then check the CRC. Depending on whether we
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500131 * are reading a ancillary or critical chunk, and how the program has set
132 * things up, we may calculate the CRC on the data and print a message.
133 * Returns '1' if there was a CRC error, '0' otherwise.
134 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500135int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600136png_crc_finish(png_structp png_ptr, png_uint_32 skip)
Guy Schalnat0d580581995-07-20 02:43:20 -0500137{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500138 png_size_t i;
139 png_size_t istop = png_ptr->zbuf_size;
Guy Schalnat0d580581995-07-20 02:43:20 -0500140
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -0500141 for (i = (png_size_t)skip; i > istop; i -= istop)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600142 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500143 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
Guy Schalnat0d580581995-07-20 02:43:20 -0500144 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500145
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500146 if (i)
Guy Schalnat0d580581995-07-20 02:43:20 -0500147 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500148 png_crc_read(png_ptr, png_ptr->zbuf, i);
Guy Schalnat0d580581995-07-20 02:43:20 -0500149 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600150
Andreas Dilger47a0c421997-05-16 02:46:07 -0500151 if (png_crc_error(png_ptr))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600152 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500153 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500154 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500155 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600156 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600157 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600158 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600159 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500160
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600161 else
162 {
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500163 png_chunk_benign_error(png_ptr, "CRC error");
164 return (0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600165 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500166
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600167 return (1);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600168 }
169
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600170 return (0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500171}
172
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600173/* 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 -0500174 * the data it has read thus far.
175 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500176int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600177png_crc_error(png_structp png_ptr)
178{
179 png_byte crc_bytes[4];
180 png_uint_32 crc;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500181 int need_crc = 1;
182
183 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
184 {
185 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
186 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
187 need_crc = 0;
188 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500189
Andreas Dilger47a0c421997-05-16 02:46:07 -0500190 else /* critical */
191 {
192 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
193 need_crc = 0;
194 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600195
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500196#ifdef PNG_IO_STATE_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500197 /* Inform the I/O callback that the chunk CRC is being read */
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500198 /* PNG_IO_CHUNK_CRC requires the I/O to be done at once */
199 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
200#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500201
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600202 png_read_data(png_ptr, crc_bytes, 4);
203
Andreas Dilger47a0c421997-05-16 02:46:07 -0500204 if (need_crc)
205 {
206 crc = png_get_uint_32(crc_bytes);
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600207 return ((int)(crc != png_ptr->crc));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500208 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500209
Andreas Dilger47a0c421997-05-16 02:46:07 -0500210 else
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600211 return (0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600212}
213
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600214#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500215 defined(PNG_READ_iCCP_SUPPORTED)
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600216static png_size_t
217png_inflate(png_structp png_ptr, const png_byte *data, png_size_t size,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600218 png_bytep output, png_size_t output_size)
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600219{
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600220 png_size_t count = 0;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600221
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600222 png_ptr->zstream.next_in = (png_bytep)data; /* const_cast: VALID */
223 png_ptr->zstream.avail_in = size;
224
225 while (1)
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600226 {
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600227 int ret, avail;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600228
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600229 /* Reset the output buffer each time round - we empty it
230 * after every inflate call.
231 */
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600232 png_ptr->zstream.next_out = png_ptr->zbuf;
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600233 png_ptr->zstream.avail_out = png_ptr->zbuf_size;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600234
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600235 ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
236 avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600237
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600238 /* First copy/count any new output - but only if we didn't
239 * get an error code.
240 */
241 if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600242 {
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600243 if (output != 0 && output_size > count)
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600244 {
245 int copy = output_size - count;
246 if (avail < copy)
247 copy = avail;
248 png_memcpy(output + count, png_ptr->zbuf, copy);
249 }
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600250 count += avail;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600251 }
252
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600253 if (ret == Z_OK)
254 continue;
255
256 /* Termination conditions - always reset the zstream, it
257 * must be left in inflateInit state.
258 */
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600259 png_ptr->zstream.avail_in = 0;
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600260 inflateReset(&png_ptr->zstream);
261
262 if (ret == Z_STREAM_END)
263 return count; /* NOTE: may be zero. */
264
265 /* Now handle the error codes - the API always returns 0
266 * and the error message is dumped into the uncompressed
267 * buffer if available.
268 */
269 {
Glenn Randers-Pehrson6cac43c2010-06-26 12:33:17 -0500270 PNG_CONST char *msg;
Glenn Randers-Pehrsond7da8bb2010-03-13 20:30:10 -0600271#ifdef PNG_CONSOLE_IO_SUPPORTED
272 char umsg[52];
273#endif
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600274 if (png_ptr->zstream.msg != 0)
275 msg = png_ptr->zstream.msg;
276 else
277 {
Glenn Randers-Pehrson6a9e4802010-02-19 09:47:43 -0600278#ifdef PNG_CONSOLE_IO_SUPPORTED
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600279 switch (ret)
280 {
281 case Z_BUF_ERROR:
282 msg = "Buffer error in compressed datastream in %s chunk";
283 break;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500284
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600285 case Z_DATA_ERROR:
286 msg = "Data error in compressed datastream in %s chunk";
287 break;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500288
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600289 default:
290 msg = "Incomplete compressed datastream in %s chunk";
291 break;
292 }
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600293
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600294 png_snprintf(umsg, sizeof umsg, msg, png_ptr->chunk_name);
295 msg = umsg;
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600296#else
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600297 msg = "Damaged compressed datastream in chunk other than IDAT";
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600298#endif
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600299 }
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600300
301 png_warning(png_ptr, msg);
302 }
303
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600304 /* 0 means an error - notice that this code simply ignores
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600305 * zero length compressed chunks as a result.
306 */
307 return 0;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600308 }
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600309}
310
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600311/*
312 * Decompress trailing data in a chunk. The assumption is that chunkdata
313 * points at an allocated area holding the contents of a chunk with a
314 * trailing compressed part. What we get back is an allocated area
315 * holding the original prefix part and an uncompressed version of the
316 * trailing part (the malloc area passed in is freed).
317 */
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500318void /* PRIVATE */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500319png_decompress_chunk(png_structp png_ptr, int comp_type,
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600320 png_size_t chunklength,
321 png_size_t prefix_size, png_size_t *newlength)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600322{
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600323 /* The caller should guarantee this */
324 if (prefix_size > chunklength)
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600325 {
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600326 /* The recovery is to delete the chunk. */
327 png_warning(png_ptr, "invalid chunklength");
328 prefix_size = 0; /* To delete everything */
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600329 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600330
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600331 else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600332 {
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600333 png_size_t expanded_size = png_inflate(png_ptr,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600334 (png_bytep)(png_ptr->chunkdata + prefix_size),
335 chunklength - prefix_size,
336 0, /*output*/
337 0); /*output size*/
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600338
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600339 /* Now check the limits on this chunk - if the limit fails the
340 * compressed data will be removed, the prefix will remain.
341 */
342#ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
343 if (png_ptr->user_chunk_malloc_max &&
344 (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600345#else
Glenn Randers-Pehrsonafa999d2010-03-09 07:52:30 -0600346# ifdef PNG_USER_CHUNK_MALLOC_MAX
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600347 if ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
348 prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
Glenn Randers-Pehrsonafa999d2010-03-09 07:52:30 -0600349# endif
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600350#endif
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600351 png_warning(png_ptr, "Exceeded size limit while expanding chunk");
352
353 /* If the size is zero either there was an error and a message
354 * has already been output (warning) or the size really is zero
355 * and we have nothing to do - the code will exit through the
356 * error case below.
357 */
Glenn Randers-Pehrsonafa999d2010-03-09 07:52:30 -0600358#if defined(PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED) || \
359 defined(PNG_USER_CHUNK_MALLOC_MAX)
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600360 else if (expanded_size > 0)
Glenn Randers-Pehrsonafa999d2010-03-09 07:52:30 -0600361#else
362 if (expanded_size > 0)
363#endif
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600364 {
365 /* Success (maybe) - really uncompress the chunk. */
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600366 png_size_t new_size = 0;
367 png_charp text = png_malloc_warn(png_ptr,
368 prefix_size + expanded_size + 1);
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600369
370 if (text != NULL)
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600371 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600372 png_memcpy(text, png_ptr->chunkdata, prefix_size);
373 new_size = png_inflate(png_ptr,
Glenn Randers-Pehrsonee4eb9a2010-02-12 20:30:45 -0600374 (png_bytep)(png_ptr->chunkdata + prefix_size),
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600375 chunklength - prefix_size,
Glenn Randers-Pehrsonee4eb9a2010-02-12 20:30:45 -0600376 (png_bytep)(text + prefix_size), expanded_size);
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600377 text[prefix_size + expanded_size] = 0; /* just in case */
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600378
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600379 if (new_size == expanded_size)
380 {
381 png_free(png_ptr, png_ptr->chunkdata);
382 png_ptr->chunkdata = text;
383 *newlength = prefix_size + expanded_size;
384 return; /* The success return! */
385 }
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500386
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600387 png_warning(png_ptr, "png_inflate logic error");
388 png_free(png_ptr, text);
389 }
390 else
391 png_warning(png_ptr, "Not enough memory to decompress chunk");
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600392 }
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600393 }
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600394
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600395 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
396 {
Glenn Randers-Pehrsond7da8bb2010-03-13 20:30:10 -0600397#ifdef PNG_STDIO_SUPPORTED
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600398 char umsg[50];
399
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600400 png_snprintf(umsg, sizeof umsg,
401 "Unknown zTXt compression type %d", comp_type);
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600402 png_warning(png_ptr, umsg);
403#else
404 png_warning(png_ptr, "Unknown zTXt compression type");
405#endif
406
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600407 /* The recovery is to simply drop the data. */
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -0600408 }
409
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600410 /* Generic error return - leave the prefix, delete the compressed
411 * data, reallocate the chunkdata to remove the potentially large
412 * amount of compressed data.
413 */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600414 {
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600415 png_charp text = png_malloc_warn(png_ptr, prefix_size + 1);
416 if (text != NULL)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600417 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600418 if (prefix_size > 0)
Glenn Randers-Pehrson7d1f5912010-02-11 23:03:26 -0600419 png_memcpy(text, png_ptr->chunkdata, prefix_size);
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600420 png_free(png_ptr, png_ptr->chunkdata);
421 png_ptr->chunkdata = text;
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600422
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600423 /* This is an extra zero in the 'uncompressed' part. */
424 *(png_ptr->chunkdata + prefix_size) = 0x00;
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500425 }
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600426 /* Ignore a malloc error here - it is safe. */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600427 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600428
Glenn Randers-Pehrson9d51afc2010-02-12 20:12:56 -0600429 *newlength = prefix_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600430}
431#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600432
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500433/* Read and check the IDHR chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500434void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600435png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500436{
437 png_byte buf[13];
438 png_uint_32 width, height;
439 int bit_depth, color_type, compression_type, filter_type;
440 int interlace_type;
441
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500442 png_debug(1, "in png_handle_IHDR");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500443
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600444 if (png_ptr->mode & PNG_HAVE_IHDR)
Guy Schalnate5a37791996-06-05 15:50:50 -0500445 png_error(png_ptr, "Out of place IHDR");
446
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500447 /* Check the length */
Guy Schalnat0d580581995-07-20 02:43:20 -0500448 if (length != 13)
Guy Schalnat6d764711995-12-19 03:22:19 -0600449 png_error(png_ptr, "Invalid IHDR chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -0500450
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600451 png_ptr->mode |= PNG_HAVE_IHDR;
452
Guy Schalnat0d580581995-07-20 02:43:20 -0500453 png_crc_read(png_ptr, buf, 13);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600454 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500455
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500456 width = png_get_uint_31(png_ptr, buf);
457 height = png_get_uint_31(png_ptr, buf + 4);
Guy Schalnat0d580581995-07-20 02:43:20 -0500458 bit_depth = buf[8];
459 color_type = buf[9];
460 compression_type = buf[10];
461 filter_type = buf[11];
462 interlace_type = buf[12];
463
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500464 /* Set internal variables */
Guy Schalnat0d580581995-07-20 02:43:20 -0500465 png_ptr->width = width;
466 png_ptr->height = height;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600467 png_ptr->bit_depth = (png_byte)bit_depth;
468 png_ptr->interlaced = (png_byte)interlace_type;
469 png_ptr->color_type = (png_byte)color_type;
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500470#ifdef PNG_MNG_FEATURES_SUPPORTED
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -0600471 png_ptr->filter_type = (png_byte)filter_type;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500472#endif
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500473 png_ptr->compression_type = (png_byte)compression_type;
Guy Schalnat0d580581995-07-20 02:43:20 -0500474
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500475 /* Find number of channels */
Guy Schalnat0d580581995-07-20 02:43:20 -0500476 switch (png_ptr->color_type)
477 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500478 case PNG_COLOR_TYPE_GRAY:
479 case PNG_COLOR_TYPE_PALETTE:
Guy Schalnat0d580581995-07-20 02:43:20 -0500480 png_ptr->channels = 1;
481 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500482
Andreas Dilger47a0c421997-05-16 02:46:07 -0500483 case PNG_COLOR_TYPE_RGB:
Guy Schalnat0d580581995-07-20 02:43:20 -0500484 png_ptr->channels = 3;
485 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500486
Andreas Dilger47a0c421997-05-16 02:46:07 -0500487 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500488 png_ptr->channels = 2;
489 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500490
Andreas Dilger47a0c421997-05-16 02:46:07 -0500491 case PNG_COLOR_TYPE_RGB_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500492 png_ptr->channels = 4;
493 break;
494 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600495
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500496 /* Set up other useful info */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600497 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600498 png_ptr->channels);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500499 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500500 png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
501 png_debug1(3, "channels = %d", png_ptr->channels);
Glenn Randers-Pehrson632a84e2010-03-09 22:28:33 -0600502 png_debug1(3, "rowbytes = %u", png_ptr->rowbytes);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500503 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600504 color_type, interlace_type, compression_type, filter_type);
Guy Schalnat0d580581995-07-20 02:43:20 -0500505}
506
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500507/* Read and check the palette */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500508void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600509png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500510{
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600511 png_color palette[PNG_MAX_PALETTE_LENGTH];
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600512 int num, i;
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500513#ifdef PNG_POINTER_INDEXING_SUPPORTED
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500514 png_colorp pal_ptr;
515#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500516
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500517 png_debug(1, "in png_handle_PLTE");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500518
Guy Schalnate5a37791996-06-05 15:50:50 -0500519 if (!(png_ptr->mode & PNG_HAVE_IHDR))
520 png_error(png_ptr, "Missing IHDR before PLTE");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500521
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600522 else if (png_ptr->mode & PNG_HAVE_IDAT)
523 {
524 png_warning(png_ptr, "Invalid PLTE after IDAT");
525 png_crc_finish(png_ptr, length);
526 return;
527 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500528
Guy Schalnate5a37791996-06-05 15:50:50 -0500529 else if (png_ptr->mode & PNG_HAVE_PLTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600530 png_error(png_ptr, "Duplicate PLTE chunk");
531
532 png_ptr->mode |= PNG_HAVE_PLTE;
Guy Schalnate5a37791996-06-05 15:50:50 -0500533
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500534 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
535 {
536 png_warning(png_ptr,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600537 "Ignoring PLTE chunk in grayscale PNG");
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500538 png_crc_finish(png_ptr, length);
539 return;
540 }
Glenn Randers-Pehrsonb2aca212009-09-23 11:32:37 -0500541#ifndef PNG_READ_OPT_PLTE_SUPPORTED
Guy Schalnate5a37791996-06-05 15:50:50 -0500542 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
543 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600544 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500545 return;
546 }
547#endif
548
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600549 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
Guy Schalnate5a37791996-06-05 15:50:50 -0500550 {
551 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
552 {
553 png_warning(png_ptr, "Invalid palette chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600554 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500555 return;
556 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500557
Guy Schalnate5a37791996-06-05 15:50:50 -0500558 else
559 {
560 png_error(png_ptr, "Invalid palette chunk");
561 }
562 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500563
564 num = (int)length / 3;
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500565
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500566#ifdef PNG_POINTER_INDEXING_SUPPORTED
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500567 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
568 {
569 png_byte buf[3];
570
571 png_crc_read(png_ptr, buf, 3);
572 pal_ptr->red = buf[0];
573 pal_ptr->green = buf[1];
574 pal_ptr->blue = buf[2];
575 }
576#else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600577 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500578 {
579 png_byte buf[3];
580
581 png_crc_read(png_ptr, buf, 3);
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500582 /* Don't depend upon png_color being any order */
Guy Schalnat0d580581995-07-20 02:43:20 -0500583 palette[i].red = buf[0];
584 palette[i].green = buf[1];
585 palette[i].blue = buf[2];
586 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500587#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600588
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600589 /* 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 -0500590 * whatever the normal CRC configuration tells us. However, if we
591 * have an RGB image, the PLTE can be considered ancillary, so
592 * we will act as though it is.
593 */
Glenn Randers-Pehrsonb2aca212009-09-23 11:32:37 -0500594#ifndef PNG_READ_OPT_PLTE_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600595 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600596#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600597 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500598 png_crc_finish(png_ptr, 0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600599 }
Glenn Randers-Pehrsonb2aca212009-09-23 11:32:37 -0500600#ifndef PNG_READ_OPT_PLTE_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600601 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
602 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600603 /* If we don't want to use the data from an ancillary chunk,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600604 * we have two options: an error abort, or a warning and we
605 * ignore the data in this chunk (which should be OK, since
606 * it's considered ancillary for a RGB or RGBA image).
607 */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600608 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
609 {
610 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
611 {
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500612 png_chunk_benign_error(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600613 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500614
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600615 else
616 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600617 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600618 return;
619 }
620 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500621 /* Otherwise, we (optionally) emit a warning and use the chunk. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600622 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
623 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600624 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600625 }
626 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600627#endif
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500628
Andreas Dilger47a0c421997-05-16 02:46:07 -0500629 png_set_PLTE(png_ptr, info_ptr, palette, num);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500630
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500631#ifdef PNG_READ_tRNS_SUPPORTED
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500632 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
633 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600634 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500635 {
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500636 if (png_ptr->num_trans > (png_uint_16)num)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500637 {
638 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500639 png_ptr->num_trans = (png_uint_16)num;
640 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500641
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500642 if (info_ptr->num_trans > (png_uint_16)num)
643 {
644 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
645 info_ptr->num_trans = (png_uint_16)num;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500646 }
647 }
648 }
649#endif
650
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600651}
Guy Schalnate5a37791996-06-05 15:50:50 -0500652
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500653void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600654png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
655{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500656 png_debug(1, "in png_handle_IEND");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500657
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600658 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
659 {
660 png_error(png_ptr, "No image in file");
661 }
662
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600663 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600664
665 if (length != 0)
666 {
667 png_warning(png_ptr, "Incorrect IEND chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600668 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500669
Andreas Dilger47a0c421997-05-16 02:46:07 -0500670 png_crc_finish(png_ptr, length);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500671
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500672 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
Guy Schalnat0d580581995-07-20 02:43:20 -0500673}
674
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500675#ifdef PNG_READ_gAMA_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500676void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600677png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500678{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600679 png_fixed_point igamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600680#ifdef PNG_FLOATING_POINT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500681 float file_gamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600682#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500683 png_byte buf[4];
684
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500685 png_debug(1, "in png_handle_gAMA");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500686
Guy Schalnate5a37791996-06-05 15:50:50 -0500687 if (!(png_ptr->mode & PNG_HAVE_IHDR))
688 png_error(png_ptr, "Missing IHDR before gAMA");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600689 else if (png_ptr->mode & PNG_HAVE_IDAT)
690 {
691 png_warning(png_ptr, "Invalid gAMA after IDAT");
692 png_crc_finish(png_ptr, length);
693 return;
694 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500695 else if (png_ptr->mode & PNG_HAVE_PLTE)
696 /* Should be an error, but we can cope with it */
697 png_warning(png_ptr, "Out of place gAMA chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600698
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500699 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500700#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600701 && !(info_ptr->valid & PNG_INFO_sRGB)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600702#endif
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600703 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600704 {
705 png_warning(png_ptr, "Duplicate gAMA chunk");
706 png_crc_finish(png_ptr, length);
707 return;
708 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500709
Guy Schalnat0d580581995-07-20 02:43:20 -0500710 if (length != 4)
711 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600712 png_warning(png_ptr, "Incorrect gAMA chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600713 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500714 return;
715 }
716
717 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600718 if (png_crc_finish(png_ptr, 0))
719 return;
720
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600721 igamma = (png_fixed_point)png_get_uint_32(buf);
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500722 /* Check for zero gamma */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500723 if (igamma == 0)
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500724 {
725 png_warning(png_ptr,
726 "Ignoring gAMA chunk with gamma=0");
727 return;
728 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500729
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500730#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600731 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500732 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600733 {
734 png_warning(png_ptr,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600735 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500736#ifdef PNG_CONSOLE_IO_SUPPORTED
Glenn Randers-Pehrson79134c62009-02-14 10:32:18 -0600737 fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600738#endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600739 return;
740 }
741#endif /* PNG_READ_sRGB_SUPPORTED */
742
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600743#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600744 file_gamma = (float)igamma / (float)100000.0;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600745# ifdef PNG_READ_GAMMA_SUPPORTED
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600746 png_ptr->gamma = file_gamma;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600747# endif
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600748 png_set_gAMA(png_ptr, info_ptr, file_gamma);
Glenn Randers-Pehrsona272d8f2010-06-25 21:45:31 -0500749#else
750 /* Fixed point must be set! */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600751 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
752#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500753}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500754#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500755
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500756#ifdef PNG_READ_sBIT_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500757void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600758png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500759{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500760 png_size_t truelen;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600761 png_byte buf[4];
Guy Schalnat69b14481996-01-10 02:56:49 -0600762
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500763 png_debug(1, "in png_handle_sBIT");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500764
Guy Schalnat69b14481996-01-10 02:56:49 -0600765 buf[0] = buf[1] = buf[2] = buf[3] = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500766
Guy Schalnate5a37791996-06-05 15:50:50 -0500767 if (!(png_ptr->mode & PNG_HAVE_IHDR))
768 png_error(png_ptr, "Missing IHDR before sBIT");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500769
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600770 else if (png_ptr->mode & PNG_HAVE_IDAT)
771 {
772 png_warning(png_ptr, "Invalid sBIT after IDAT");
773 png_crc_finish(png_ptr, length);
774 return;
775 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500776
Guy Schalnate5a37791996-06-05 15:50:50 -0500777 else if (png_ptr->mode & PNG_HAVE_PLTE)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600778 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500779 /* Should be an error, but we can cope with it */
780 png_warning(png_ptr, "Out of place sBIT chunk");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600781 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500782
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500783 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600784 {
785 png_warning(png_ptr, "Duplicate sBIT chunk");
786 png_crc_finish(png_ptr, length);
787 return;
788 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500789
Guy Schalnat0d580581995-07-20 02:43:20 -0500790 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600791 truelen = 3;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500792
Guy Schalnat0d580581995-07-20 02:43:20 -0500793 else
Andreas Dilger47a0c421997-05-16 02:46:07 -0500794 truelen = (png_size_t)png_ptr->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500795
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500796 if (length != truelen || length > 4)
Guy Schalnat0d580581995-07-20 02:43:20 -0500797 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600798 png_warning(png_ptr, "Incorrect sBIT chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600799 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600800 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500801 }
802
Andreas Dilger47a0c421997-05-16 02:46:07 -0500803 png_crc_read(png_ptr, buf, truelen);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500804
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600805 if (png_crc_finish(png_ptr, 0))
806 return;
807
Guy Schalnat0d580581995-07-20 02:43:20 -0500808 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
809 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600810 png_ptr->sig_bit.red = buf[0];
811 png_ptr->sig_bit.green = buf[1];
812 png_ptr->sig_bit.blue = buf[2];
813 png_ptr->sig_bit.alpha = buf[3];
Guy Schalnat0d580581995-07-20 02:43:20 -0500814 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500815
Guy Schalnat0d580581995-07-20 02:43:20 -0500816 else
817 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600818 png_ptr->sig_bit.gray = buf[0];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600819 png_ptr->sig_bit.red = buf[0];
820 png_ptr->sig_bit.green = buf[0];
821 png_ptr->sig_bit.blue = buf[0];
Guy Schalnat6d764711995-12-19 03:22:19 -0600822 png_ptr->sig_bit.alpha = buf[1];
Guy Schalnat0d580581995-07-20 02:43:20 -0500823 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500824
Andreas Dilger47a0c421997-05-16 02:46:07 -0500825 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
Guy Schalnat0d580581995-07-20 02:43:20 -0500826}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500827#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500828
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500829#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500830void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600831png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500832{
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500833 png_byte buf[32];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600834#ifdef PNG_FLOATING_POINT_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -0500835 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600836#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600837 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600838 int_y_green, int_x_blue, int_y_blue;
Guy Schalnat0d580581995-07-20 02:43:20 -0500839
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600840 png_uint_32 uint_x, uint_y;
841
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500842 png_debug(1, "in png_handle_cHRM");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500843
Guy Schalnate5a37791996-06-05 15:50:50 -0500844 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600845 png_error(png_ptr, "Missing IHDR before cHRM");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500846
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600847 else if (png_ptr->mode & PNG_HAVE_IDAT)
848 {
849 png_warning(png_ptr, "Invalid cHRM after IDAT");
850 png_crc_finish(png_ptr, length);
851 return;
852 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500853
Guy Schalnate5a37791996-06-05 15:50:50 -0500854 else if (png_ptr->mode & PNG_HAVE_PLTE)
855 /* Should be an error, but we can cope with it */
856 png_warning(png_ptr, "Missing PLTE before cHRM");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600857
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500858 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500859#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600860 && !(info_ptr->valid & PNG_INFO_sRGB)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600861#endif
862 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600863 {
864 png_warning(png_ptr, "Duplicate cHRM chunk");
865 png_crc_finish(png_ptr, length);
866 return;
867 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500868
Guy Schalnat0d580581995-07-20 02:43:20 -0500869 if (length != 32)
870 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600871 png_warning(png_ptr, "Incorrect cHRM chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600872 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600873 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500874 }
875
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500876 png_crc_read(png_ptr, buf, 32);
877 if (png_crc_finish(png_ptr, 0))
878 return;
879
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600880 uint_x = png_get_uint_32(buf);
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500881 uint_y = png_get_uint_32(buf + 4);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600882 int_x_white = (png_fixed_point)uint_x;
883 int_y_white = (png_fixed_point)uint_y;
Guy Schalnat0d580581995-07-20 02:43:20 -0500884
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500885 uint_x = png_get_uint_32(buf + 8);
886 uint_y = png_get_uint_32(buf + 12);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600887 int_x_red = (png_fixed_point)uint_x;
888 int_y_red = (png_fixed_point)uint_y;
Guy Schalnat0d580581995-07-20 02:43:20 -0500889
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500890 uint_x = png_get_uint_32(buf + 16);
891 uint_y = png_get_uint_32(buf + 20);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600892 int_x_green = (png_fixed_point)uint_x;
893 int_y_green = (png_fixed_point)uint_y;
Guy Schalnat0d580581995-07-20 02:43:20 -0500894
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500895 uint_x = png_get_uint_32(buf + 24);
896 uint_y = png_get_uint_32(buf + 28);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600897 int_x_blue = (png_fixed_point)uint_x;
898 int_y_blue = (png_fixed_point)uint_y;
899
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600900#ifdef PNG_FLOATING_POINT_SUPPORTED
901 white_x = (float)int_x_white / (float)100000.0;
902 white_y = (float)int_y_white / (float)100000.0;
903 red_x = (float)int_x_red / (float)100000.0;
904 red_y = (float)int_y_red / (float)100000.0;
905 green_x = (float)int_x_green / (float)100000.0;
906 green_y = (float)int_y_green / (float)100000.0;
907 blue_x = (float)int_x_blue / (float)100000.0;
908 blue_y = (float)int_y_blue / (float)100000.0;
909#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600910
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500911#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500912 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500913 {
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500914 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
915 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
916 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
917 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
918 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
919 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
920 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
921 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500922 {
923 png_warning(png_ptr,
924 "Ignoring incorrect cHRM value when sRGB is also present");
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500925#ifdef PNG_CONSOLE_IO_SUPPORTED
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600926#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500927 fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
928 white_x, white_y, red_x, red_y);
929 fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
930 green_x, green_y, blue_x, blue_y);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600931#else
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500932 fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
933 (long)int_x_white, (long)int_y_white,
934 (long)int_x_red, (long)int_y_red);
935 fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
936 (long)int_x_green, (long)int_y_green,
937 (long)int_x_blue, (long)int_y_blue);
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600938#endif
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500939#endif /* PNG_CONSOLE_IO_SUPPORTED */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600940 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500941 return;
942 }
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600943#endif /* PNG_READ_sRGB_SUPPORTED */
944
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600945#ifdef PNG_FLOATING_POINT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500946 png_set_cHRM(png_ptr, info_ptr,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600947 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600948#endif
949#ifdef PNG_FIXED_POINT_SUPPORTED
950 png_set_cHRM_fixed(png_ptr, info_ptr,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -0600951 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
952 int_y_green, int_x_blue, int_y_blue);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600953#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500954}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500955#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500956
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500957#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500958void /* PRIVATE */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600959png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
960{
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600961 int intent;
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600962 png_byte buf[1];
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600963
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500964 png_debug(1, "in png_handle_sRGB");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600965
966 if (!(png_ptr->mode & PNG_HAVE_IHDR))
967 png_error(png_ptr, "Missing IHDR before sRGB");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500968
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600969 else if (png_ptr->mode & PNG_HAVE_IDAT)
970 {
971 png_warning(png_ptr, "Invalid sRGB after IDAT");
972 png_crc_finish(png_ptr, length);
973 return;
974 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500975
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600976 else if (png_ptr->mode & PNG_HAVE_PLTE)
977 /* Should be an error, but we can cope with it */
978 png_warning(png_ptr, "Out of place sRGB chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600979
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500980 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600981 {
982 png_warning(png_ptr, "Duplicate sRGB chunk");
983 png_crc_finish(png_ptr, length);
984 return;
985 }
986
987 if (length != 1)
988 {
989 png_warning(png_ptr, "Incorrect sRGB chunk length");
990 png_crc_finish(png_ptr, length);
991 return;
992 }
993
994 png_crc_read(png_ptr, buf, 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500995
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600996 if (png_crc_finish(png_ptr, 0))
997 return;
998
999 intent = buf[0];
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001000 /* Check for bad intent */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -06001001 if (intent >= PNG_sRGB_INTENT_LAST)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001002 {
1003 png_warning(png_ptr, "Unknown sRGB intent");
1004 return;
1005 }
1006
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -06001007#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -06001008 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001009 {
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05001010 png_fixed_point igamma;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001011#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05001012 igamma=info_ptr->int_gamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001013#else
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001014# ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05001015 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001016# endif
1017#endif
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -05001018 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06001019 {
1020 png_warning(png_ptr,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001021 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05001022#ifdef PNG_CONSOLE_IO_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001023# ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001024 fprintf(stderr, "incorrect gamma=(%d/100000)\n",
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001025 (int)png_ptr->int_gamma);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001026# else
1027# ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001028 fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001029# endif
1030# endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001031#endif
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06001032 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001033 }
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06001034#endif /* PNG_READ_gAMA_SUPPORTED */
1035
1036#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001037#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -06001038 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -05001039 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
1040 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
1041 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
1042 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
1043 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
1044 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
1045 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
1046 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001047 {
1048 png_warning(png_ptr,
1049 "Ignoring incorrect cHRM value when sRGB is also present");
1050 }
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001051#endif /* PNG_FIXED_POINT_SUPPORTED */
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -06001052#endif /* PNG_READ_cHRM_SUPPORTED */
1053
1054 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
1055}
1056#endif /* PNG_READ_sRGB_SUPPORTED */
1057
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001058#ifdef PNG_READ_iCCP_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001059void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001060png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1061/* Note: this does not properly handle chunks that are > 64K under DOS */
1062{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001063 png_byte compression_type;
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -06001064 png_bytep pC;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001065 png_charp profile;
1066 png_uint_32 skip = 0;
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05001067 png_uint_32 profile_size, profile_length;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001068 png_size_t slength, prefix_length, data_length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001069
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001070 png_debug(1, "in png_handle_iCCP");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001071
1072 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1073 png_error(png_ptr, "Missing IHDR before iCCP");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001074
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001075 else if (png_ptr->mode & PNG_HAVE_IDAT)
1076 {
1077 png_warning(png_ptr, "Invalid iCCP after IDAT");
1078 png_crc_finish(png_ptr, length);
1079 return;
1080 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001081
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001082 else if (png_ptr->mode & PNG_HAVE_PLTE)
1083 /* Should be an error, but we can cope with it */
1084 png_warning(png_ptr, "Out of place iCCP chunk");
1085
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001086 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001087 {
1088 png_warning(png_ptr, "Duplicate iCCP chunk");
1089 png_crc_finish(png_ptr, length);
1090 return;
1091 }
1092
1093#ifdef PNG_MAX_MALLOC_64K
1094 if (length > (png_uint_32)65535L)
1095 {
1096 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1097 skip = length - (png_uint_32)65535L;
1098 length = (png_uint_32)65535L;
1099 }
1100#endif
1101
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001102 png_free(png_ptr, png_ptr->chunkdata);
1103 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001104 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001105 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001106
1107 if (png_crc_finish(png_ptr, skip))
1108 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001109 png_free(png_ptr, png_ptr->chunkdata);
1110 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001111 return;
1112 }
1113
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001114 png_ptr->chunkdata[slength] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001115
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001116 for (profile = png_ptr->chunkdata; *profile; profile++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001117 /* Empty loop to find end of name */ ;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001118
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001119 ++profile;
1120
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001121 /* There should be at least one zero (the compression type byte)
1122 * following the separator, and we should be on it
1123 */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001124 if ( profile >= png_ptr->chunkdata + slength - 1)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001125 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001126 png_free(png_ptr, png_ptr->chunkdata);
1127 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001128 png_warning(png_ptr, "Malformed iCCP chunk");
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001129 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001130 }
1131
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001132 /* Compression_type should always be zero */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001133 compression_type = *profile++;
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001134 if (compression_type)
1135 {
1136 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001137 compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001138 wrote nonzero) */
1139 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001140
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001141 prefix_length = profile - png_ptr->chunkdata;
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -05001142 png_decompress_chunk(png_ptr, compression_type,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001143 slength, prefix_length, &data_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001144
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001145 profile_length = data_length - prefix_length;
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06001146
Glenn Randers-Pehrsondb3b88d2001-12-04 06:30:43 -06001147 if ( prefix_length > data_length || profile_length < 4)
Glenn Randers-Pehrsonb1828932001-06-23 08:03:17 -05001148 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001149 png_free(png_ptr, png_ptr->chunkdata);
1150 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrsonb1828932001-06-23 08:03:17 -05001151 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1152 return;
1153 }
1154
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06001155 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001156 pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001157 profile_size = ((*(pC )) << 24) |
1158 ((*(pC + 1)) << 16) |
1159 ((*(pC + 2)) << 8) |
1160 ((*(pC + 3)) );
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001161
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001162 if (profile_size < profile_length)
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001163 profile_length = profile_size;
1164
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001165 if (profile_size > profile_length)
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001166 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001167 png_free(png_ptr, png_ptr->chunkdata);
1168 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -06001169#ifdef PNG_STDIO_SUPPORTED
1170 {
Glenn Randers-Pehrson92a3ef42010-03-31 21:50:21 -05001171 char umsg[80];
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -06001172
Glenn Randers-Pehrson92a3ef42010-03-31 21:50:21 -05001173 png_snprintf2(umsg, 80,
1174 "Ignoring iCCP chunk with declared size = %lu "
1175 "and actual length = %lu",
1176 (unsigned long)profile_size,
Glenn Randers-Pehrson9b0956f2010-02-12 11:17:22 -06001177 (unsigned long)profile_length);
1178 png_warning(png_ptr, umsg);
1179 }
1180#endif
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001181 return;
1182 }
1183
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001184 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001185 compression_type, png_ptr->chunkdata + prefix_length, profile_length);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001186 png_free(png_ptr, png_ptr->chunkdata);
1187 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001188}
1189#endif /* PNG_READ_iCCP_SUPPORTED */
1190
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001191#ifdef PNG_READ_sPLT_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001192void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001193png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1194/* Note: this does not properly handle chunks that are > 64K under DOS */
1195{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001196 png_bytep entry_start;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001197 png_sPLT_t new_palette;
Glenn Randers-Pehrson90b878c2009-10-07 12:44:35 -05001198#ifdef PNG_POINTER_INDEXING_SUPPORTED
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001199 png_sPLT_entryp pp;
1200#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001201 int data_length, entry_size, i;
1202 png_uint_32 skip = 0;
1203 png_size_t slength;
1204
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001205 png_debug(1, "in png_handle_sPLT");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001206
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06001207#ifdef PNG_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrson7824a702009-06-13 10:05:05 -05001208
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05001209 if (png_ptr->user_chunk_cache_max != 0)
1210 {
1211 if (png_ptr->user_chunk_cache_max == 1)
1212 {
1213 png_crc_finish(png_ptr, length);
1214 return;
1215 }
1216 if (--png_ptr->user_chunk_cache_max == 1)
1217 {
1218 png_warning(png_ptr, "No space in chunk cache for sPLT");
1219 png_crc_finish(png_ptr, length);
1220 return;
1221 }
1222 }
1223#endif
1224
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001225 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1226 png_error(png_ptr, "Missing IHDR before sPLT");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001227
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001228 else if (png_ptr->mode & PNG_HAVE_IDAT)
1229 {
1230 png_warning(png_ptr, "Invalid sPLT after IDAT");
1231 png_crc_finish(png_ptr, length);
1232 return;
1233 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001234
1235#ifdef PNG_MAX_MALLOC_64K
1236 if (length > (png_uint_32)65535L)
1237 {
1238 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1239 skip = length - (png_uint_32)65535L;
1240 length = (png_uint_32)65535L;
1241 }
1242#endif
1243
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001244 png_free(png_ptr, png_ptr->chunkdata);
1245 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001246 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001247 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001248
1249 if (png_crc_finish(png_ptr, skip))
1250 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001251 png_free(png_ptr, png_ptr->chunkdata);
1252 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001253 return;
1254 }
1255
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001256 png_ptr->chunkdata[slength] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001257
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06001258 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
1259 entry_start++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001260 /* Empty loop to find end of name */ ;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001261
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001262 ++entry_start;
1263
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001264 /* A sample depth should follow the separator, and we should be on it */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001265 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001266 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001267 png_free(png_ptr, png_ptr->chunkdata);
1268 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001269 png_warning(png_ptr, "malformed sPLT chunk");
1270 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001271 }
1272
1273 new_palette.depth = *entry_start++;
Glenn Randers-Pehrsona565f0e2010-03-06 08:24:45 -06001274 entry_size = (new_palette.depth == 8 ? 6 : 10);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001275 data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001276
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001277 /* Integrity-check the data length */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001278 if (data_length % entry_size)
1279 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001280 png_free(png_ptr, png_ptr->chunkdata);
1281 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001282 png_warning(png_ptr, "sPLT chunk has bad length");
1283 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001284 }
1285
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06001286 new_palette.nentries = (png_int_32) ( data_length / entry_size);
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001287 if ((png_uint_32) new_palette.nentries >
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001288 (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001289 {
1290 png_warning(png_ptr, "sPLT chunk too long");
1291 return;
1292 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001293
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001294 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001295 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001296
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001297 if (new_palette.entries == NULL)
1298 {
1299 png_warning(png_ptr, "sPLT chunk requires too much memory");
1300 return;
1301 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001302
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05001303#ifdef PNG_POINTER_INDEXING_SUPPORTED
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001304 for (i = 0; i < new_palette.nentries; i++)
1305 {
Glenn Randers-Pehrson90b878c2009-10-07 12:44:35 -05001306 pp = new_palette.entries + i;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001307
1308 if (new_palette.depth == 8)
1309 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001310 pp->red = *entry_start++;
1311 pp->green = *entry_start++;
1312 pp->blue = *entry_start++;
1313 pp->alpha = *entry_start++;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001314 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001315
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001316 else
1317 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001318 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1319 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1320 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1321 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001322 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001323
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001324 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1325 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001326#else
1327 pp = new_palette.entries;
1328 for (i = 0; i < new_palette.nentries; i++)
1329 {
1330
1331 if (new_palette.depth == 8)
1332 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001333 pp[i].red = *entry_start++;
1334 pp[i].green = *entry_start++;
1335 pp[i].blue = *entry_start++;
1336 pp[i].alpha = *entry_start++;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001337 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001338
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001339 else
1340 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001341 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1342 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1343 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1344 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001345 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001346
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001347 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1348 }
1349#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001350
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001351 /* Discard all chunk data except the name and stash that */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001352 new_palette.name = png_ptr->chunkdata;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001353
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001354 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001355
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001356 png_free(png_ptr, png_ptr->chunkdata);
1357 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001358 png_free(png_ptr, new_palette.entries);
1359}
1360#endif /* PNG_READ_sPLT_SUPPORTED */
1361
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001362#ifdef PNG_READ_tRNS_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001363void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001364png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001365{
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001366 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001367
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001368 png_debug(1, "in png_handle_tRNS");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001369
Guy Schalnate5a37791996-06-05 15:50:50 -05001370 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1371 png_error(png_ptr, "Missing IHDR before tRNS");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001372 else if (png_ptr->mode & PNG_HAVE_IDAT)
1373 {
1374 png_warning(png_ptr, "Invalid tRNS after IDAT");
1375 png_crc_finish(png_ptr, length);
1376 return;
1377 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001378
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001379 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001380 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001381 png_warning(png_ptr, "Duplicate tRNS chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001382 png_crc_finish(png_ptr, length);
1383 return;
1384 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001385
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001386 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001387 {
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001388 png_byte buf[2];
Guy Schalnat0d580581995-07-20 02:43:20 -05001389
1390 if (length != 2)
1391 {
Guy Schalnat69b14481996-01-10 02:56:49 -06001392 png_warning(png_ptr, "Incorrect tRNS chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001393 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001394 return;
1395 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001396
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001397 png_crc_read(png_ptr, buf, 2);
1398 png_ptr->num_trans = 1;
Glenn Randers-Pehrson56f63962008-10-06 10:16:17 -05001399 png_ptr->trans_color.gray = png_get_uint_16(buf);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001400 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001401
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001402 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1403 {
1404 png_byte buf[6];
1405
1406 if (length != 6)
1407 {
1408 png_warning(png_ptr, "Incorrect tRNS chunk length");
1409 png_crc_finish(png_ptr, length);
1410 return;
1411 }
1412 png_crc_read(png_ptr, buf, (png_size_t)length);
1413 png_ptr->num_trans = 1;
Glenn Randers-Pehrson56f63962008-10-06 10:16:17 -05001414 png_ptr->trans_color.red = png_get_uint_16(buf);
1415 png_ptr->trans_color.green = png_get_uint_16(buf + 2);
1416 png_ptr->trans_color.blue = png_get_uint_16(buf + 4);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001417 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001418
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001419 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1420 {
1421 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1422 {
1423 /* Should be an error, but we can cope with it. */
1424 png_warning(png_ptr, "Missing PLTE before tRNS");
1425 }
1426 if (length > (png_uint_32)png_ptr->num_palette ||
1427 length > PNG_MAX_PALETTE_LENGTH)
1428 {
1429 png_warning(png_ptr, "Incorrect tRNS chunk length");
1430 png_crc_finish(png_ptr, length);
1431 return;
1432 }
1433 if (length == 0)
1434 {
1435 png_warning(png_ptr, "Zero length tRNS chunk");
1436 png_crc_finish(png_ptr, length);
1437 return;
1438 }
1439 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1440 png_ptr->num_trans = (png_uint_16)length;
1441 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001442
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001443 else
Guy Schalnate5a37791996-06-05 15:50:50 -05001444 {
1445 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001446 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001447 return;
1448 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001449
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001450 if (png_crc_finish(png_ptr, 0))
Glenn Randers-Pehrsona7dbcba2007-05-15 16:16:34 -05001451 {
1452 png_ptr->num_trans = 0;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001453 return;
Glenn Randers-Pehrsona7dbcba2007-05-15 16:16:34 -05001454 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001455
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001456 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001457 &(png_ptr->trans_color));
Guy Schalnat0d580581995-07-20 02:43:20 -05001458}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001459#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001460
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001461#ifdef PNG_READ_bKGD_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001462void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001463png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001464{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001465 png_size_t truelen;
Guy Schalnat0d580581995-07-20 02:43:20 -05001466 png_byte buf[6];
1467
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001468 png_debug(1, "in png_handle_bKGD");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001469
Guy Schalnate5a37791996-06-05 15:50:50 -05001470 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1471 png_error(png_ptr, "Missing IHDR before bKGD");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001472
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001473 else if (png_ptr->mode & PNG_HAVE_IDAT)
1474 {
1475 png_warning(png_ptr, "Invalid bKGD after IDAT");
1476 png_crc_finish(png_ptr, length);
1477 return;
1478 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001479
Guy Schalnate5a37791996-06-05 15:50:50 -05001480 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001481 !(png_ptr->mode & PNG_HAVE_PLTE))
Guy Schalnate5a37791996-06-05 15:50:50 -05001482 {
1483 png_warning(png_ptr, "Missing PLTE before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001484 png_crc_finish(png_ptr, length);
1485 return;
1486 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001487
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001488 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001489 {
1490 png_warning(png_ptr, "Duplicate bKGD chunk");
1491 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001492 return;
1493 }
1494
Guy Schalnat0d580581995-07-20 02:43:20 -05001495 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1496 truelen = 1;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001497
Guy Schalnat0d580581995-07-20 02:43:20 -05001498 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1499 truelen = 6;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001500
Guy Schalnat0d580581995-07-20 02:43:20 -05001501 else
1502 truelen = 2;
1503
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001504 if (length != truelen)
Guy Schalnat0d580581995-07-20 02:43:20 -05001505 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001506 png_warning(png_ptr, "Incorrect bKGD chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001507 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001508 return;
1509 }
1510
Andreas Dilger47a0c421997-05-16 02:46:07 -05001511 png_crc_read(png_ptr, buf, truelen);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001512
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001513 if (png_crc_finish(png_ptr, 0))
1514 return;
1515
Guy Schalnate5a37791996-06-05 15:50:50 -05001516 /* We convert the index value into RGB components so that we can allow
1517 * arbitrary RGB values for background when we have transparency, and
1518 * so it is easy to determine the RGB values of the background color
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001519 * from the info_ptr struct.
1520 */
Guy Schalnat0d580581995-07-20 02:43:20 -05001521 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnate5a37791996-06-05 15:50:50 -05001522 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001523 png_ptr->background.index = buf[0];
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001524 if (info_ptr && info_ptr->num_palette)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001525 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001526 if (buf[0] >= info_ptr->num_palette)
1527 {
1528 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1529 return;
1530 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001531
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001532 png_ptr->background.red =
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001533 (png_uint_16)png_ptr->palette[buf[0]].red;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001534
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001535 png_ptr->background.green =
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001536 (png_uint_16)png_ptr->palette[buf[0]].green;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001537
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001538 png_ptr->background.blue =
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001539 (png_uint_16)png_ptr->palette[buf[0]].blue;
1540 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001541 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001542
Andreas Dilger47a0c421997-05-16 02:46:07 -05001543 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
Guy Schalnate5a37791996-06-05 15:50:50 -05001544 {
1545 png_ptr->background.red =
1546 png_ptr->background.green =
1547 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -05001548 png_ptr->background.gray = png_get_uint_16(buf);
Guy Schalnate5a37791996-06-05 15:50:50 -05001549 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001550
Guy Schalnat0d580581995-07-20 02:43:20 -05001551 else
1552 {
1553 png_ptr->background.red = png_get_uint_16(buf);
1554 png_ptr->background.green = png_get_uint_16(buf + 2);
1555 png_ptr->background.blue = png_get_uint_16(buf + 4);
1556 }
1557
Andreas Dilger47a0c421997-05-16 02:46:07 -05001558 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
Guy Schalnat0d580581995-07-20 02:43:20 -05001559}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001560#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001561
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001562#ifdef PNG_READ_hIST_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001563void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001564png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001565{
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001566 unsigned int num, i;
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001567 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
Guy Schalnat0d580581995-07-20 02:43:20 -05001568
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001569 png_debug(1, "in png_handle_hIST");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001570
Guy Schalnate5a37791996-06-05 15:50:50 -05001571 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1572 png_error(png_ptr, "Missing IHDR before hIST");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001573
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001574 else if (png_ptr->mode & PNG_HAVE_IDAT)
1575 {
1576 png_warning(png_ptr, "Invalid hIST after IDAT");
1577 png_crc_finish(png_ptr, length);
1578 return;
1579 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001580
Guy Schalnate5a37791996-06-05 15:50:50 -05001581 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1582 {
1583 png_warning(png_ptr, "Missing PLTE before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001584 png_crc_finish(png_ptr, length);
1585 return;
1586 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001587
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001588 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001589 {
1590 png_warning(png_ptr, "Duplicate hIST chunk");
1591 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001592 return;
1593 }
1594
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001595 num = length / 2 ;
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001596 if (num != (unsigned int) png_ptr->num_palette || num >
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001597 (unsigned int) PNG_MAX_PALETTE_LENGTH)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001598 {
1599 png_warning(png_ptr, "Incorrect hIST chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001600 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001601 return;
1602 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001603
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001604 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001605 {
1606 png_byte buf[2];
1607
1608 png_crc_read(png_ptr, buf, 2);
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001609 readbuf[i] = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001610 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001611
1612 if (png_crc_finish(png_ptr, 0))
1613 return;
1614
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001615 png_set_hIST(png_ptr, info_ptr, readbuf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001616}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001617#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001618
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001619#ifdef PNG_READ_pHYs_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001620void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001621png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001622{
1623 png_byte buf[9];
1624 png_uint_32 res_x, res_y;
1625 int unit_type;
1626
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001627 png_debug(1, "in png_handle_pHYs");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001628
Guy Schalnate5a37791996-06-05 15:50:50 -05001629 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001630 png_error(png_ptr, "Missing IHDR before pHYs");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001631
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001632 else if (png_ptr->mode & PNG_HAVE_IDAT)
1633 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001634 png_warning(png_ptr, "Invalid pHYs after IDAT");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001635 png_crc_finish(png_ptr, length);
1636 return;
1637 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001638
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001639 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001640 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001641 png_warning(png_ptr, "Duplicate pHYs chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001642 png_crc_finish(png_ptr, length);
1643 return;
1644 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001645
Guy Schalnat0d580581995-07-20 02:43:20 -05001646 if (length != 9)
1647 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001648 png_warning(png_ptr, "Incorrect pHYs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001649 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001650 return;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001651 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001652
1653 png_crc_read(png_ptr, buf, 9);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001654
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001655 if (png_crc_finish(png_ptr, 0))
1656 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001657
1658 res_x = png_get_uint_32(buf);
1659 res_y = png_get_uint_32(buf + 4);
1660 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001661 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
Guy Schalnat0d580581995-07-20 02:43:20 -05001662}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001663#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001664
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001665#ifdef PNG_READ_oFFs_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001666void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001667png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001668{
1669 png_byte buf[9];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001670 png_int_32 offset_x, offset_y;
Guy Schalnat0d580581995-07-20 02:43:20 -05001671 int unit_type;
1672
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001673 png_debug(1, "in png_handle_oFFs");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001674
Guy Schalnate5a37791996-06-05 15:50:50 -05001675 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1676 png_error(png_ptr, "Missing IHDR before oFFs");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001677
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001678 else if (png_ptr->mode & PNG_HAVE_IDAT)
1679 {
1680 png_warning(png_ptr, "Invalid oFFs after IDAT");
1681 png_crc_finish(png_ptr, length);
1682 return;
1683 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001684
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001685 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001686 {
1687 png_warning(png_ptr, "Duplicate oFFs chunk");
1688 png_crc_finish(png_ptr, length);
1689 return;
1690 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001691
Guy Schalnat0d580581995-07-20 02:43:20 -05001692 if (length != 9)
1693 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001694 png_warning(png_ptr, "Incorrect oFFs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001695 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001696 return;
1697 }
1698
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001699 png_crc_read(png_ptr, buf, 9);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001700
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001701 if (png_crc_finish(png_ptr, 0))
1702 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001703
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001704 offset_x = png_get_int_32(buf);
1705 offset_y = png_get_int_32(buf + 4);
Guy Schalnat0d580581995-07-20 02:43:20 -05001706 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001707 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1708}
1709#endif
1710
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001711#ifdef PNG_READ_pCAL_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001712/* Read the pCAL chunk (described in the PNG Extensions document) */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001713void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001714png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1715{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001716 png_int_32 X0, X1;
1717 png_byte type, nparams;
1718 png_charp buf, units, endptr;
1719 png_charpp params;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001720 png_size_t slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001721 int i;
1722
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001723 png_debug(1, "in png_handle_pCAL");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001724
1725 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1726 png_error(png_ptr, "Missing IHDR before pCAL");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001727
Andreas Dilger47a0c421997-05-16 02:46:07 -05001728 else if (png_ptr->mode & PNG_HAVE_IDAT)
1729 {
1730 png_warning(png_ptr, "Invalid pCAL after IDAT");
1731 png_crc_finish(png_ptr, length);
1732 return;
1733 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001734
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001735 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
Andreas Dilger47a0c421997-05-16 02:46:07 -05001736 {
1737 png_warning(png_ptr, "Duplicate pCAL chunk");
1738 png_crc_finish(png_ptr, length);
1739 return;
1740 }
1741
Glenn Randers-Pehrson632a84e2010-03-09 22:28:33 -06001742 png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)",
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001743 length + 1);
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001744 png_free(png_ptr, png_ptr->chunkdata);
1745 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001746
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001747 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001748 {
1749 png_warning(png_ptr, "No memory for pCAL purpose");
1750 return;
1751 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001752
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001753 slength = (png_size_t)length;
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001754 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001755
1756 if (png_crc_finish(png_ptr, 0))
1757 {
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001758 png_free(png_ptr, png_ptr->chunkdata);
1759 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001760 return;
1761 }
1762
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001763 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001764
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001765 png_debug(3, "Finding end of pCAL purpose string");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001766 for (buf = png_ptr->chunkdata; *buf; buf++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001767 /* Empty loop */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001768
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001769 endptr = png_ptr->chunkdata + slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001770
1771 /* We need to have at least 12 bytes after the purpose string
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001772 * in order to get the parameter information.
1773 */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001774 if (endptr <= buf + 12)
1775 {
1776 png_warning(png_ptr, "Invalid pCAL data");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001777 png_free(png_ptr, png_ptr->chunkdata);
1778 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001779 return;
1780 }
1781
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001782 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001783 X0 = png_get_int_32((png_bytep)buf+1);
1784 X1 = png_get_int_32((png_bytep)buf+5);
1785 type = buf[9];
1786 nparams = buf[10];
1787 units = buf + 11;
1788
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001789 png_debug(3, "Checking pCAL equation type and number of parameters");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001790 /* Check that we have the right number of parameters for known
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001791 * equation types.
1792 */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001793 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1794 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1795 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1796 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1797 {
1798 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001799 png_free(png_ptr, png_ptr->chunkdata);
1800 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001801 return;
1802 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001803
Andreas Dilger47a0c421997-05-16 02:46:07 -05001804 else if (type >= PNG_EQUATION_LAST)
1805 {
1806 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1807 }
1808
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001809 for (buf = units; *buf; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001810 /* Empty loop to move past the units string. */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001811
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001812 png_debug(3, "Allocating pCAL parameters array");
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001813 params = (png_charpp)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001814 (png_size_t)(nparams * png_sizeof(png_charp)));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001815 if (params == NULL)
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001816 {
1817 png_free(png_ptr, png_ptr->chunkdata);
1818 png_ptr->chunkdata = NULL;
1819 png_warning(png_ptr, "No memory for pCAL params");
1820 return;
1821 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001822
1823 /* Get pointers to the start of each parameter string. */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001824 for (i = 0; i < (int)nparams; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001825 {
1826 buf++; /* Skip the null string terminator from previous parameter. */
1827
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001828 png_debug1(3, "Reading pCAL parameter %d", i);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001829 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001830 /* Empty loop to move past each parameter string */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001831
1832 /* Make sure we haven't run out of data yet */
1833 if (buf > endptr)
1834 {
1835 png_warning(png_ptr, "Invalid pCAL data");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001836 png_free(png_ptr, png_ptr->chunkdata);
1837 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001838 png_free(png_ptr, params);
1839 return;
1840 }
1841 }
1842
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001843 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001844 units, params);
1845
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001846 png_free(png_ptr, png_ptr->chunkdata);
1847 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001848 png_free(png_ptr, params);
Guy Schalnat0d580581995-07-20 02:43:20 -05001849}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001850#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001851
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001852#ifdef PNG_READ_sCAL_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001853/* Read the sCAL chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001854void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001855png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1856{
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001857 png_charp ep;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001858#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001859 double width, height;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001860 png_charp vp;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001861#else
1862#ifdef PNG_FIXED_POINT_SUPPORTED
1863 png_charp swidth, sheight;
1864#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001865#endif
1866 png_size_t slength;
1867
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001868 png_debug(1, "in png_handle_sCAL");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001869
1870 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1871 png_error(png_ptr, "Missing IHDR before sCAL");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001872
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001873 else if (png_ptr->mode & PNG_HAVE_IDAT)
1874 {
1875 png_warning(png_ptr, "Invalid sCAL after IDAT");
1876 png_crc_finish(png_ptr, length);
1877 return;
1878 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001879
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001880 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001881 {
1882 png_warning(png_ptr, "Duplicate sCAL chunk");
1883 png_crc_finish(png_ptr, length);
1884 return;
1885 }
1886
Glenn Randers-Pehrson632a84e2010-03-09 22:28:33 -06001887 png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)",
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001888 length + 1);
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001889 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001890
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001891 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001892 {
1893 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -05001894 png_crc_finish(png_ptr, length);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001895 return;
1896 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001897
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001898 slength = (png_size_t)length;
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001899 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001900
1901 if (png_crc_finish(png_ptr, 0))
1902 {
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001903 png_free(png_ptr, png_ptr->chunkdata);
1904 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001905 return;
1906 }
1907
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001908 png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001909
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001910 ep = png_ptr->chunkdata + 1; /* Skip unit byte */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001911
1912#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001913 width = png_strtod(png_ptr, ep, &vp);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001914 if (*vp)
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001915 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001916 png_warning(png_ptr, "malformed width string in sCAL chunk");
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -05001917 png_free(png_ptr, png_ptr->chunkdata);
1918 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001919 return;
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001920 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001921#else
1922#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001923 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001924
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001925 if (swidth == NULL)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001926 {
1927 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -05001928 png_free(png_ptr, png_ptr->chunkdata);
1929 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001930 return;
1931 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001932
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001933 png_memcpy(swidth, ep, png_strlen(ep));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001934#endif
1935#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001936
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001937 for (ep = png_ptr->chunkdata; *ep; ep++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001938 /* Empty loop */ ;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001939
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001940 ep++;
1941
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001942 if (png_ptr->chunkdata + slength < ep)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001943 {
1944 png_warning(png_ptr, "Truncated sCAL chunk");
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -05001945#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001946 png_free(png_ptr, swidth);
1947#endif
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001948 png_free(png_ptr, png_ptr->chunkdata);
1949 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001950 return;
1951 }
1952
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001953#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001954 height = png_strtod(png_ptr, ep, &vp);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001955
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001956 if (*vp)
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001957 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001958 png_warning(png_ptr, "malformed height string in sCAL chunk");
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -05001959 png_free(png_ptr, png_ptr->chunkdata);
1960 png_ptr->chunkdata = NULL;
1961#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1962 png_free(png_ptr, swidth);
1963#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001964 return;
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001965 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001966
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001967#else
1968#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001969 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001970
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001971 if (sheight == NULL)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001972 {
1973 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -05001974 png_free(png_ptr, png_ptr->chunkdata);
1975 png_ptr->chunkdata = NULL;
1976#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1977 png_free(png_ptr, swidth);
1978#endif
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001979 return;
1980 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001981
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001982 png_memcpy(sheight, ep, png_strlen(ep));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001983#endif
1984#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001985
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001986 if (png_ptr->chunkdata + slength < ep
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001987#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001988 || width <= 0. || height <= 0.
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001989#endif
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06001990 )
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001991 {
1992 png_warning(png_ptr, "Invalid sCAL data");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001993 png_free(png_ptr, png_ptr->chunkdata);
1994 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001995#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001996 png_free(png_ptr, swidth);
1997 png_free(png_ptr, sheight);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001998#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001999 return;
2000 }
2001
2002
2003#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05002004 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002005#else
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002006#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05002007 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002008#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002009#endif
2010
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05002011 png_free(png_ptr, png_ptr->chunkdata);
2012 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002013#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
2014 png_free(png_ptr, swidth);
2015 png_free(png_ptr, sheight);
2016#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002017}
2018#endif
2019
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002020#ifdef PNG_READ_tIME_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002021void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002022png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05002023{
2024 png_byte buf[7];
2025 png_time mod_time;
2026
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002027 png_debug(1, "in png_handle_tIME");
Andreas Dilger47a0c421997-05-16 02:46:07 -05002028
Guy Schalnate5a37791996-06-05 15:50:50 -05002029 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002030 png_error(png_ptr, "Out of place tIME chunk");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002031
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002032 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002033 {
2034 png_warning(png_ptr, "Duplicate tIME chunk");
2035 png_crc_finish(png_ptr, length);
2036 return;
2037 }
2038
2039 if (png_ptr->mode & PNG_HAVE_IDAT)
2040 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnate5a37791996-06-05 15:50:50 -05002041
Guy Schalnat0d580581995-07-20 02:43:20 -05002042 if (length != 7)
2043 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002044 png_warning(png_ptr, "Incorrect tIME chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002045 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05002046 return;
2047 }
2048
2049 png_crc_read(png_ptr, buf, 7);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002050
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002051 if (png_crc_finish(png_ptr, 0))
2052 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05002053
2054 mod_time.second = buf[6];
2055 mod_time.minute = buf[5];
2056 mod_time.hour = buf[4];
2057 mod_time.day = buf[3];
2058 mod_time.month = buf[2];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002059 mod_time.year = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05002060
Andreas Dilger47a0c421997-05-16 02:46:07 -05002061 png_set_tIME(png_ptr, info_ptr, &mod_time);
Guy Schalnat0d580581995-07-20 02:43:20 -05002062}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002063#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002064
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002065#ifdef PNG_READ_tEXt_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002066/* Note: this does not properly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002067void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002068png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05002069{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002070 png_textp text_ptr;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002071 png_charp key;
Guy Schalnat6d764711995-12-19 03:22:19 -06002072 png_charp text;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002073 png_uint_32 skip = 0;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002074 png_size_t slength;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002075 int ret;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002076
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002077 png_debug(1, "in png_handle_tEXt");
Guy Schalnat0d580581995-07-20 02:43:20 -05002078
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06002079#ifdef PNG_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002080 if (png_ptr->user_chunk_cache_max != 0)
2081 {
2082 if (png_ptr->user_chunk_cache_max == 1)
2083 {
2084 png_crc_finish(png_ptr, length);
2085 return;
2086 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002087
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002088 if (--png_ptr->user_chunk_cache_max == 1)
2089 {
2090 png_warning(png_ptr, "No space in chunk cache for tEXt");
2091 png_crc_finish(png_ptr, length);
2092 return;
2093 }
2094 }
2095#endif
2096
Guy Schalnate5a37791996-06-05 15:50:50 -05002097 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2098 png_error(png_ptr, "Missing IHDR before tEXt");
2099
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002100 if (png_ptr->mode & PNG_HAVE_IDAT)
2101 png_ptr->mode |= PNG_AFTER_IDAT;
2102
Andreas Dilger47a0c421997-05-16 02:46:07 -05002103#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002104 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002105 {
2106 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002107 skip = length - (png_uint_32)65535L;
2108 length = (png_uint_32)65535L;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002109 }
2110#endif
2111
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002112 png_free(png_ptr, png_ptr->chunkdata);
2113
2114 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2115 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002116 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05002117 png_warning(png_ptr, "No memory to process text chunk");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002118 return;
2119 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002120 slength = (png_size_t)length;
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002121 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002122
2123 if (png_crc_finish(png_ptr, skip))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002124 {
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002125 png_free(png_ptr, png_ptr->chunkdata);
2126 png_ptr->chunkdata = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002127 return;
2128 }
2129
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002130 key = png_ptr->chunkdata;
2131
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002132 key[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05002133
2134 for (text = key; *text; text++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002135 /* Empty loop to find end of key */ ;
Guy Schalnat0d580581995-07-20 02:43:20 -05002136
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002137 if (text != key + slength)
Guy Schalnat0d580581995-07-20 02:43:20 -05002138 text++;
2139
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002140 text_ptr = (png_textp)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002141 png_sizeof(png_text));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002142
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002143 if (text_ptr == NULL)
2144 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002145 png_warning(png_ptr, "Not enough memory to process text chunk");
2146 png_free(png_ptr, png_ptr->chunkdata);
2147 png_ptr->chunkdata = NULL;
2148 return;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002149 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002150
Andreas Dilger47a0c421997-05-16 02:46:07 -05002151 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
2152 text_ptr->key = key;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002153 text_ptr->lang = NULL;
2154 text_ptr->lang_key = NULL;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002155 text_ptr->itxt_length = 0;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002156 text_ptr->text = text;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002157 text_ptr->text_length = png_strlen(text);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002158
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002159 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002160
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002161 png_free(png_ptr, png_ptr->chunkdata);
2162 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002163 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002164
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002165 if (ret)
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002166 png_warning(png_ptr, "Insufficient memory to process text chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -05002167}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002168#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002169
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002170#ifdef PNG_READ_zTXt_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002171/* Note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002172void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002173png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05002174{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002175 png_textp text_ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -06002176 png_charp text;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002177 int comp_type;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002178 int ret;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002179 png_size_t slength, prefix_len, data_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002180
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002181 png_debug(1, "in png_handle_zTXt");
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002182
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06002183#ifdef PNG_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002184 if (png_ptr->user_chunk_cache_max != 0)
2185 {
2186 if (png_ptr->user_chunk_cache_max == 1)
2187 {
2188 png_crc_finish(png_ptr, length);
2189 return;
2190 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002191
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002192 if (--png_ptr->user_chunk_cache_max == 1)
2193 {
2194 png_warning(png_ptr, "No space in chunk cache for zTXt");
2195 png_crc_finish(png_ptr, length);
2196 return;
2197 }
2198 }
2199#endif
2200
Guy Schalnate5a37791996-06-05 15:50:50 -05002201 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2202 png_error(png_ptr, "Missing IHDR before zTXt");
2203
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002204 if (png_ptr->mode & PNG_HAVE_IDAT)
2205 png_ptr->mode |= PNG_AFTER_IDAT;
2206
Andreas Dilger47a0c421997-05-16 02:46:07 -05002207#ifdef PNG_MAX_MALLOC_64K
2208 /* We will no doubt have problems with chunks even half this size, but
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002209 * there is no hard and fast rule to tell us where to stop.
2210 */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002211 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002212 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002213 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
2214 png_crc_finish(png_ptr, length);
2215 return;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002216 }
2217#endif
2218
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002219 png_free(png_ptr, png_ptr->chunkdata);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002220 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2221 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002222 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002223 png_warning(png_ptr, "Out of memory processing zTXt chunk");
2224 return;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002225 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002226
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002227 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002228 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002229
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002230 if (png_crc_finish(png_ptr, 0))
2231 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002232 png_free(png_ptr, png_ptr->chunkdata);
2233 png_ptr->chunkdata = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002234 return;
2235 }
2236
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002237 png_ptr->chunkdata[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05002238
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002239 for (text = png_ptr->chunkdata; *text; text++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002240 /* Empty loop */ ;
Guy Schalnat0d580581995-07-20 02:43:20 -05002241
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002242 /* zTXt must have some text after the chunkdataword */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002243 if (text >= png_ptr->chunkdata + slength - 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002244 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002245 png_warning(png_ptr, "Truncated zTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002246 png_free(png_ptr, png_ptr->chunkdata);
2247 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002248 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05002249 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002250
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002251 else
Guy Schalnat0d580581995-07-20 02:43:20 -05002252 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002253 comp_type = *(++text);
Glenn Randers-Pehrsonf05f8032000-12-23 14:27:39 -06002254 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2255 {
2256 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2257 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2258 }
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002259 text++; /* Skip the compression_method byte */
Guy Schalnat0d580581995-07-20 02:43:20 -05002260 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002261
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002262 prefix_len = text - png_ptr->chunkdata;
Guy Schalnat0d580581995-07-20 02:43:20 -05002263
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -05002264 png_decompress_chunk(png_ptr, comp_type,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002265 (png_size_t)length, prefix_len, &data_len);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002266
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002267 text_ptr = (png_textp)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002268 png_sizeof(png_text));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002269
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002270 if (text_ptr == NULL)
2271 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002272 png_warning(png_ptr, "Not enough memory to process zTXt chunk");
2273 png_free(png_ptr, png_ptr->chunkdata);
2274 png_ptr->chunkdata = NULL;
2275 return;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002276 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002277
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002278 text_ptr->compression = comp_type;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002279 text_ptr->key = png_ptr->chunkdata;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002280 text_ptr->lang = NULL;
2281 text_ptr->lang_key = NULL;
2282 text_ptr->itxt_length = 0;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002283 text_ptr->text = png_ptr->chunkdata + prefix_len;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002284 text_ptr->text_length = data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002285
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002286 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002287
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002288 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002289 png_free(png_ptr, png_ptr->chunkdata);
2290 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002291
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002292 if (ret)
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002293 png_error(png_ptr, "Insufficient memory to store zTXt chunk");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002294}
2295#endif
2296
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002297#ifdef PNG_READ_iTXt_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002298/* Note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002299void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002300png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2301{
2302 png_textp text_ptr;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002303 png_charp key, lang, text, lang_key;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002304 int comp_flag;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002305 int comp_type = 0;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002306 int ret;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002307 png_size_t slength, prefix_len, data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002308
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002309 png_debug(1, "in png_handle_iTXt");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002310
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06002311#ifdef PNG_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002312 if (png_ptr->user_chunk_cache_max != 0)
2313 {
2314 if (png_ptr->user_chunk_cache_max == 1)
2315 {
2316 png_crc_finish(png_ptr, length);
2317 return;
2318 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002319
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002320 if (--png_ptr->user_chunk_cache_max == 1)
2321 {
2322 png_warning(png_ptr, "No space in chunk cache for iTXt");
2323 png_crc_finish(png_ptr, length);
2324 return;
2325 }
2326 }
2327#endif
2328
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002329 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2330 png_error(png_ptr, "Missing IHDR before iTXt");
2331
2332 if (png_ptr->mode & PNG_HAVE_IDAT)
2333 png_ptr->mode |= PNG_AFTER_IDAT;
2334
2335#ifdef PNG_MAX_MALLOC_64K
2336 /* We will no doubt have problems with chunks even half this size, but
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002337 * there is no hard and fast rule to tell us where to stop.
2338 */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002339 if (length > (png_uint_32)65535L)
2340 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002341 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
2342 png_crc_finish(png_ptr, length);
2343 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002344 }
2345#endif
2346
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002347 png_free(png_ptr, png_ptr->chunkdata);
2348 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2349 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002350 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002351 png_warning(png_ptr, "No memory to process iTXt chunk");
2352 return;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002353 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002354 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002355 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002356
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002357 if (png_crc_finish(png_ptr, 0))
2358 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002359 png_free(png_ptr, png_ptr->chunkdata);
2360 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002361 return;
2362 }
2363
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002364 png_ptr->chunkdata[slength] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002365
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002366 for (lang = png_ptr->chunkdata; *lang; lang++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002367 /* Empty loop */ ;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002368
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002369 lang++; /* Skip NUL separator */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002370
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002371 /* iTXt must have a language tag (possibly empty), two compression bytes,
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002372 * translated keyword (possibly empty), and possibly some text after the
2373 * keyword
2374 */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002375
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002376 if (lang >= png_ptr->chunkdata + slength - 3)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002377 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002378 png_warning(png_ptr, "Truncated iTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002379 png_free(png_ptr, png_ptr->chunkdata);
2380 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002381 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002382 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002383
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002384 else
2385 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002386 comp_flag = *lang++;
2387 comp_type = *lang++;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002388 }
2389
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002390 for (lang_key = lang; *lang_key; lang_key++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002391 /* Empty loop */ ;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002392
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002393 lang_key++; /* Skip NUL separator */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002394
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002395 if (lang_key >= png_ptr->chunkdata + slength)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002396 {
2397 png_warning(png_ptr, "Truncated iTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002398 png_free(png_ptr, png_ptr->chunkdata);
2399 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002400 return;
2401 }
2402
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002403 for (text = lang_key; *text; text++)
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002404 /* Empty loop */ ;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002405
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002406 text++; /* Skip NUL separator */
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002407
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002408 if (text >= png_ptr->chunkdata + slength)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002409 {
2410 png_warning(png_ptr, "Malformed iTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002411 png_free(png_ptr, png_ptr->chunkdata);
2412 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002413 return;
2414 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002415
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002416 prefix_len = text - png_ptr->chunkdata;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002417
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002418 key=png_ptr->chunkdata;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002419
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002420 if (comp_flag)
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002421 png_decompress_chunk(png_ptr, comp_type,
2422 (size_t)length, prefix_len, &data_len);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002423
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002424 else
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002425 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002426
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002427 text_ptr = (png_textp)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002428 png_sizeof(png_text));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002429
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002430 if (text_ptr == NULL)
2431 {
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002432 png_warning(png_ptr, "Not enough memory to process iTXt chunk");
2433 png_free(png_ptr, png_ptr->chunkdata);
2434 png_ptr->chunkdata = NULL;
2435 return;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002436 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002437
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002438 text_ptr->compression = (int)comp_flag + 1;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002439 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
2440 text_ptr->lang = png_ptr->chunkdata + (lang - key);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002441 text_ptr->itxt_length = data_len;
2442 text_ptr->text_length = 0;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002443 text_ptr->key = png_ptr->chunkdata;
2444 text_ptr->text = png_ptr->chunkdata + prefix_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002445
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002446 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002447
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002448 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002449 png_free(png_ptr, png_ptr->chunkdata);
2450 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002451
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002452 if (ret)
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002453 png_error(png_ptr, "Insufficient memory to store iTXt chunk");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002454}
2455#endif
2456
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002457/* This function is called when we haven't found a handler for a
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002458 * chunk. If there isn't a problem with the chunk itself (ie bad
2459 * chunk name, CRC, or a critical chunk), the chunk is silently ignored
2460 * -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2461 * case it will be saved away to be written out later.
2462 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002463void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002464png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2465{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002466 png_uint_32 skip = 0;
2467
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002468 png_debug(1, "in png_handle_unknown");
Andreas Dilger47a0c421997-05-16 02:46:07 -05002469
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06002470#ifdef PNG_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002471 if (png_ptr->user_chunk_cache_max != 0)
2472 {
2473 if (png_ptr->user_chunk_cache_max == 1)
2474 {
2475 png_crc_finish(png_ptr, length);
2476 return;
2477 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002478
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002479 if (--png_ptr->user_chunk_cache_max == 1)
2480 {
2481 png_warning(png_ptr, "No space in chunk cache for unknown chunk");
2482 png_crc_finish(png_ptr, length);
2483 return;
2484 }
2485 }
2486#endif
2487
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002488 if (png_ptr->mode & PNG_HAVE_IDAT)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002489 {
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002490 PNG_IDAT;
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002491 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* Not an IDAT */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002492 png_ptr->mode |= PNG_AFTER_IDAT;
2493 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002494
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002495 if (!(png_ptr->chunk_name[0] & 0x20))
2496 {
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002497#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002498 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002499 PNG_HANDLE_CHUNK_ALWAYS
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002500#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002501 && png_ptr->read_user_chunk_fn == NULL
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002502#endif
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002503 )
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05002504#endif
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002505 png_chunk_error(png_ptr, "unknown critical chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002506 }
2507
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002508#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
Glenn Randers-Pehrson7824a702009-06-13 10:05:05 -05002509 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002510#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Glenn Randers-Pehrson7824a702009-06-13 10:05:05 -05002511 || (png_ptr->read_user_chunk_fn != NULL)
2512#endif
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002513 )
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002514 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002515#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002516 if (length > (png_uint_32)65535L)
2517 {
2518 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2519 skip = length - (png_uint_32)65535L;
2520 length = (png_uint_32)65535L;
2521 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002522#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002523
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002524 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
2525 (png_charp)png_ptr->chunk_name,
2526 png_sizeof(png_ptr->unknown_chunk.name));
2527 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1]
2528 = '\0';
2529 png_ptr->unknown_chunk.size = (png_size_t)length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002530
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002531 if (length == 0)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002532 png_ptr->unknown_chunk.data = NULL;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002533
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002534 else
2535 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002536 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2537 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002538 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002539
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002540#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002541 if (png_ptr->read_user_chunk_fn != NULL)
2542 {
2543 /* Callback to user unknown chunk handler */
2544 int ret;
2545 ret = (*(png_ptr->read_user_chunk_fn))
2546 (png_ptr, &png_ptr->unknown_chunk);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002547
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002548 if (ret < 0)
2549 png_chunk_error(png_ptr, "error in user chunk");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002550
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002551 if (ret == 0)
2552 {
2553 if (!(png_ptr->chunk_name[0] & 0x20))
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002554#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002555 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2556 PNG_HANDLE_CHUNK_ALWAYS)
Glenn Randers-Pehrson7824a702009-06-13 10:05:05 -05002557#endif
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002558 png_chunk_error(png_ptr, "unknown critical chunk");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002559
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002560 png_set_unknown_chunks(png_ptr, info_ptr,
2561 &png_ptr->unknown_chunk, 1);
2562 }
2563 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002564
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002565 else
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002566#endif
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002567 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002568
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002569 png_free(png_ptr, png_ptr->unknown_chunk.data);
2570 png_ptr->unknown_chunk.data = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002571 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002572
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002573 else
2574#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002575 skip = length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002576
2577 png_crc_finish(png_ptr, skip);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002578
Glenn Randers-Pehrsonb2aca212009-09-23 11:32:37 -05002579#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002580 info_ptr = info_ptr; /* Quiet compiler warnings about unused info_ptr */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002581#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002582}
2583
2584/* This function is called to verify that a chunk name is valid.
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002585 * This function can't have the "critical chunk check" incorporated
2586 * into it, since in the future we will need to be able to call user
2587 * functions to handle unknown critical chunks after we check that
2588 * the chunk name itself is valid.
2589 */
Andreas Dilger47a0c421997-05-16 02:46:07 -05002590
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05002591#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
Andreas Dilger47a0c421997-05-16 02:46:07 -05002592
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002593void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002594png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2595{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002596 png_debug(1, "in png_check_chunk_name");
Andreas Dilger47a0c421997-05-16 02:46:07 -05002597 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -05002598 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002599 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06002600 png_chunk_error(png_ptr, "invalid chunk type");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002601 }
2602}
2603
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002604/* Combines the row recently read in with the existing pixels in the
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002605 * row. This routine takes care of alpha and transparency if requested.
2606 * This routine also handles the two methods of progressive display
2607 * of interlaced images, depending on the mask value.
2608 * The mask value describes which pixels are to be combined with
2609 * the row. The pattern always repeats every 8 pixels, so just 8
2610 * bits are needed. A one indicates the pixel is to be combined,
2611 * a zero indicates the pixel is to be skipped. This is in addition
2612 * to any alpha or transparency value associated with the pixel. If
2613 * you want all pixels to be combined, pass 0xff (255) in mask.
2614 */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002615
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002616void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002617png_combine_row(png_structp png_ptr, png_bytep row, int mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002618{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002619 png_debug(1, "in png_combine_row");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002620
Guy Schalnat0d580581995-07-20 02:43:20 -05002621 if (mask == 0xff)
2622 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002623 png_memcpy(row, png_ptr->row_buf + 1,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06002624 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
Guy Schalnat0d580581995-07-20 02:43:20 -05002625 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002626
Guy Schalnat0d580581995-07-20 02:43:20 -05002627 else
2628 {
2629 switch (png_ptr->row_info.pixel_depth)
2630 {
2631 case 1:
2632 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002633 png_bytep sp = png_ptr->row_buf + 1;
2634 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002635 int s_inc, s_start, s_end;
2636 int m = 0x80;
2637 int shift;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002638 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002639 png_uint_32 row_width = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05002640
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002641#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002642 if (png_ptr->transformations & PNG_PACKSWAP)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002643 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002644 s_start = 0;
2645 s_end = 7;
2646 s_inc = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002647 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002648
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002649 else
2650#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002651 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002652 s_start = 7;
2653 s_end = 0;
2654 s_inc = -1;
2655 }
2656
2657 shift = s_start;
2658
2659 for (i = 0; i < row_width; i++)
2660 {
2661 if (m & mask)
2662 {
2663 int value;
2664
2665 value = (*sp >> shift) & 0x01;
2666 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2667 *dp |= (png_byte)(value << shift);
2668 }
2669
2670 if (shift == s_end)
2671 {
2672 shift = s_start;
2673 sp++;
2674 dp++;
2675 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002676
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002677 else
2678 shift += s_inc;
2679
2680 if (m == 1)
2681 m = 0x80;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002682
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002683 else
2684 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002685 }
2686 break;
2687 }
2688 case 2:
2689 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002690 png_bytep sp = png_ptr->row_buf + 1;
2691 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002692 int s_start, s_end, s_inc;
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002693 int m = 0x80;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002694 int shift;
2695 png_uint_32 i;
2696 png_uint_32 row_width = png_ptr->width;
2697 int value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002698
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002699#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002700 if (png_ptr->transformations & PNG_PACKSWAP)
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002701 {
2702 s_start = 0;
2703 s_end = 6;
2704 s_inc = 2;
2705 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002706
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002707 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002708#endif
2709 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002710 s_start = 6;
2711 s_end = 0;
2712 s_inc = -2;
2713 }
2714
2715 shift = s_start;
2716
2717 for (i = 0; i < row_width; i++)
2718 {
2719 if (m & mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002720 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002721 value = (*sp >> shift) & 0x03;
2722 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2723 *dp |= (png_byte)(value << shift);
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002724 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002725
2726 if (shift == s_end)
2727 {
2728 shift = s_start;
2729 sp++;
2730 dp++;
2731 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002732
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002733 else
2734 shift += s_inc;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002735
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002736 if (m == 1)
2737 m = 0x80;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002738
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002739 else
2740 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002741 }
2742 break;
2743 }
2744 case 4:
2745 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002746 png_bytep sp = png_ptr->row_buf + 1;
2747 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002748 int s_start, s_end, s_inc;
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002749 int m = 0x80;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002750 int shift;
2751 png_uint_32 i;
2752 png_uint_32 row_width = png_ptr->width;
2753 int value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002754
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002755#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002756 if (png_ptr->transformations & PNG_PACKSWAP)
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002757 {
2758 s_start = 0;
2759 s_end = 4;
2760 s_inc = 4;
2761 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002762
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002763 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002764#endif
2765 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002766 s_start = 4;
2767 s_end = 0;
2768 s_inc = -4;
2769 }
2770 shift = s_start;
2771
2772 for (i = 0; i < row_width; i++)
2773 {
2774 if (m & mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002775 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002776 value = (*sp >> shift) & 0xf;
2777 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2778 *dp |= (png_byte)(value << shift);
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002779 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002780
2781 if (shift == s_end)
2782 {
2783 shift = s_start;
2784 sp++;
2785 dp++;
2786 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002787
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002788 else
2789 shift += s_inc;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002790
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002791 if (m == 1)
2792 m = 0x80;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002793
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002794 else
2795 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002796 }
2797 break;
2798 }
2799 default:
2800 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002801 png_bytep sp = png_ptr->row_buf + 1;
2802 png_bytep dp = row;
2803 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2804 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002805 png_uint_32 row_width = png_ptr->width;
2806 png_byte m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05002807
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002808
2809 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002810 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002811 if (m & mask)
2812 {
2813 png_memcpy(dp, sp, pixel_bytes);
2814 }
2815
2816 sp += pixel_bytes;
2817 dp += pixel_bytes;
2818
2819 if (m == 1)
2820 m = 0x80;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002821
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002822 else
2823 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002824 }
2825 break;
2826 }
2827 }
2828 }
2829}
2830
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002831#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002832void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002833png_do_read_interlace(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002834{
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002835 png_row_infop row_info = &(png_ptr->row_info);
2836 png_bytep row = png_ptr->row_buf + 1;
2837 int pass = png_ptr->pass;
2838 png_uint_32 transformations = png_ptr->transformations;
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05002839 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2840 /* Offset to next interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002841 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002842
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002843 png_debug(1, "in png_do_read_interlace");
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002844 if (row != NULL && row_info != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002845 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002846 png_uint_32 final_width;
2847
2848 final_width = row_info->width * png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05002849
2850 switch (row_info->pixel_depth)
2851 {
2852 case 1:
2853 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002854 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2855 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002856 int sshift, dshift;
2857 int s_start, s_end, s_inc;
2858 int jstop = png_pass_inc[pass];
2859 png_byte v;
Guy Schalnat0d580581995-07-20 02:43:20 -05002860 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002861 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -05002862
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002863#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002864 if (transformations & PNG_PACKSWAP)
2865 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002866 sshift = (int)((row_info->width + 7) & 0x07);
2867 dshift = (int)((final_width + 7) & 0x07);
2868 s_start = 7;
2869 s_end = 0;
2870 s_inc = -1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002871 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002872
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002873 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002874#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002875 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002876 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2877 dshift = 7 - (int)((final_width + 7) & 0x07);
2878 s_start = 0;
2879 s_end = 7;
2880 s_inc = 1;
2881 }
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002882
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002883 for (i = 0; i < row_info->width; i++)
2884 {
2885 v = (png_byte)((*sp >> sshift) & 0x01);
2886 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002887 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002888 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2889 *dp |= (png_byte)(v << dshift);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002890
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002891 if (dshift == s_end)
2892 {
2893 dshift = s_start;
2894 dp--;
2895 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002896
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002897 else
2898 dshift += s_inc;
2899 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002900
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002901 if (sshift == s_end)
2902 {
2903 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002904 sp--;
2905 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002906
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002907 else
2908 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002909 }
2910 break;
2911 }
2912 case 2:
2913 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002914 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2915 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2916 int sshift, dshift;
2917 int s_start, s_end, s_inc;
2918 int jstop = png_pass_inc[pass];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002919 png_uint_32 i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002920
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002921#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002922 if (transformations & PNG_PACKSWAP)
2923 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002924 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2925 dshift = (int)(((final_width + 3) & 0x03) << 1);
2926 s_start = 6;
2927 s_end = 0;
2928 s_inc = -2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002929 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002930
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002931 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002932#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002933 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002934 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2935 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2936 s_start = 0;
2937 s_end = 6;
2938 s_inc = 2;
2939 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002940
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002941 for (i = 0; i < row_info->width; i++)
2942 {
2943 png_byte v;
2944 int j;
2945
2946 v = (png_byte)((*sp >> sshift) & 0x03);
2947 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002948 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002949 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2950 *dp |= (png_byte)(v << dshift);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002951
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002952 if (dshift == s_end)
2953 {
2954 dshift = s_start;
2955 dp--;
2956 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002957
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002958 else
2959 dshift += s_inc;
2960 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002961
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002962 if (sshift == s_end)
2963 {
2964 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002965 sp--;
2966 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002967
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002968 else
2969 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002970 }
2971 break;
2972 }
2973 case 4:
2974 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002975 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2976 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002977 int sshift, dshift;
2978 int s_start, s_end, s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002979 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002980 int jstop = png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05002981
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05002982#ifdef PNG_READ_PACKSWAP_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -05002983 if (transformations & PNG_PACKSWAP)
2984 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002985 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2986 dshift = (int)(((final_width + 1) & 0x01) << 2);
2987 s_start = 4;
2988 s_end = 0;
2989 s_inc = -4;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002990 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05002991
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002992 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002993#endif
2994 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002995 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2996 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2997 s_start = 0;
2998 s_end = 4;
2999 s_inc = 4;
3000 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05003001
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003002 for (i = 0; i < row_info->width; i++)
3003 {
3004 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
3005 int j;
Andreas Dilger47a0c421997-05-16 02:46:07 -05003006
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003007 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003008 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003009 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
3010 *dp |= (png_byte)(v << dshift);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003011
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003012 if (dshift == s_end)
3013 {
3014 dshift = s_start;
3015 dp--;
3016 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003017
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003018 else
3019 dshift += s_inc;
3020 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003021
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003022 if (sshift == s_end)
3023 {
3024 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05003025 sp--;
3026 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003027
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003028 else
3029 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05003030 }
3031 break;
3032 }
3033 default:
3034 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003035 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06003036 png_bytep sp = row + (png_size_t)(row_info->width - 1)
3037 * pixel_bytes;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003038 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05003039
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003040 int jstop = png_pass_inc[pass];
3041 png_uint_32 i;
3042
3043 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05003044 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003045 png_byte v[8];
3046 int j;
3047
3048 png_memcpy(v, sp, pixel_bytes);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003049
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003050 for (j = 0; j < jstop; j++)
3051 {
3052 png_memcpy(dp, v, pixel_bytes);
3053 dp -= pixel_bytes;
3054 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003055
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06003056 sp -= pixel_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05003057 }
3058 break;
3059 }
3060 }
3061 row_info->width = final_width;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003062 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
Guy Schalnat0d580581995-07-20 02:43:20 -05003063 }
Glenn Randers-Pehrsonb2aca212009-09-23 11:32:37 -05003064#ifndef PNG_READ_PACKSWAP_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003065 transformations = transformations; /* Silence compiler warning */
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05003066#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003067}
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06003068#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003069
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003070void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06003071png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003072 png_bytep prev_row, int filter)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003073{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05003074 png_debug(1, "in png_read_filter_row");
Glenn Randers-Pehrson632a84e2010-03-09 22:28:33 -06003075 png_debug2(2, "row = %u, filter = %d", png_ptr->row_number, filter);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003076 switch (filter)
3077 {
3078 case PNG_FILTER_VALUE_NONE:
3079 break;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003080
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003081 case PNG_FILTER_VALUE_SUB:
3082 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003083 png_uint_32 i;
3084 png_uint_32 istop = row_info->rowbytes;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003085 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003086 png_bytep rp = row + bpp;
3087 png_bytep lp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003088
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003089 for (i = bpp; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003090 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003091 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
3092 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003093 }
3094 break;
3095 }
3096 case PNG_FILTER_VALUE_UP:
3097 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003098 png_uint_32 i;
3099 png_uint_32 istop = row_info->rowbytes;
3100 png_bytep rp = row;
3101 png_bytep pp = prev_row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003102
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003103 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003104 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003105 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3106 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003107 }
3108 break;
3109 }
3110 case PNG_FILTER_VALUE_AVG:
3111 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003112 png_uint_32 i;
3113 png_bytep rp = row;
3114 png_bytep pp = prev_row;
3115 png_bytep lp = row;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003116 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003117 png_uint_32 istop = row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003118
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003119 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003120 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003121 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003122 ((int)(*pp++) / 2 )) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003123 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003124 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003125
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003126 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003127 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003128 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003129 (int)(*pp++ + *lp++) / 2 ) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003130 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003131 }
3132 break;
3133 }
3134 case PNG_FILTER_VALUE_PAETH:
3135 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003136 png_uint_32 i;
3137 png_bytep rp = row;
3138 png_bytep pp = prev_row;
3139 png_bytep lp = row;
3140 png_bytep cp = prev_row;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003141 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003142 png_uint_32 istop=row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003143
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003144 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003145 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003146 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3147 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003148 }
3149
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003150 for (i = 0; i < istop; i++) /* Use leftover rp,pp */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003151 {
3152 int a, b, c, pa, pb, pc, p;
3153
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003154 a = *lp++;
3155 b = *pp++;
3156 c = *cp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003157
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003158 p = b - c;
3159 pc = a - c;
3160
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003161#ifdef PNG_USE_ABS
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05003162 pa = abs(p);
3163 pb = abs(pc);
3164 pc = abs(p + pc);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003165#else
Glenn Randers-Pehrsona565f0e2010-03-06 08:24:45 -06003166 pa = p < 0 ? -p : p;
3167 pb = pc < 0 ? -pc : pc;
3168 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003169#endif
3170
3171 /*
3172 if (pa <= pb && pa <= pc)
3173 p = a;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003174
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003175 else if (pb <= pc)
3176 p = b;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003177
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003178 else
3179 p = c;
3180 */
3181
Glenn Randers-Pehrsona565f0e2010-03-06 08:24:45 -06003182 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003183
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05003184 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
3185 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003186 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003187 break;
3188 }
3189 default:
Glenn Randers-Pehrsona272d8f2010-06-25 21:45:31 -05003190 png_error(png_ptr, "Ignoring bad adaptive filter type");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003191 *row = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003192 break;
3193 }
3194}
Guy Schalnat0d580581995-07-20 02:43:20 -05003195
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05003196#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003197void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003198png_read_finish_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05003199{
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003200#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003201 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003202
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003203 /* Start of interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003204 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003205
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003206 /* Offset to next interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003207 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003208
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003209 /* Start of interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003210 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003211
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003212 /* Offset to next interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003213 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3214#endif /* PNG_READ_INTERLACING_SUPPORTED */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003215
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05003216 png_debug(1, "in png_read_finish_row");
Guy Schalnat0d580581995-07-20 02:43:20 -05003217 png_ptr->row_number++;
3218 if (png_ptr->row_number < png_ptr->num_rows)
3219 return;
3220
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003221#ifdef PNG_READ_INTERLACING_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05003222 if (png_ptr->interlaced)
3223 {
3224 png_ptr->row_number = 0;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003225
Glenn Randers-Pehrsona31c74f2009-05-18 15:52:01 -05003226 png_memset(png_ptr->prev_row, 0,
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003227 png_ptr->rowbytes + 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003228
Guy Schalnat0d580581995-07-20 02:43:20 -05003229 do
3230 {
3231 png_ptr->pass++;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003232
Guy Schalnat0d580581995-07-20 02:43:20 -05003233 if (png_ptr->pass >= 7)
3234 break;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003235
Guy Schalnat0d580581995-07-20 02:43:20 -05003236 png_ptr->iwidth = (png_ptr->width +
3237 png_pass_inc[png_ptr->pass] - 1 -
3238 png_pass_start[png_ptr->pass]) /
3239 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05003240
Guy Schalnat0d580581995-07-20 02:43:20 -05003241 if (!(png_ptr->transformations & PNG_INTERLACE))
3242 {
3243 png_ptr->num_rows = (png_ptr->height +
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003244 png_pass_yinc[png_ptr->pass] - 1 -
3245 png_pass_ystart[png_ptr->pass]) /
3246 png_pass_yinc[png_ptr->pass];
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003247
Guy Schalnat0d580581995-07-20 02:43:20 -05003248 if (!(png_ptr->num_rows))
3249 continue;
3250 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003251
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05003252 else /* if (png_ptr->transformations & PNG_INTERLACE) */
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003253 break;
Guy Schalnat0d580581995-07-20 02:43:20 -05003254 } while (png_ptr->iwidth == 0);
3255
3256 if (png_ptr->pass < 7)
3257 return;
3258 }
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003259#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003260
Guy Schalnate5a37791996-06-05 15:50:50 -05003261 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
Guy Schalnat0d580581995-07-20 02:43:20 -05003262 {
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003263 PNG_IDAT;
Guy Schalnat0d580581995-07-20 02:43:20 -05003264 char extra;
3265 int ret;
3266
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003267 png_ptr->zstream.next_out = (Byte *)&extra;
3268 png_ptr->zstream.avail_out = (uInt)1;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003269
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003270 for (;;)
Guy Schalnat0d580581995-07-20 02:43:20 -05003271 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003272 if (!(png_ptr->zstream.avail_in))
Guy Schalnat0d580581995-07-20 02:43:20 -05003273 {
3274 while (!png_ptr->idat_size)
3275 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003276 png_byte chunk_length[4];
Guy Schalnat0d580581995-07-20 02:43:20 -05003277
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003278 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -05003279
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003280 png_read_data(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05003281 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnat0d580581995-07-20 02:43:20 -05003282 png_reset_crc(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003283 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003284
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003285 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Guy Schalnat6d764711995-12-19 03:22:19 -06003286 png_error(png_ptr, "Not enough image data");
Guy Schalnat0d580581995-07-20 02:43:20 -05003287
3288 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003289
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003290 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
3291 png_ptr->zstream.next_in = png_ptr->zbuf;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003292
Guy Schalnat0d580581995-07-20 02:43:20 -05003293 if (png_ptr->zbuf_size > png_ptr->idat_size)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003294 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003295
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003296 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
3297 png_ptr->idat_size -= png_ptr->zstream.avail_in;
Guy Schalnat0d580581995-07-20 02:43:20 -05003298 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003299 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003300
Guy Schalnat0d580581995-07-20 02:43:20 -05003301 if (ret == Z_STREAM_END)
3302 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003303 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003304 png_ptr->idat_size)
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003305 png_warning(png_ptr, "Extra compressed data");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003306
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003307 png_ptr->mode |= PNG_AFTER_IDAT;
3308 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Guy Schalnat0d580581995-07-20 02:43:20 -05003309 break;
3310 }
3311 if (ret != Z_OK)
Glenn Randers-Pehrsona565f0e2010-03-06 08:24:45 -06003312 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003313 "Decompression Error");
Guy Schalnat0d580581995-07-20 02:43:20 -05003314
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003315 if (!(png_ptr->zstream.avail_out))
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003316 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003317 png_warning(png_ptr, "Extra compressed data");
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003318 png_ptr->mode |= PNG_AFTER_IDAT;
3319 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3320 break;
3321 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003322
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -06003323 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003324 png_ptr->zstream.avail_out = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003325 }
3326
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003327 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003328 png_warning(png_ptr, "Extra compression data");
Guy Schalnat0d580581995-07-20 02:43:20 -05003329
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003330 inflateReset(&png_ptr->zstream);
Guy Schalnat0d580581995-07-20 02:43:20 -05003331
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003332 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnat0d580581995-07-20 02:43:20 -05003333}
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05003334#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003335
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003336void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003337png_read_start_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05003338{
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003339#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003340 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003341
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003342 /* Start of interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003343 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003344
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003345 /* Offset to next interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003346 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003347
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003348 /* Start of interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003349 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003350
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003351 /* Offset to next interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003352 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3353#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003354
Guy Schalnat0d580581995-07-20 02:43:20 -05003355 int max_pixel_depth;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003356 png_size_t row_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05003357
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05003358 png_debug(1, "in png_read_start_row");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003359 png_ptr->zstream.avail_in = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003360 png_init_read_transformations(png_ptr);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003361#ifdef PNG_READ_INTERLACING_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05003362 if (png_ptr->interlaced)
3363 {
3364 if (!(png_ptr->transformations & PNG_INTERLACE))
3365 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003366 png_pass_ystart[0]) / png_pass_yinc[0];
Guy Schalnat0d580581995-07-20 02:43:20 -05003367 else
3368 png_ptr->num_rows = png_ptr->height;
3369
3370 png_ptr->iwidth = (png_ptr->width +
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003371 png_pass_inc[png_ptr->pass] - 1 -
3372 png_pass_start[png_ptr->pass]) /
3373 png_pass_inc[png_ptr->pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05003374 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003375
Guy Schalnat0d580581995-07-20 02:43:20 -05003376 else
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003377#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003378 {
3379 png_ptr->num_rows = png_ptr->height;
3380 png_ptr->iwidth = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05003381 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003382
Guy Schalnat0d580581995-07-20 02:43:20 -05003383 max_pixel_depth = png_ptr->pixel_depth;
3384
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003385#ifdef PNG_READ_PACK_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05003386 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003387 max_pixel_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003388#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003389
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003390#ifdef PNG_READ_EXPAND_SUPPORTED
Guy Schalnate5a37791996-06-05 15:50:50 -05003391 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05003392 {
3393 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3394 {
3395 if (png_ptr->num_trans)
3396 max_pixel_depth = 32;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003397
Guy Schalnat0d580581995-07-20 02:43:20 -05003398 else
3399 max_pixel_depth = 24;
3400 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003401
Guy Schalnat0d580581995-07-20 02:43:20 -05003402 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3403 {
3404 if (max_pixel_depth < 8)
3405 max_pixel_depth = 8;
3406 if (png_ptr->num_trans)
3407 max_pixel_depth *= 2;
3408 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003409
Guy Schalnat0d580581995-07-20 02:43:20 -05003410 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3411 {
3412 if (png_ptr->num_trans)
3413 {
3414 max_pixel_depth *= 4;
3415 max_pixel_depth /= 3;
3416 }
3417 }
3418 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003419#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003420
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003421#ifdef PNG_READ_FILLER_SUPPORTED
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003422 if (png_ptr->transformations & (PNG_FILLER))
Guy Schalnat0d580581995-07-20 02:43:20 -05003423 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003424 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3425 max_pixel_depth = 32;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003426
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003427 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003428 {
3429 if (max_pixel_depth <= 8)
3430 max_pixel_depth = 16;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003431
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003432 else
3433 max_pixel_depth = 32;
3434 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003435
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003436 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3437 {
3438 if (max_pixel_depth <= 32)
3439 max_pixel_depth = 32;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003440
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003441 else
3442 max_pixel_depth = 64;
3443 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003444 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003445#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003446
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003447#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05003448 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3449 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003450 if (
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003451#ifdef PNG_READ_EXPAND_SUPPORTED
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003452 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003453#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05003454#ifdef PNG_READ_FILLER_SUPPORTED
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003455 (png_ptr->transformations & (PNG_FILLER)) ||
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003456#endif
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003457 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
Guy Schalnat0d580581995-07-20 02:43:20 -05003458 {
3459 if (max_pixel_depth <= 16)
3460 max_pixel_depth = 32;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003461
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003462 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003463 max_pixel_depth = 64;
3464 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003465
Guy Schalnat0d580581995-07-20 02:43:20 -05003466 else
3467 {
3468 if (max_pixel_depth <= 8)
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003469 {
3470 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06003471 max_pixel_depth = 32;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003472
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003473 else
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06003474 max_pixel_depth = 24;
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003475 }
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06003476 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3477 max_pixel_depth = 64;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003478
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003479 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003480 max_pixel_depth = 48;
3481 }
3482 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003483#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003484
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05003485#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3486defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003487 if (png_ptr->transformations & PNG_USER_TRANSFORM)
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003488 {
3489 int user_pixel_depth = png_ptr->user_transform_depth*
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003490 png_ptr->user_transform_channels;
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003491 if (user_pixel_depth > max_pixel_depth)
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003492 max_pixel_depth=user_pixel_depth;
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003493 }
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003494#endif
3495
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003496 /* Align the width on the next larger 8 pixels. Mainly used
3497 * for interlacing
3498 */
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003499 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05003500 /* Calculate the maximum bytes needed, adding a byte and a pixel
3501 * for safety's sake
3502 */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003503 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003504 1 + ((max_pixel_depth + 7) >> 3);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003505
Guy Schalnat0d580581995-07-20 02:43:20 -05003506#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003507 if (row_bytes > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05003508 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05003509#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003510
Glenn Randers-Pehrsoneddc5af2009-11-20 21:15:06 -06003511 if (row_bytes + 48 > png_ptr->old_big_row_buf_size)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003512 {
3513 png_free(png_ptr, png_ptr->big_row_buf);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003514
Glenn Randers-Pehrson6917b512009-03-09 15:31:08 -05003515 if (png_ptr->interlaced)
Glenn Randers-Pehrsona515d302010-01-01 10:24:25 -06003516 png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
3517 row_bytes + 48);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003518
Glenn Randers-Pehrsona515d302010-01-01 10:24:25 -06003519 else
3520 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr,
3521 row_bytes + 48);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003522
Glenn Randers-Pehrsoneddc5af2009-11-20 21:15:06 -06003523 png_ptr->old_big_row_buf_size = row_bytes + 48;
3524
3525#ifdef PNG_ALIGNED_MEMORY_SUPPORTED
3526 /* Use 16-byte aligned memory for row_buf with at least 16 bytes
3527 * of padding before and after row_buf.
3528 */
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003529 png_ptr->row_buf = png_ptr->big_row_buf + 32 -
3530 (((png_alloc_size_t)png_ptr->big_row_buf + 15) & 0x0F);
3531
Glenn Randers-Pehrsoneddc5af2009-11-20 21:15:06 -06003532 png_ptr->old_big_row_buf_size = row_bytes + 48;
3533#else
3534 /* Use 32 bytes of padding before and 16 bytes after row_buf. */
Glenn Randers-Pehrson8fb550c2009-03-21 08:15:32 -05003535 png_ptr->row_buf = png_ptr->big_row_buf + 32;
Glenn Randers-Pehrsoneddc5af2009-11-20 21:15:06 -06003536#endif
3537 png_ptr->old_big_row_buf_size = row_bytes + 48;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003538 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003539
3540#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003541 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05003542 png_error(png_ptr, "This image requires a row greater than 64KB");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003543
Guy Schalnat0d580581995-07-20 02:43:20 -05003544#endif
Glenn Randers-Pehrsonebd7f9a2006-10-19 09:37:56 -05003545 if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003546 png_error(png_ptr, "Row has too many bytes to allocate in memory");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003547
Glenn Randers-Pehrsona98aa482009-10-13 09:23:39 -05003548 if (png_ptr->rowbytes + 1 > png_ptr->old_prev_row_size)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003549 {
Glenn Randers-Pehrsona98aa482009-10-13 09:23:39 -05003550 png_free(png_ptr, png_ptr->prev_row);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003551
Glenn Randers-Pehrsona98aa482009-10-13 09:23:39 -05003552 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
Glenn Randers-Pehrson72cda2d2010-03-06 08:18:03 -06003553 png_ptr->rowbytes + 1));
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05003554
Glenn Randers-Pehrsona98aa482009-10-13 09:23:39 -05003555 png_ptr->old_prev_row_size = png_ptr->rowbytes + 1;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003556 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003557
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003558 png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003559
Glenn Randers-Pehrson632a84e2010-03-09 22:28:33 -06003560 png_debug1(3, "width = %u,", png_ptr->width);
3561 png_debug1(3, "height = %u,", png_ptr->height);
3562 png_debug1(3, "iwidth = %u,", png_ptr->iwidth);
3563 png_debug1(3, "num_rows = %u,", png_ptr->num_rows);
3564 png_debug1(3, "rowbytes = %u,", png_ptr->rowbytes);
3565 png_debug1(3, "irowbytes = %u",
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06003566 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05003567
Guy Schalnate5a37791996-06-05 15:50:50 -05003568 png_ptr->flags |= PNG_FLAG_ROW_INIT;
Guy Schalnat0d580581995-07-20 02:43:20 -05003569}
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06003570#endif /* PNG_READ_SUPPORTED */