blob: 960b6916c06674e0460ae731fbe0f5403f305740 [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-Pehrson glennrp@comcast.net11a3c7b2009-05-15 20:33:24 -05004 * Last changed in libpng 1.4.0 [May 15, 2009]
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
Glenn Randers-Pehrson79134c62009-02-14 10:32:18 -06006 * Copyright (c) 1998-2009 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05007 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06009 *
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050010 * This file contains routines that are only called from within
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060011 * libpng itself during the course of reading an image.
12 */
Guy Schalnat0d580581995-07-20 02:43:20 -050013
Guy Schalnat0d580581995-07-20 02:43:20 -050014#include "png.h"
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -050015#if defined(PNG_READ_SUPPORTED)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050016#include "pngpriv.h"
Guy Schalnat0d580581995-07-20 02:43:20 -050017
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -050018# define png_strtod(p,a,b) strtod(a,b)
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060019png_uint_32 PNGAPI
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050020png_get_uint_31(png_structp png_ptr, png_bytep buf)
21{
22 png_uint_32 i = png_get_uint_32(buf);
23 if (i > PNG_UINT_31_MAX)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050024 png_error(png_ptr, "PNG unsigned integer out of range");
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050025 return (i);
26}
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -050027#ifndef PNG_USE_READ_MACROS
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050028/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060029png_uint_32 PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060030png_get_uint_32(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050031{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050032 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
Guy Schalnat0d580581995-07-20 02:43:20 -050033 ((png_uint_32)(*(buf + 1)) << 16) +
34 ((png_uint_32)(*(buf + 2)) << 8) +
35 (png_uint_32)(*(buf + 3));
36
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060037 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050038}
39
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050040/* Grab a signed 32-bit integer from a buffer in big-endian format. The
Andreas Dilger47a0c421997-05-16 02:46:07 -050041 * 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 -050042 * assumed that the machine format for signed integers is the same.
43 */
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060044png_int_32 PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050045png_get_int_32(png_bytep buf)
46{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050047 png_int_32 i = ((png_int_32)(*buf) << 24) +
Andreas Dilger47a0c421997-05-16 02:46:07 -050048 ((png_int_32)(*(buf + 1)) << 16) +
49 ((png_int_32)(*(buf + 2)) << 8) +
50 (png_int_32)(*(buf + 3));
51
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060052 return (i);
Andreas Dilger47a0c421997-05-16 02:46:07 -050053}
Andreas Dilger47a0c421997-05-16 02:46:07 -050054
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050055/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060056png_uint_16 PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060057png_get_uint_16(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050058{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050059 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060060 (png_uint_16)(*(buf + 1)));
Guy Schalnat0d580581995-07-20 02:43:20 -050061
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060062 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050063}
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -050064#endif /* PNG_USE_READ_MACROS */
Guy Schalnat0d580581995-07-20 02:43:20 -050065
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050066/* Read the chunk header (length + type name).
67 * Put the type name into png_ptr->chunk_name, and return the length.
68 */
69png_uint_32 /* PRIVATE */
70png_read_chunk_header(png_structp png_ptr)
71{
72 png_byte buf[8];
73 png_uint_32 length;
74
75#ifdef PNG_IO_STATE_SUPPORTED
76 /* Inform the I/O callback that the chunk header is being read.
77 * PNG_IO_CHUNK_HDR requires a single I/O call.
78 */
79 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_HDR;
80#endif
81
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050082 /* Read the length and the chunk name */
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050083 png_read_data(png_ptr, buf, 8);
84 length = png_get_uint_31(png_ptr, buf);
85
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050086 /* Put the chunk name into png_ptr->chunk_name */
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050087 png_memcpy(png_ptr->chunk_name, buf + 4, 4);
88
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -050089 png_debug2(0, "Reading %s chunk, length = %lu",
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050090 png_ptr->chunk_name, length);
91
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050092 /* Reset the crc and run it over the chunk name */
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050093 png_reset_crc(png_ptr);
94 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
95
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050096 /* Check to see if chunk name is valid */
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -050097 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
98
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -050099#ifdef PNG_IO_STATE_SUPPORTED
100 /* Inform the I/O callback that chunk data will (possibly) be read.
101 * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
102 */
103 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_DATA;
104#endif
105
106 return length;
107}
108
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500109/* Read data, and (optionally) run it through the CRC. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500110void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500111png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500112{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500113 if (png_ptr == NULL)
114 return;
Guy Schalnat6d764711995-12-19 03:22:19 -0600115 png_read_data(png_ptr, buf, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500116 png_calculate_crc(png_ptr, buf, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500117}
118
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600119/* Optionally skip data and then check the CRC. Depending on whether we
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500120 * are reading a ancillary or critical chunk, and how the program has set
121 * things up, we may calculate the CRC on the data and print a message.
122 * Returns '1' if there was a CRC error, '0' otherwise.
123 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500124int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600125png_crc_finish(png_structp png_ptr, png_uint_32 skip)
Guy Schalnat0d580581995-07-20 02:43:20 -0500126{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500127 png_size_t i;
128 png_size_t istop = png_ptr->zbuf_size;
Guy Schalnat0d580581995-07-20 02:43:20 -0500129
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -0500130 for (i = (png_size_t)skip; i > istop; i -= istop)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600131 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500132 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
Guy Schalnat0d580581995-07-20 02:43:20 -0500133 }
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500134 if (i)
Guy Schalnat0d580581995-07-20 02:43:20 -0500135 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500136 png_crc_read(png_ptr, png_ptr->zbuf, i);
Guy Schalnat0d580581995-07-20 02:43:20 -0500137 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600138
Andreas Dilger47a0c421997-05-16 02:46:07 -0500139 if (png_crc_error(png_ptr))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600140 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500141 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500142 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500143 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600144 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600145 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600146 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600147 }
148 else
149 {
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500150 png_chunk_benign_error(png_ptr, "CRC error");
151 return (0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600152 }
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600153 return (1);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600154 }
155
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600156 return (0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500157}
158
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600159/* 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 -0500160 * the data it has read thus far.
161 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500162int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600163png_crc_error(png_structp png_ptr)
164{
165 png_byte crc_bytes[4];
166 png_uint_32 crc;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500167 int need_crc = 1;
168
169 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
170 {
171 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
172 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
173 need_crc = 0;
174 }
175 else /* critical */
176 {
177 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
178 need_crc = 0;
179 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600180
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500181#ifdef PNG_IO_STATE_SUPPORTED
182 /* inform the I/O callback that the chunk CRC is being read */
183 /* PNG_IO_CHUNK_CRC requires the I/O to be done at once */
184 png_ptr->io_state = PNG_IO_READING | PNG_IO_CHUNK_CRC;
185#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500186
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600187 png_read_data(png_ptr, crc_bytes, 4);
188
Andreas Dilger47a0c421997-05-16 02:46:07 -0500189 if (need_crc)
190 {
191 crc = png_get_uint_32(crc_bytes);
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600192 return ((int)(crc != png_ptr->crc));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500193 }
194 else
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600195 return (0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600196}
197
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600198#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500199 defined(PNG_READ_iCCP_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600200/*
201 * Decompress trailing data in a chunk. The assumption is that chunkdata
202 * points at an allocated area holding the contents of a chunk with a
203 * trailing compressed part. What we get back is an allocated area
204 * holding the original prefix part and an uncompressed version of the
205 * trailing part (the malloc area passed in is freed).
206 */
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500207void /* PRIVATE */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500208png_decompress_chunk(png_structp png_ptr, int comp_type,
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500209 png_size_t chunklength,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600210 png_size_t prefix_size, png_size_t *newlength)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600211{
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500212 static PNG_CONST char msg[] = "Error decoding compressed text";
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500213 png_charp text;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600214 png_size_t text_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600215
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600216 if (comp_type == PNG_COMPRESSION_TYPE_BASE)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600217 {
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500218 int ret = Z_OK;
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500219 png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600220 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
221 png_ptr->zstream.next_out = png_ptr->zbuf;
222 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
223
224 text_size = 0;
225 text = NULL;
226
227 while (png_ptr->zstream.avail_in)
228 {
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500229 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600230 if (ret != Z_OK && ret != Z_STREAM_END)
231 {
232 if (png_ptr->zstream.msg != NULL)
233 png_warning(png_ptr, png_ptr->zstream.msg);
234 else
235 png_warning(png_ptr, msg);
236 inflateReset(&png_ptr->zstream);
237 png_ptr->zstream.avail_in = 0;
238
239 if (text == NULL)
240 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500241 text_size = prefix_size + png_sizeof(msg) + 1;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500242 text = (png_charp)png_malloc_warn(png_ptr, text_size);
243 if (text == NULL)
244 {
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500245 png_free(png_ptr, png_ptr->chunkdata);
Glenn Randers-Pehrson72b63302008-07-22 13:59:07 -0500246 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500247 png_error(png_ptr, "Not enough memory to decompress chunk");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500248 }
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500249 png_memcpy(text, png_ptr->chunkdata, prefix_size);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600250 }
251
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500252 text[text_size - 1] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600253
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500254 /* Copy what we can of the error message into the text chunk */
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500255 text_size = (png_size_t)(chunklength -
256 (text - png_ptr->chunkdata) - 1);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500257 if (text_size > png_sizeof(msg))
258 text_size = png_sizeof(msg);
259 png_memcpy(text + prefix_size, msg, text_size);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600260 break;
261 }
262 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
263 {
264 if (text == NULL)
265 {
266 text_size = prefix_size +
267 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500268 text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
269 if (text == NULL)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500270 {
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500271 png_free(png_ptr, png_ptr->chunkdata);
Glenn Randers-Pehrson72b63302008-07-22 13:59:07 -0500272 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500273 png_error(png_ptr,
274 "Not enough memory to decompress chunk");
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500275 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500276 png_memcpy(text + prefix_size, png_ptr->zbuf,
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500277 text_size - prefix_size);
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500278 png_memcpy(text, png_ptr->chunkdata, prefix_size);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500279 *(text + text_size) = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600280 }
281 else
282 {
283 png_charp tmp;
284
285 tmp = text;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500286 text = (png_charp)png_malloc_warn(png_ptr,
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500287 (png_size_t)(text_size +
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600288 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500289 if (text == NULL)
290 {
291 png_free(png_ptr, tmp);
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500292 png_free(png_ptr, png_ptr->chunkdata);
Glenn Randers-Pehrson72b63302008-07-22 13:59:07 -0500293 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500294 png_error(png_ptr,
295 "Not enough memory to decompress chunk");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500296 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600297 png_memcpy(text, tmp, text_size);
298 png_free(png_ptr, tmp);
299 png_memcpy(text + text_size, png_ptr->zbuf,
300 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
301 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
302 *(text + text_size) = 0x00;
303 }
304 if (ret == Z_STREAM_END)
305 break;
306 else
307 {
308 png_ptr->zstream.next_out = png_ptr->zbuf;
309 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
310 }
311 }
312 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500313 if (ret != Z_STREAM_END)
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500314 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500315#if !defined(PNG_NO_STDIO)
Glenn Randers-Pehrsonf46918d2006-06-02 05:31:20 -0500316 char umsg[52];
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500317
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500318 if (ret == Z_BUF_ERROR)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500319 png_snprintf(umsg, 52,
320 "Buffer error in compressed datastream in %s chunk",
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500321 png_ptr->chunk_name);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500322
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500323 else if (ret == Z_DATA_ERROR)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500324 png_snprintf(umsg, 52,
325 "Data error in compressed datastream in %s chunk",
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500326 png_ptr->chunk_name);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500327
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500328 else
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500329 png_snprintf(umsg, 52,
330 "Incomplete compressed datastream in %s chunk",
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500331 png_ptr->chunk_name);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500332
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500333 png_warning(png_ptr, umsg);
334#else
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500335 png_warning(png_ptr,
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500336 "Incomplete compressed datastream in chunk other than IDAT");
337#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500338 text_size = prefix_size;
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -0600339 if (text == NULL)
340 {
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500341 text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
342 if (text == NULL)
343 {
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500344 png_free(png_ptr, png_ptr->chunkdata);
Glenn Randers-Pehrson72b63302008-07-22 13:59:07 -0500345 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500346 png_error(png_ptr, "Not enough memory for text");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500347 }
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500348 png_memcpy(text, png_ptr->chunkdata, prefix_size);
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -0600349 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500350 *(text + text_size) = 0x00;
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500351 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600352
353 inflateReset(&png_ptr->zstream);
354 png_ptr->zstream.avail_in = 0;
355
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500356 png_free(png_ptr, png_ptr->chunkdata);
357 png_ptr->chunkdata = text;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600358 *newlength=text_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600359 }
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600360 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600361 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500362#if !defined(PNG_NO_STDIO)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600363 char umsg[50];
364
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500365 png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600366 png_warning(png_ptr, umsg);
367#else
368 png_warning(png_ptr, "Unknown zTXt compression type");
369#endif
370
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500371 *(png_ptr->chunkdata + prefix_size) = 0x00;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500372 *newlength = prefix_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600373 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600374}
375#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600376
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500377/* Read and check the IDHR chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500378void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600379png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500380{
381 png_byte buf[13];
382 png_uint_32 width, height;
383 int bit_depth, color_type, compression_type, filter_type;
384 int interlace_type;
385
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500386 png_debug(1, "in png_handle_IHDR");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500387
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600388 if (png_ptr->mode & PNG_HAVE_IHDR)
Guy Schalnate5a37791996-06-05 15:50:50 -0500389 png_error(png_ptr, "Out of place IHDR");
390
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500391 /* Check the length */
Guy Schalnat0d580581995-07-20 02:43:20 -0500392 if (length != 13)
Guy Schalnat6d764711995-12-19 03:22:19 -0600393 png_error(png_ptr, "Invalid IHDR chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -0500394
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600395 png_ptr->mode |= PNG_HAVE_IHDR;
396
Guy Schalnat0d580581995-07-20 02:43:20 -0500397 png_crc_read(png_ptr, buf, 13);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600398 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500399
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500400 width = png_get_uint_31(png_ptr, buf);
401 height = png_get_uint_31(png_ptr, buf + 4);
Guy Schalnat0d580581995-07-20 02:43:20 -0500402 bit_depth = buf[8];
403 color_type = buf[9];
404 compression_type = buf[10];
405 filter_type = buf[11];
406 interlace_type = buf[12];
407
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500408 /* Set internal variables */
Guy Schalnat0d580581995-07-20 02:43:20 -0500409 png_ptr->width = width;
410 png_ptr->height = height;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600411 png_ptr->bit_depth = (png_byte)bit_depth;
412 png_ptr->interlaced = (png_byte)interlace_type;
413 png_ptr->color_type = (png_byte)color_type;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500414#if defined(PNG_MNG_FEATURES_SUPPORTED)
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -0600415 png_ptr->filter_type = (png_byte)filter_type;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500416#endif
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500417 png_ptr->compression_type = (png_byte)compression_type;
Guy Schalnat0d580581995-07-20 02:43:20 -0500418
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500419 /* Find number of channels */
Guy Schalnat0d580581995-07-20 02:43:20 -0500420 switch (png_ptr->color_type)
421 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500422 case PNG_COLOR_TYPE_GRAY:
423 case PNG_COLOR_TYPE_PALETTE:
Guy Schalnat0d580581995-07-20 02:43:20 -0500424 png_ptr->channels = 1;
425 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500426
Andreas Dilger47a0c421997-05-16 02:46:07 -0500427 case PNG_COLOR_TYPE_RGB:
Guy Schalnat0d580581995-07-20 02:43:20 -0500428 png_ptr->channels = 3;
429 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500430
Andreas Dilger47a0c421997-05-16 02:46:07 -0500431 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500432 png_ptr->channels = 2;
433 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500434
Andreas Dilger47a0c421997-05-16 02:46:07 -0500435 case PNG_COLOR_TYPE_RGB_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500436 png_ptr->channels = 4;
437 break;
438 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600439
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500440 /* Set up other useful info */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600441 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600442 png_ptr->channels);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500443 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500444 png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
445 png_debug1(3, "channels = %d", png_ptr->channels);
446 png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500447 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
448 color_type, interlace_type, compression_type, filter_type);
Guy Schalnat0d580581995-07-20 02:43:20 -0500449}
450
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500451/* Read and check the palette */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500452void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600453png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500454{
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600455 png_color palette[PNG_MAX_PALETTE_LENGTH];
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600456 int num, i;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500457#ifndef PNG_NO_POINTER_INDEXING
458 png_colorp pal_ptr;
459#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500460
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500461 png_debug(1, "in png_handle_PLTE");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500462
Guy Schalnate5a37791996-06-05 15:50:50 -0500463 if (!(png_ptr->mode & PNG_HAVE_IHDR))
464 png_error(png_ptr, "Missing IHDR before PLTE");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500465
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600466 else if (png_ptr->mode & PNG_HAVE_IDAT)
467 {
468 png_warning(png_ptr, "Invalid PLTE after IDAT");
469 png_crc_finish(png_ptr, length);
470 return;
471 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500472
Guy Schalnate5a37791996-06-05 15:50:50 -0500473 else if (png_ptr->mode & PNG_HAVE_PLTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600474 png_error(png_ptr, "Duplicate PLTE chunk");
475
476 png_ptr->mode |= PNG_HAVE_PLTE;
Guy Schalnate5a37791996-06-05 15:50:50 -0500477
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500478 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
479 {
480 png_warning(png_ptr,
481 "Ignoring PLTE chunk in grayscale PNG");
482 png_crc_finish(png_ptr, length);
483 return;
484 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500485#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
486 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
487 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600488 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500489 return;
490 }
491#endif
492
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600493 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
Guy Schalnate5a37791996-06-05 15:50:50 -0500494 {
495 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
496 {
497 png_warning(png_ptr, "Invalid palette chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600498 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500499 return;
500 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500501
Guy Schalnate5a37791996-06-05 15:50:50 -0500502 else
503 {
504 png_error(png_ptr, "Invalid palette chunk");
505 }
506 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500507
508 num = (int)length / 3;
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500509
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500510#ifndef PNG_NO_POINTER_INDEXING
511 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
512 {
513 png_byte buf[3];
514
515 png_crc_read(png_ptr, buf, 3);
516 pal_ptr->red = buf[0];
517 pal_ptr->green = buf[1];
518 pal_ptr->blue = buf[2];
519 }
520#else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600521 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500522 {
523 png_byte buf[3];
524
525 png_crc_read(png_ptr, buf, 3);
526 /* don't depend upon png_color being any order */
527 palette[i].red = buf[0];
528 palette[i].green = buf[1];
529 palette[i].blue = buf[2];
530 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500531#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600532
533 /* 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 -0500534 * whatever the normal CRC configuration tells us. However, if we
535 * have an RGB image, the PLTE can be considered ancillary, so
536 * we will act as though it is.
537 */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600538#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600539 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600540#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600541 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500542 png_crc_finish(png_ptr, 0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600543 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600544#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600545 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
546 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600547 /* If we don't want to use the data from an ancillary chunk,
548 we have two options: an error abort, or a warning and we
549 ignore the data in this chunk (which should be OK, since
550 it's considered ancillary for a RGB or RGBA image). */
551 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
552 {
553 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
554 {
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500555 png_chunk_benign_error(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600556 }
557 else
558 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600559 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600560 return;
561 }
562 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500563 /* Otherwise, we (optionally) emit a warning and use the chunk. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600564 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
565 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600566 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600567 }
568 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600569#endif
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500570
Andreas Dilger47a0c421997-05-16 02:46:07 -0500571 png_set_PLTE(png_ptr, info_ptr, palette, num);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500572
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500573#if defined(PNG_READ_tRNS_SUPPORTED)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500574 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
575 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600576 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500577 {
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500578 if (png_ptr->num_trans > (png_uint_16)num)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500579 {
580 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500581 png_ptr->num_trans = (png_uint_16)num;
582 }
583 if (info_ptr->num_trans > (png_uint_16)num)
584 {
585 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
586 info_ptr->num_trans = (png_uint_16)num;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500587 }
588 }
589 }
590#endif
591
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600592}
Guy Schalnate5a37791996-06-05 15:50:50 -0500593
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500594void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600595png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
596{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500597 png_debug(1, "in png_handle_IEND");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500598
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600599 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
600 {
601 png_error(png_ptr, "No image in file");
602 }
603
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600604 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600605
606 if (length != 0)
607 {
608 png_warning(png_ptr, "Incorrect IEND chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600609 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500610 png_crc_finish(png_ptr, length);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500611
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500612 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
Guy Schalnat0d580581995-07-20 02:43:20 -0500613}
614
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500615#if defined(PNG_READ_gAMA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500616void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600617png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500618{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600619 png_fixed_point igamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600620#ifdef PNG_FLOATING_POINT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500621 float file_gamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600622#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500623 png_byte buf[4];
624
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500625 png_debug(1, "in png_handle_gAMA");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500626
Guy Schalnate5a37791996-06-05 15:50:50 -0500627 if (!(png_ptr->mode & PNG_HAVE_IHDR))
628 png_error(png_ptr, "Missing IHDR before gAMA");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600629 else if (png_ptr->mode & PNG_HAVE_IDAT)
630 {
631 png_warning(png_ptr, "Invalid gAMA after IDAT");
632 png_crc_finish(png_ptr, length);
633 return;
634 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500635 else if (png_ptr->mode & PNG_HAVE_PLTE)
636 /* Should be an error, but we can cope with it */
637 png_warning(png_ptr, "Out of place gAMA chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600638
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500639 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600640#if defined(PNG_READ_sRGB_SUPPORTED)
641 && !(info_ptr->valid & PNG_INFO_sRGB)
642#endif
643 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600644 {
645 png_warning(png_ptr, "Duplicate gAMA chunk");
646 png_crc_finish(png_ptr, length);
647 return;
648 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500649
Guy Schalnat0d580581995-07-20 02:43:20 -0500650 if (length != 4)
651 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600652 png_warning(png_ptr, "Incorrect gAMA chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600653 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500654 return;
655 }
656
657 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600658 if (png_crc_finish(png_ptr, 0))
659 return;
660
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600661 igamma = (png_fixed_point)png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500662 /* check for zero gamma */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500663 if (igamma == 0)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500664 {
665 png_warning(png_ptr,
666 "Ignoring gAMA chunk with gamma=0");
667 return;
668 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500669
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600670#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600671 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500672 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600673 {
674 png_warning(png_ptr,
675 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500676#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson79134c62009-02-14 10:32:18 -0600677 fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600678#endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600679 return;
680 }
681#endif /* PNG_READ_sRGB_SUPPORTED */
682
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600683#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600684 file_gamma = (float)igamma / (float)100000.0;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600685# ifdef PNG_READ_GAMMA_SUPPORTED
686 png_ptr->gamma = file_gamma;
687# endif
688 png_set_gAMA(png_ptr, info_ptr, file_gamma);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600689#endif
690#ifdef PNG_FIXED_POINT_SUPPORTED
691 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
692#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500693}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500694#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500695
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500696#if defined(PNG_READ_sBIT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500697void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600698png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500699{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500700 png_size_t truelen;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600701 png_byte buf[4];
Guy Schalnat69b14481996-01-10 02:56:49 -0600702
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500703 png_debug(1, "in png_handle_sBIT");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500704
Guy Schalnat69b14481996-01-10 02:56:49 -0600705 buf[0] = buf[1] = buf[2] = buf[3] = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500706
Guy Schalnate5a37791996-06-05 15:50:50 -0500707 if (!(png_ptr->mode & PNG_HAVE_IHDR))
708 png_error(png_ptr, "Missing IHDR before sBIT");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600709 else if (png_ptr->mode & PNG_HAVE_IDAT)
710 {
711 png_warning(png_ptr, "Invalid sBIT after IDAT");
712 png_crc_finish(png_ptr, length);
713 return;
714 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500715 else if (png_ptr->mode & PNG_HAVE_PLTE)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600716 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500717 /* Should be an error, but we can cope with it */
718 png_warning(png_ptr, "Out of place sBIT chunk");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600719 }
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500720 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600721 {
722 png_warning(png_ptr, "Duplicate sBIT chunk");
723 png_crc_finish(png_ptr, length);
724 return;
725 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500726
Guy Schalnat0d580581995-07-20 02:43:20 -0500727 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600728 truelen = 3;
Guy Schalnat0d580581995-07-20 02:43:20 -0500729 else
Andreas Dilger47a0c421997-05-16 02:46:07 -0500730 truelen = (png_size_t)png_ptr->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500731
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500732 if (length != truelen || length > 4)
Guy Schalnat0d580581995-07-20 02:43:20 -0500733 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600734 png_warning(png_ptr, "Incorrect sBIT chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600735 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600736 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500737 }
738
Andreas Dilger47a0c421997-05-16 02:46:07 -0500739 png_crc_read(png_ptr, buf, truelen);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600740 if (png_crc_finish(png_ptr, 0))
741 return;
742
Guy Schalnat0d580581995-07-20 02:43:20 -0500743 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
744 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600745 png_ptr->sig_bit.red = buf[0];
746 png_ptr->sig_bit.green = buf[1];
747 png_ptr->sig_bit.blue = buf[2];
748 png_ptr->sig_bit.alpha = buf[3];
Guy Schalnat0d580581995-07-20 02:43:20 -0500749 }
750 else
751 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600752 png_ptr->sig_bit.gray = buf[0];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600753 png_ptr->sig_bit.red = buf[0];
754 png_ptr->sig_bit.green = buf[0];
755 png_ptr->sig_bit.blue = buf[0];
Guy Schalnat6d764711995-12-19 03:22:19 -0600756 png_ptr->sig_bit.alpha = buf[1];
Guy Schalnat0d580581995-07-20 02:43:20 -0500757 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500758 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
Guy Schalnat0d580581995-07-20 02:43:20 -0500759}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500760#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500761
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500762#if defined(PNG_READ_cHRM_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500763void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600764png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500765{
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500766 png_byte buf[32];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600767#ifdef PNG_FLOATING_POINT_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -0500768 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 -0600769#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600770 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600771 int_y_green, int_x_blue, int_y_blue;
Guy Schalnat0d580581995-07-20 02:43:20 -0500772
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600773 png_uint_32 uint_x, uint_y;
774
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500775 png_debug(1, "in png_handle_cHRM");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500776
Guy Schalnate5a37791996-06-05 15:50:50 -0500777 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600778 png_error(png_ptr, "Missing IHDR before cHRM");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600779 else if (png_ptr->mode & PNG_HAVE_IDAT)
780 {
781 png_warning(png_ptr, "Invalid cHRM after IDAT");
782 png_crc_finish(png_ptr, length);
783 return;
784 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500785 else if (png_ptr->mode & PNG_HAVE_PLTE)
786 /* Should be an error, but we can cope with it */
787 png_warning(png_ptr, "Missing PLTE before cHRM");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600788
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500789 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600790#if defined(PNG_READ_sRGB_SUPPORTED)
791 && !(info_ptr->valid & PNG_INFO_sRGB)
792#endif
793 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600794 {
795 png_warning(png_ptr, "Duplicate cHRM chunk");
796 png_crc_finish(png_ptr, length);
797 return;
798 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500799
Guy Schalnat0d580581995-07-20 02:43:20 -0500800 if (length != 32)
801 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600802 png_warning(png_ptr, "Incorrect cHRM chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600803 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600804 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500805 }
806
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500807 png_crc_read(png_ptr, buf, 32);
808 if (png_crc_finish(png_ptr, 0))
809 return;
810
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600811 uint_x = png_get_uint_32(buf);
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500812 uint_y = png_get_uint_32(buf + 4);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600813 int_x_white = (png_fixed_point)uint_x;
814 int_y_white = (png_fixed_point)uint_y;
Guy Schalnat0d580581995-07-20 02:43:20 -0500815
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500816 uint_x = png_get_uint_32(buf + 8);
817 uint_y = png_get_uint_32(buf + 12);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600818 int_x_red = (png_fixed_point)uint_x;
819 int_y_red = (png_fixed_point)uint_y;
Guy Schalnat0d580581995-07-20 02:43:20 -0500820
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500821 uint_x = png_get_uint_32(buf + 16);
822 uint_y = png_get_uint_32(buf + 20);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600823 int_x_green = (png_fixed_point)uint_x;
824 int_y_green = (png_fixed_point)uint_y;
Guy Schalnat0d580581995-07-20 02:43:20 -0500825
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500826 uint_x = png_get_uint_32(buf + 24);
827 uint_y = png_get_uint_32(buf + 28);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600828 int_x_blue = (png_fixed_point)uint_x;
829 int_y_blue = (png_fixed_point)uint_y;
830
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600831#ifdef PNG_FLOATING_POINT_SUPPORTED
832 white_x = (float)int_x_white / (float)100000.0;
833 white_y = (float)int_y_white / (float)100000.0;
834 red_x = (float)int_x_red / (float)100000.0;
835 red_y = (float)int_y_red / (float)100000.0;
836 green_x = (float)int_x_green / (float)100000.0;
837 green_y = (float)int_y_green / (float)100000.0;
838 blue_x = (float)int_x_blue / (float)100000.0;
839 blue_y = (float)int_y_blue / (float)100000.0;
840#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600841
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600842#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500843 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600844 {
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500845 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
846 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
847 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
848 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
849 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
850 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
851 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
852 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600853 {
854 png_warning(png_ptr,
855 "Ignoring incorrect cHRM value when sRGB is also present");
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500856#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600857#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500858 fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600859 white_x, white_y, red_x, red_y);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500860 fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600861 green_x, green_y, blue_x, blue_y);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600862#else
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500863 fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600864 int_x_white, int_y_white, int_x_red, int_y_red);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500865 fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600866 int_x_green, int_y_green, int_x_blue, int_y_blue);
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600867#endif
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500868#endif /* PNG_NO_CONSOLE_IO */
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600869 }
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600870 return;
871 }
872#endif /* PNG_READ_sRGB_SUPPORTED */
873
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600874#ifdef PNG_FLOATING_POINT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500875 png_set_cHRM(png_ptr, info_ptr,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600876 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600877#endif
878#ifdef PNG_FIXED_POINT_SUPPORTED
879 png_set_cHRM_fixed(png_ptr, info_ptr,
880 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
881 int_y_green, int_x_blue, int_y_blue);
882#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500883}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500884#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500885
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600886#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500887void /* PRIVATE */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600888png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
889{
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600890 int intent;
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600891 png_byte buf[1];
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600892
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500893 png_debug(1, "in png_handle_sRGB");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600894
895 if (!(png_ptr->mode & PNG_HAVE_IHDR))
896 png_error(png_ptr, "Missing IHDR before sRGB");
897 else if (png_ptr->mode & PNG_HAVE_IDAT)
898 {
899 png_warning(png_ptr, "Invalid sRGB after IDAT");
900 png_crc_finish(png_ptr, length);
901 return;
902 }
903 else if (png_ptr->mode & PNG_HAVE_PLTE)
904 /* Should be an error, but we can cope with it */
905 png_warning(png_ptr, "Out of place sRGB chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600906
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500907 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600908 {
909 png_warning(png_ptr, "Duplicate sRGB chunk");
910 png_crc_finish(png_ptr, length);
911 return;
912 }
913
914 if (length != 1)
915 {
916 png_warning(png_ptr, "Incorrect sRGB chunk length");
917 png_crc_finish(png_ptr, length);
918 return;
919 }
920
921 png_crc_read(png_ptr, buf, 1);
922 if (png_crc_finish(png_ptr, 0))
923 return;
924
925 intent = buf[0];
926 /* check for bad intent */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600927 if (intent >= PNG_sRGB_INTENT_LAST)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600928 {
929 png_warning(png_ptr, "Unknown sRGB intent");
930 return;
931 }
932
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600933#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600934 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600935 {
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500936 png_fixed_point igamma;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600937#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500938 igamma=info_ptr->int_gamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600939#else
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600940# ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500941 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600942# endif
943#endif
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500944 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600945 {
946 png_warning(png_ptr,
947 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500948#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600949# ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500950 fprintf(stderr, "incorrect gamma=(%d/100000)\n",
951 (int)png_ptr->int_gamma);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600952# else
953# ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500954 fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600955# endif
956# endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600957#endif
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600958 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600959 }
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600960#endif /* PNG_READ_gAMA_SUPPORTED */
961
962#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500963#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600964 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500965 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
966 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
967 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
968 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
969 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
970 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
971 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
972 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600973 {
974 png_warning(png_ptr,
975 "Ignoring incorrect cHRM value when sRGB is also present");
976 }
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500977#endif /* PNG_FIXED_POINT_SUPPORTED */
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600978#endif /* PNG_READ_cHRM_SUPPORTED */
979
980 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
981}
982#endif /* PNG_READ_sRGB_SUPPORTED */
983
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600984#if defined(PNG_READ_iCCP_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500985void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600986png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
987/* Note: this does not properly handle chunks that are > 64K under DOS */
988{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600989 png_byte compression_type;
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600990 png_bytep pC;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600991 png_charp profile;
992 png_uint_32 skip = 0;
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500993 png_uint_32 profile_size, profile_length;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600994 png_size_t slength, prefix_length, data_length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600995
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500996 png_debug(1, "in png_handle_iCCP");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600997
998 if (!(png_ptr->mode & PNG_HAVE_IHDR))
999 png_error(png_ptr, "Missing IHDR before iCCP");
1000 else if (png_ptr->mode & PNG_HAVE_IDAT)
1001 {
1002 png_warning(png_ptr, "Invalid iCCP after IDAT");
1003 png_crc_finish(png_ptr, length);
1004 return;
1005 }
1006 else if (png_ptr->mode & PNG_HAVE_PLTE)
1007 /* Should be an error, but we can cope with it */
1008 png_warning(png_ptr, "Out of place iCCP chunk");
1009
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001010 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001011 {
1012 png_warning(png_ptr, "Duplicate iCCP chunk");
1013 png_crc_finish(png_ptr, length);
1014 return;
1015 }
1016
1017#ifdef PNG_MAX_MALLOC_64K
1018 if (length > (png_uint_32)65535L)
1019 {
1020 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1021 skip = length - (png_uint_32)65535L;
1022 length = (png_uint_32)65535L;
1023 }
1024#endif
1025
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001026 png_free(png_ptr, png_ptr->chunkdata);
1027 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001028 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001029 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001030
1031 if (png_crc_finish(png_ptr, skip))
1032 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001033 png_free(png_ptr, png_ptr->chunkdata);
1034 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001035 return;
1036 }
1037
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001038 png_ptr->chunkdata[slength] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001039
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001040 for (profile = png_ptr->chunkdata; *profile; profile++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001041 /* empty loop to find end of name */ ;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001042
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001043 ++profile;
1044
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001045 /* there should be at least one zero (the compression type byte)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001046 following the separator, and we should be on it */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001047 if ( profile >= png_ptr->chunkdata + slength - 1)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001048 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001049 png_free(png_ptr, png_ptr->chunkdata);
1050 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001051 png_warning(png_ptr, "Malformed iCCP chunk");
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001052 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001053 }
1054
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001055 /* compression_type should always be zero */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001056 compression_type = *profile++;
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001057 if (compression_type)
1058 {
1059 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001060 compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001061 wrote nonzero) */
1062 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001063
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001064 prefix_length = profile - png_ptr->chunkdata;
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -05001065 png_decompress_chunk(png_ptr, compression_type,
1066 slength, prefix_length, &data_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001067
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001068 profile_length = data_length - prefix_length;
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06001069
Glenn Randers-Pehrsondb3b88d2001-12-04 06:30:43 -06001070 if ( prefix_length > data_length || profile_length < 4)
Glenn Randers-Pehrsonb1828932001-06-23 08:03:17 -05001071 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001072 png_free(png_ptr, png_ptr->chunkdata);
1073 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrsonb1828932001-06-23 08:03:17 -05001074 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1075 return;
1076 }
1077
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06001078 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001079 pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
Glenn Randers-Pehrson72b63302008-07-22 13:59:07 -05001080 profile_size = ((*(pC ))<<24) |
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001081 ((*(pC + 1))<<16) |
1082 ((*(pC + 2))<< 8) |
1083 ((*(pC + 3)) );
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001084
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001085 if (profile_size < profile_length)
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001086 profile_length = profile_size;
1087
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001088 if (profile_size > profile_length)
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001089 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001090 png_free(png_ptr, png_ptr->chunkdata);
1091 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001092 png_warning(png_ptr, "Ignoring truncated iCCP profile");
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001093 return;
1094 }
1095
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001096 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
1097 compression_type, png_ptr->chunkdata + prefix_length, profile_length);
1098 png_free(png_ptr, png_ptr->chunkdata);
1099 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001100}
1101#endif /* PNG_READ_iCCP_SUPPORTED */
1102
1103#if defined(PNG_READ_sPLT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001104void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001105png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1106/* Note: this does not properly handle chunks that are > 64K under DOS */
1107{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001108 png_bytep entry_start;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001109 png_sPLT_t new_palette;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001110#ifdef PNG_NO_POINTER_INDEXING
1111 png_sPLT_entryp pp;
1112#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001113 int data_length, entry_size, i;
1114 png_uint_32 skip = 0;
1115 png_size_t slength;
1116
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001117 png_debug(1, "in png_handle_sPLT");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001118
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05001119#ifdef PNG_SET_USER_LIMITS_SUPPORTED
1120
1121 if (png_ptr->user_chunk_cache_max != 0)
1122 {
1123 if (png_ptr->user_chunk_cache_max == 1)
1124 {
1125 png_crc_finish(png_ptr, length);
1126 return;
1127 }
1128 if (--png_ptr->user_chunk_cache_max == 1)
1129 {
1130 png_warning(png_ptr, "No space in chunk cache for sPLT");
1131 png_crc_finish(png_ptr, length);
1132 return;
1133 }
1134 }
1135#endif
1136
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001137 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1138 png_error(png_ptr, "Missing IHDR before sPLT");
1139 else if (png_ptr->mode & PNG_HAVE_IDAT)
1140 {
1141 png_warning(png_ptr, "Invalid sPLT after IDAT");
1142 png_crc_finish(png_ptr, length);
1143 return;
1144 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001145
1146#ifdef PNG_MAX_MALLOC_64K
1147 if (length > (png_uint_32)65535L)
1148 {
1149 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1150 skip = length - (png_uint_32)65535L;
1151 length = (png_uint_32)65535L;
1152 }
1153#endif
1154
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001155 png_free(png_ptr, png_ptr->chunkdata);
1156 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001157 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001158 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001159
1160 if (png_crc_finish(png_ptr, skip))
1161 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001162 png_free(png_ptr, png_ptr->chunkdata);
1163 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001164 return;
1165 }
1166
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001167 png_ptr->chunkdata[slength] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001168
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001169 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; entry_start++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001170 /* empty loop to find end of name */ ;
1171 ++entry_start;
1172
1173 /* a sample depth should follow the separator, and we should be on it */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001174 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001175 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001176 png_free(png_ptr, png_ptr->chunkdata);
1177 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001178 png_warning(png_ptr, "malformed sPLT chunk");
1179 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001180 }
1181
1182 new_palette.depth = *entry_start++;
1183 entry_size = (new_palette.depth == 8 ? 6 : 10);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001184 data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001185
1186 /* integrity-check the data length */
1187 if (data_length % entry_size)
1188 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001189 png_free(png_ptr, png_ptr->chunkdata);
1190 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001191 png_warning(png_ptr, "sPLT chunk has bad length");
1192 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001193 }
1194
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06001195 new_palette.nentries = (png_int_32) ( data_length / entry_size);
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001196 if ((png_uint_32) new_palette.nentries >
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001197 (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001198 {
1199 png_warning(png_ptr, "sPLT chunk too long");
1200 return;
1201 }
1202 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001203 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001204 if (new_palette.entries == NULL)
1205 {
1206 png_warning(png_ptr, "sPLT chunk requires too much memory");
1207 return;
1208 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001209
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001210#ifndef PNG_NO_POINTER_INDEXING
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001211 for (i = 0; i < new_palette.nentries; i++)
1212 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001213 png_sPLT_entryp pp = new_palette.entries + i;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001214
1215 if (new_palette.depth == 8)
1216 {
1217 pp->red = *entry_start++;
1218 pp->green = *entry_start++;
1219 pp->blue = *entry_start++;
1220 pp->alpha = *entry_start++;
1221 }
1222 else
1223 {
1224 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1225 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1226 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1227 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1228 }
1229 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1230 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001231#else
1232 pp = new_palette.entries;
1233 for (i = 0; i < new_palette.nentries; i++)
1234 {
1235
1236 if (new_palette.depth == 8)
1237 {
1238 pp[i].red = *entry_start++;
1239 pp[i].green = *entry_start++;
1240 pp[i].blue = *entry_start++;
1241 pp[i].alpha = *entry_start++;
1242 }
1243 else
1244 {
1245 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1246 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1247 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1248 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1249 }
1250 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1251 }
1252#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001253
1254 /* discard all chunk data except the name and stash that */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001255 new_palette.name = png_ptr->chunkdata;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001256
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001257 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001258
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001259 png_free(png_ptr, png_ptr->chunkdata);
1260 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001261 png_free(png_ptr, new_palette.entries);
1262}
1263#endif /* PNG_READ_sPLT_SUPPORTED */
1264
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001265#if defined(PNG_READ_tRNS_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001266void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001267png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001268{
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001269 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001270
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001271 png_debug(1, "in png_handle_tRNS");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001272
Guy Schalnate5a37791996-06-05 15:50:50 -05001273 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1274 png_error(png_ptr, "Missing IHDR before tRNS");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001275 else if (png_ptr->mode & PNG_HAVE_IDAT)
1276 {
1277 png_warning(png_ptr, "Invalid tRNS after IDAT");
1278 png_crc_finish(png_ptr, length);
1279 return;
1280 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001281 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001282 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001283 png_warning(png_ptr, "Duplicate tRNS chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001284 png_crc_finish(png_ptr, length);
1285 return;
1286 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001287
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001288 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001289 {
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001290 png_byte buf[2];
Guy Schalnat0d580581995-07-20 02:43:20 -05001291
1292 if (length != 2)
1293 {
Guy Schalnat69b14481996-01-10 02:56:49 -06001294 png_warning(png_ptr, "Incorrect tRNS chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001295 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001296 return;
1297 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001298
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001299 png_crc_read(png_ptr, buf, 2);
1300 png_ptr->num_trans = 1;
Glenn Randers-Pehrson56f63962008-10-06 10:16:17 -05001301 png_ptr->trans_color.gray = png_get_uint_16(buf);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001302 }
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001303 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1304 {
1305 png_byte buf[6];
1306
1307 if (length != 6)
1308 {
1309 png_warning(png_ptr, "Incorrect tRNS chunk length");
1310 png_crc_finish(png_ptr, length);
1311 return;
1312 }
1313 png_crc_read(png_ptr, buf, (png_size_t)length);
1314 png_ptr->num_trans = 1;
Glenn Randers-Pehrson56f63962008-10-06 10:16:17 -05001315 png_ptr->trans_color.red = png_get_uint_16(buf);
1316 png_ptr->trans_color.green = png_get_uint_16(buf + 2);
1317 png_ptr->trans_color.blue = png_get_uint_16(buf + 4);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001318 }
1319 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1320 {
1321 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1322 {
1323 /* Should be an error, but we can cope with it. */
1324 png_warning(png_ptr, "Missing PLTE before tRNS");
1325 }
1326 if (length > (png_uint_32)png_ptr->num_palette ||
1327 length > PNG_MAX_PALETTE_LENGTH)
1328 {
1329 png_warning(png_ptr, "Incorrect tRNS chunk length");
1330 png_crc_finish(png_ptr, length);
1331 return;
1332 }
1333 if (length == 0)
1334 {
1335 png_warning(png_ptr, "Zero length tRNS chunk");
1336 png_crc_finish(png_ptr, length);
1337 return;
1338 }
1339 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1340 png_ptr->num_trans = (png_uint_16)length;
1341 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001342 else
Guy Schalnate5a37791996-06-05 15:50:50 -05001343 {
1344 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001345 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001346 return;
1347 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001348
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001349 if (png_crc_finish(png_ptr, 0))
Glenn Randers-Pehrsona7dbcba2007-05-15 16:16:34 -05001350 {
1351 png_ptr->num_trans = 0;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001352 return;
Glenn Randers-Pehrsona7dbcba2007-05-15 16:16:34 -05001353 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001354
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001355 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
Glenn Randers-Pehrson56f63962008-10-06 10:16:17 -05001356 &(png_ptr->trans_color));
Guy Schalnat0d580581995-07-20 02:43:20 -05001357}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001358#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001359
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001360#if defined(PNG_READ_bKGD_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001361void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001362png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001363{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001364 png_size_t truelen;
Guy Schalnat0d580581995-07-20 02:43:20 -05001365 png_byte buf[6];
1366
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001367 png_debug(1, "in png_handle_bKGD");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001368
Guy Schalnate5a37791996-06-05 15:50:50 -05001369 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1370 png_error(png_ptr, "Missing IHDR before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001371 else if (png_ptr->mode & PNG_HAVE_IDAT)
1372 {
1373 png_warning(png_ptr, "Invalid bKGD after IDAT");
1374 png_crc_finish(png_ptr, length);
1375 return;
1376 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001377 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1378 !(png_ptr->mode & PNG_HAVE_PLTE))
1379 {
1380 png_warning(png_ptr, "Missing PLTE before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001381 png_crc_finish(png_ptr, length);
1382 return;
1383 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001384 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001385 {
1386 png_warning(png_ptr, "Duplicate bKGD chunk");
1387 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001388 return;
1389 }
1390
Guy Schalnat0d580581995-07-20 02:43:20 -05001391 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1392 truelen = 1;
1393 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1394 truelen = 6;
1395 else
1396 truelen = 2;
1397
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001398 if (length != truelen)
Guy Schalnat0d580581995-07-20 02:43:20 -05001399 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001400 png_warning(png_ptr, "Incorrect bKGD chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001401 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001402 return;
1403 }
1404
Andreas Dilger47a0c421997-05-16 02:46:07 -05001405 png_crc_read(png_ptr, buf, truelen);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001406 if (png_crc_finish(png_ptr, 0))
1407 return;
1408
Guy Schalnate5a37791996-06-05 15:50:50 -05001409 /* We convert the index value into RGB components so that we can allow
1410 * arbitrary RGB values for background when we have transparency, and
1411 * so it is easy to determine the RGB values of the background color
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001412 * from the info_ptr struct. */
Guy Schalnat0d580581995-07-20 02:43:20 -05001413 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnate5a37791996-06-05 15:50:50 -05001414 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001415 png_ptr->background.index = buf[0];
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001416 if (info_ptr && info_ptr->num_palette)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001417 {
Glenn Randers-Pehrson79134c62009-02-14 10:32:18 -06001418 if (buf[0] >= info_ptr->num_palette)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001419 {
1420 png_warning(png_ptr, "Incorrect bKGD chunk index value");
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001421 return;
1422 }
1423 png_ptr->background.red =
1424 (png_uint_16)png_ptr->palette[buf[0]].red;
1425 png_ptr->background.green =
1426 (png_uint_16)png_ptr->palette[buf[0]].green;
1427 png_ptr->background.blue =
1428 (png_uint_16)png_ptr->palette[buf[0]].blue;
1429 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001430 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001431 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
Guy Schalnate5a37791996-06-05 15:50:50 -05001432 {
1433 png_ptr->background.red =
1434 png_ptr->background.green =
1435 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -05001436 png_ptr->background.gray = png_get_uint_16(buf);
Guy Schalnate5a37791996-06-05 15:50:50 -05001437 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001438 else
1439 {
1440 png_ptr->background.red = png_get_uint_16(buf);
1441 png_ptr->background.green = png_get_uint_16(buf + 2);
1442 png_ptr->background.blue = png_get_uint_16(buf + 4);
1443 }
1444
Andreas Dilger47a0c421997-05-16 02:46:07 -05001445 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
Guy Schalnat0d580581995-07-20 02:43:20 -05001446}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001447#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001448
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001449#if defined(PNG_READ_hIST_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001450void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001451png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001452{
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001453 unsigned int num, i;
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001454 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
Guy Schalnat0d580581995-07-20 02:43:20 -05001455
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001456 png_debug(1, "in png_handle_hIST");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001457
Guy Schalnate5a37791996-06-05 15:50:50 -05001458 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1459 png_error(png_ptr, "Missing IHDR before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001460 else if (png_ptr->mode & PNG_HAVE_IDAT)
1461 {
1462 png_warning(png_ptr, "Invalid hIST after IDAT");
1463 png_crc_finish(png_ptr, length);
1464 return;
1465 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001466 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1467 {
1468 png_warning(png_ptr, "Missing PLTE before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001469 png_crc_finish(png_ptr, length);
1470 return;
1471 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001472 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001473 {
1474 png_warning(png_ptr, "Duplicate hIST chunk");
1475 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001476 return;
1477 }
1478
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001479 num = length / 2 ;
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001480 if (num != (unsigned int) png_ptr->num_palette || num >
1481 (unsigned int) PNG_MAX_PALETTE_LENGTH)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001482 {
1483 png_warning(png_ptr, "Incorrect hIST chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001484 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001485 return;
1486 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001487
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001488 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001489 {
1490 png_byte buf[2];
1491
1492 png_crc_read(png_ptr, buf, 2);
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001493 readbuf[i] = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001494 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001495
1496 if (png_crc_finish(png_ptr, 0))
1497 return;
1498
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001499 png_set_hIST(png_ptr, info_ptr, readbuf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001500}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001501#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001502
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001503#if defined(PNG_READ_pHYs_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001504void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001505png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001506{
1507 png_byte buf[9];
1508 png_uint_32 res_x, res_y;
1509 int unit_type;
1510
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001511 png_debug(1, "in png_handle_pHYs");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001512
Guy Schalnate5a37791996-06-05 15:50:50 -05001513 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001514 png_error(png_ptr, "Missing IHDR before pHYs");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001515 else if (png_ptr->mode & PNG_HAVE_IDAT)
1516 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001517 png_warning(png_ptr, "Invalid pHYs after IDAT");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001518 png_crc_finish(png_ptr, length);
1519 return;
1520 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001521 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001522 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001523 png_warning(png_ptr, "Duplicate pHYs chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001524 png_crc_finish(png_ptr, length);
1525 return;
1526 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001527
Guy Schalnat0d580581995-07-20 02:43:20 -05001528 if (length != 9)
1529 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001530 png_warning(png_ptr, "Incorrect pHYs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001531 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001532 return;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001533 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001534
1535 png_crc_read(png_ptr, buf, 9);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001536 if (png_crc_finish(png_ptr, 0))
1537 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001538
1539 res_x = png_get_uint_32(buf);
1540 res_y = png_get_uint_32(buf + 4);
1541 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001542 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
Guy Schalnat0d580581995-07-20 02:43:20 -05001543}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001544#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001545
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001546#if defined(PNG_READ_oFFs_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001547void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001548png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001549{
1550 png_byte buf[9];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001551 png_int_32 offset_x, offset_y;
Guy Schalnat0d580581995-07-20 02:43:20 -05001552 int unit_type;
1553
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001554 png_debug(1, "in png_handle_oFFs");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001555
Guy Schalnate5a37791996-06-05 15:50:50 -05001556 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1557 png_error(png_ptr, "Missing IHDR before oFFs");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001558 else if (png_ptr->mode & PNG_HAVE_IDAT)
1559 {
1560 png_warning(png_ptr, "Invalid oFFs after IDAT");
1561 png_crc_finish(png_ptr, length);
1562 return;
1563 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001564 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001565 {
1566 png_warning(png_ptr, "Duplicate oFFs chunk");
1567 png_crc_finish(png_ptr, length);
1568 return;
1569 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001570
Guy Schalnat0d580581995-07-20 02:43:20 -05001571 if (length != 9)
1572 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001573 png_warning(png_ptr, "Incorrect oFFs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001574 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001575 return;
1576 }
1577
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001578 png_crc_read(png_ptr, buf, 9);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001579 if (png_crc_finish(png_ptr, 0))
1580 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001581
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001582 offset_x = png_get_int_32(buf);
1583 offset_y = png_get_int_32(buf + 4);
Guy Schalnat0d580581995-07-20 02:43:20 -05001584 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001585 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1586}
1587#endif
1588
1589#if defined(PNG_READ_pCAL_SUPPORTED)
Glenn Randers-Pehrsonff9c9472000-07-11 07:12:36 -05001590/* read the pCAL chunk (described in the PNG Extensions document) */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001591void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001592png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1593{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001594 png_int_32 X0, X1;
1595 png_byte type, nparams;
1596 png_charp buf, units, endptr;
1597 png_charpp params;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001598 png_size_t slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001599 int i;
1600
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001601 png_debug(1, "in png_handle_pCAL");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001602
1603 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1604 png_error(png_ptr, "Missing IHDR before pCAL");
1605 else if (png_ptr->mode & PNG_HAVE_IDAT)
1606 {
1607 png_warning(png_ptr, "Invalid pCAL after IDAT");
1608 png_crc_finish(png_ptr, length);
1609 return;
1610 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001611 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
Andreas Dilger47a0c421997-05-16 02:46:07 -05001612 {
1613 png_warning(png_ptr, "Duplicate pCAL chunk");
1614 png_crc_finish(png_ptr, length);
1615 return;
1616 }
1617
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001618 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001619 length + 1);
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001620 png_free(png_ptr, png_ptr->chunkdata);
1621 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1622 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001623 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001624 png_warning(png_ptr, "No memory for pCAL purpose");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001625 return;
1626 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001627 slength = (png_size_t)length;
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001628 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001629
1630 if (png_crc_finish(png_ptr, 0))
1631 {
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001632 png_free(png_ptr, png_ptr->chunkdata);
1633 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001634 return;
1635 }
1636
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001637 png_ptr->chunkdata[slength] = 0x00; /* null terminate the last string */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001638
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001639 png_debug(3, "Finding end of pCAL purpose string");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001640 for (buf = png_ptr->chunkdata; *buf; buf++)
Glenn Randers-Pehrsond12aa501998-03-13 07:39:39 -06001641 /* empty loop */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001642
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001643 endptr = png_ptr->chunkdata + slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001644
1645 /* We need to have at least 12 bytes after the purpose string
1646 in order to get the parameter information. */
1647 if (endptr <= buf + 12)
1648 {
1649 png_warning(png_ptr, "Invalid pCAL data");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001650 png_free(png_ptr, png_ptr->chunkdata);
1651 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001652 return;
1653 }
1654
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001655 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001656 X0 = png_get_int_32((png_bytep)buf+1);
1657 X1 = png_get_int_32((png_bytep)buf+5);
1658 type = buf[9];
1659 nparams = buf[10];
1660 units = buf + 11;
1661
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001662 png_debug(3, "Checking pCAL equation type and number of parameters");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001663 /* Check that we have the right number of parameters for known
1664 equation types. */
1665 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1666 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1667 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1668 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1669 {
1670 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001671 png_free(png_ptr, png_ptr->chunkdata);
1672 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001673 return;
1674 }
1675 else if (type >= PNG_EQUATION_LAST)
1676 {
1677 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1678 }
1679
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001680 for (buf = units; *buf; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001681 /* Empty loop to move past the units string. */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001682
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001683 png_debug(3, "Allocating pCAL parameters array");
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001684 params = (png_charpp)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001685 (png_size_t)(nparams * png_sizeof(png_charp)));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001686 if (params == NULL)
1687 {
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001688 png_free(png_ptr, png_ptr->chunkdata);
1689 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001690 png_warning(png_ptr, "No memory for pCAL params");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001691 return;
1692 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001693
1694 /* Get pointers to the start of each parameter string. */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001695 for (i = 0; i < (int)nparams; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001696 {
1697 buf++; /* Skip the null string terminator from previous parameter. */
1698
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001699 png_debug1(3, "Reading pCAL parameter %d", i);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001700 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001701 /* Empty loop to move past each parameter string */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001702
1703 /* Make sure we haven't run out of data yet */
1704 if (buf > endptr)
1705 {
1706 png_warning(png_ptr, "Invalid pCAL data");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001707 png_free(png_ptr, png_ptr->chunkdata);
1708 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001709 png_free(png_ptr, params);
1710 return;
1711 }
1712 }
1713
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001714 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001715 units, params);
1716
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001717 png_free(png_ptr, png_ptr->chunkdata);
1718 png_ptr->chunkdata = NULL;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001719 png_free(png_ptr, params);
Guy Schalnat0d580581995-07-20 02:43:20 -05001720}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001721#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001722
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001723#if defined(PNG_READ_sCAL_SUPPORTED)
1724/* read the sCAL chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001725void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001726png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1727{
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001728 png_charp ep;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001729#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001730 double width, height;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001731 png_charp vp;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001732#else
1733#ifdef PNG_FIXED_POINT_SUPPORTED
1734 png_charp swidth, sheight;
1735#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001736#endif
1737 png_size_t slength;
1738
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001739 png_debug(1, "in png_handle_sCAL");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001740
1741 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1742 png_error(png_ptr, "Missing IHDR before sCAL");
1743 else if (png_ptr->mode & PNG_HAVE_IDAT)
1744 {
1745 png_warning(png_ptr, "Invalid sCAL after IDAT");
1746 png_crc_finish(png_ptr, length);
1747 return;
1748 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001749 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001750 {
1751 png_warning(png_ptr, "Duplicate sCAL chunk");
1752 png_crc_finish(png_ptr, length);
1753 return;
1754 }
1755
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001756 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001757 length + 1);
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001758 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1759 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001760 {
1761 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
1762 return;
1763 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001764 slength = (png_size_t)length;
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001765 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001766
1767 if (png_crc_finish(png_ptr, 0))
1768 {
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001769 png_free(png_ptr, png_ptr->chunkdata);
1770 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001771 return;
1772 }
1773
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001774 png_ptr->chunkdata[slength] = 0x00; /* null terminate the last string */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001775
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001776 ep = png_ptr->chunkdata + 1; /* skip unit byte */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001777
1778#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001779 width = png_strtod(png_ptr, ep, &vp);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001780 if (*vp)
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001781 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001782 png_warning(png_ptr, "malformed width string in sCAL chunk");
1783 return;
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001784 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001785#else
1786#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001787 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1788 if (swidth == NULL)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001789 {
1790 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
1791 return;
1792 }
1793 png_memcpy(swidth, ep, png_strlen(ep));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001794#endif
1795#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001796
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001797 for (ep = png_ptr->chunkdata; *ep; ep++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001798 /* empty loop */ ;
1799 ep++;
1800
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001801 if (png_ptr->chunkdata + slength < ep)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001802 {
1803 png_warning(png_ptr, "Truncated sCAL chunk");
1804#if defined(PNG_FIXED_POINT_SUPPORTED) && \
1805 !defined(PNG_FLOATING_POINT_SUPPORTED)
1806 png_free(png_ptr, swidth);
1807#endif
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001808 png_free(png_ptr, png_ptr->chunkdata);
1809 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001810 return;
1811 }
1812
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001813#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001814 height = png_strtod(png_ptr, ep, &vp);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001815 if (*vp)
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001816 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001817 png_warning(png_ptr, "malformed height string in sCAL chunk");
1818 return;
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001819 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001820#else
1821#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001822 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001823 if (sheight == NULL)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001824 {
1825 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
1826 return;
1827 }
1828 png_memcpy(sheight, ep, png_strlen(ep));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001829#endif
1830#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001831
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001832 if (png_ptr->chunkdata + slength < ep
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001833#ifdef PNG_FLOATING_POINT_SUPPORTED
1834 || width <= 0. || height <= 0.
1835#endif
1836 )
1837 {
1838 png_warning(png_ptr, "Invalid sCAL data");
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001839 png_free(png_ptr, png_ptr->chunkdata);
1840 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001841#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001842 png_free(png_ptr, swidth);
1843 png_free(png_ptr, sheight);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001844#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001845 return;
1846 }
1847
1848
1849#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001850 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001851#else
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001852#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001853 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001854#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001855#endif
1856
Glenn Randers-Pehrsond8d7b942008-07-21 10:34:34 -05001857 png_free(png_ptr, png_ptr->chunkdata);
1858 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001859#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1860 png_free(png_ptr, swidth);
1861 png_free(png_ptr, sheight);
1862#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001863}
1864#endif
1865
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001866#if defined(PNG_READ_tIME_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001867void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001868png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001869{
1870 png_byte buf[7];
1871 png_time mod_time;
1872
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001873 png_debug(1, "in png_handle_tIME");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001874
Guy Schalnate5a37791996-06-05 15:50:50 -05001875 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001876 png_error(png_ptr, "Out of place tIME chunk");
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001877 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001878 {
1879 png_warning(png_ptr, "Duplicate tIME chunk");
1880 png_crc_finish(png_ptr, length);
1881 return;
1882 }
1883
1884 if (png_ptr->mode & PNG_HAVE_IDAT)
1885 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnate5a37791996-06-05 15:50:50 -05001886
Guy Schalnat0d580581995-07-20 02:43:20 -05001887 if (length != 7)
1888 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001889 png_warning(png_ptr, "Incorrect tIME chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001890 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001891 return;
1892 }
1893
1894 png_crc_read(png_ptr, buf, 7);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001895 if (png_crc_finish(png_ptr, 0))
1896 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001897
1898 mod_time.second = buf[6];
1899 mod_time.minute = buf[5];
1900 mod_time.hour = buf[4];
1901 mod_time.day = buf[3];
1902 mod_time.month = buf[2];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001903 mod_time.year = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001904
Andreas Dilger47a0c421997-05-16 02:46:07 -05001905 png_set_tIME(png_ptr, info_ptr, &mod_time);
Guy Schalnat0d580581995-07-20 02:43:20 -05001906}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001907#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001908
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001909#if defined(PNG_READ_tEXt_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001910/* Note: this does not properly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001911void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001912png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001913{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001914 png_textp text_ptr;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001915 png_charp key;
Guy Schalnat6d764711995-12-19 03:22:19 -06001916 png_charp text;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001917 png_uint_32 skip = 0;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001918 png_size_t slength;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001919 int ret;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001920
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001921 png_debug(1, "in png_handle_tEXt");
Guy Schalnat0d580581995-07-20 02:43:20 -05001922
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05001923#ifdef PNG_SET_USER_LIMITS_SUPPORTED
1924 if (png_ptr->user_chunk_cache_max != 0)
1925 {
1926 if (png_ptr->user_chunk_cache_max == 1)
1927 {
1928 png_crc_finish(png_ptr, length);
1929 return;
1930 }
1931 if (--png_ptr->user_chunk_cache_max == 1)
1932 {
1933 png_warning(png_ptr, "No space in chunk cache for tEXt");
1934 png_crc_finish(png_ptr, length);
1935 return;
1936 }
1937 }
1938#endif
1939
Guy Schalnate5a37791996-06-05 15:50:50 -05001940 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1941 png_error(png_ptr, "Missing IHDR before tEXt");
1942
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001943 if (png_ptr->mode & PNG_HAVE_IDAT)
1944 png_ptr->mode |= PNG_AFTER_IDAT;
1945
Andreas Dilger47a0c421997-05-16 02:46:07 -05001946#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001947 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001948 {
1949 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001950 skip = length - (png_uint_32)65535L;
1951 length = (png_uint_32)65535L;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001952 }
1953#endif
1954
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05001955 png_free(png_ptr, png_ptr->chunkdata);
1956
1957 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1958 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001959 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001960 png_warning(png_ptr, "No memory to process text chunk");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001961 return;
1962 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001963 slength = (png_size_t)length;
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05001964 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001965
1966 if (png_crc_finish(png_ptr, skip))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001967 {
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05001968 png_free(png_ptr, png_ptr->chunkdata);
1969 png_ptr->chunkdata = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001970 return;
1971 }
1972
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05001973 key = png_ptr->chunkdata;
1974
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001975 key[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05001976
1977 for (text = key; *text; text++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001978 /* empty loop to find end of key */ ;
Guy Schalnat0d580581995-07-20 02:43:20 -05001979
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001980 if (text != key + slength)
Guy Schalnat0d580581995-07-20 02:43:20 -05001981 text++;
1982
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001983 text_ptr = (png_textp)png_malloc_warn(png_ptr,
1984 png_sizeof(png_text));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001985 if (text_ptr == NULL)
1986 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001987 png_warning(png_ptr, "Not enough memory to process text chunk");
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05001988 png_free(png_ptr, png_ptr->chunkdata);
1989 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001990 return;
1991 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001992 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1993 text_ptr->key = key;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001994#ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001995 text_ptr->lang = NULL;
1996 text_ptr->lang_key = NULL;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001997 text_ptr->itxt_length = 0;
1998#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001999 text_ptr->text = text;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002000 text_ptr->text_length = png_strlen(text);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002001
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002002 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002003
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002004 png_free(png_ptr, png_ptr->chunkdata);
2005 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002006 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002007 if (ret)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05002008 png_warning(png_ptr, "Insufficient memory to process text chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -05002009}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002010#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002011
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002012#if defined(PNG_READ_zTXt_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002013/* note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002014void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002015png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05002016{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002017 png_textp text_ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -06002018 png_charp text;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002019 int comp_type;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002020 int ret;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002021 png_size_t slength, prefix_len, data_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002022
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002023 png_debug(1, "in png_handle_zTXt");
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002024
2025#ifdef PNG_SET_USER_LIMITS_SUPPORTED
2026 if (png_ptr->user_chunk_cache_max != 0)
2027 {
2028 if (png_ptr->user_chunk_cache_max == 1)
2029 {
2030 png_crc_finish(png_ptr, length);
2031 return;
2032 }
2033 if (--png_ptr->user_chunk_cache_max == 1)
2034 {
2035 png_warning(png_ptr, "No space in chunk cache for zTXt");
2036 png_crc_finish(png_ptr, length);
2037 return;
2038 }
2039 }
2040#endif
2041
Guy Schalnate5a37791996-06-05 15:50:50 -05002042 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2043 png_error(png_ptr, "Missing IHDR before zTXt");
2044
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002045 if (png_ptr->mode & PNG_HAVE_IDAT)
2046 png_ptr->mode |= PNG_AFTER_IDAT;
2047
Andreas Dilger47a0c421997-05-16 02:46:07 -05002048#ifdef PNG_MAX_MALLOC_64K
2049 /* We will no doubt have problems with chunks even half this size, but
2050 there is no hard and fast rule to tell us where to stop. */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002051 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002052 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002053 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
Andreas Dilger47a0c421997-05-16 02:46:07 -05002054 png_crc_finish(png_ptr, length);
2055 return;
2056 }
2057#endif
2058
Glenn Randers-Pehrson97a9b482008-10-25 20:03:28 -05002059 png_free(png_ptr, png_ptr->chunkdata);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002060 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2061 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002062 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002063 png_warning(png_ptr, "Out of memory processing zTXt chunk");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002064 return;
2065 }
2066 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002067 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002068 if (png_crc_finish(png_ptr, 0))
2069 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002070 png_free(png_ptr, png_ptr->chunkdata);
2071 png_ptr->chunkdata = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002072 return;
2073 }
2074
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002075 png_ptr->chunkdata[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05002076
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002077 for (text = png_ptr->chunkdata; *text; text++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002078 /* empty loop */ ;
2079
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002080 /* zTXt must have some text after the chunkdataword */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002081 if (text >= png_ptr->chunkdata + slength - 2)
Guy Schalnat0d580581995-07-20 02:43:20 -05002082 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002083 png_warning(png_ptr, "Truncated zTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002084 png_free(png_ptr, png_ptr->chunkdata);
2085 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002086 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05002087 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002088 else
Guy Schalnat0d580581995-07-20 02:43:20 -05002089 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002090 comp_type = *(++text);
Glenn Randers-Pehrsonf05f8032000-12-23 14:27:39 -06002091 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2092 {
2093 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2094 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2095 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002096 text++; /* skip the compression_method byte */
Guy Schalnat0d580581995-07-20 02:43:20 -05002097 }
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002098 prefix_len = text - png_ptr->chunkdata;
Guy Schalnat0d580581995-07-20 02:43:20 -05002099
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -05002100 png_decompress_chunk(png_ptr, comp_type,
2101 (png_size_t)length, prefix_len, &data_len);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002102
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002103 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2104 png_sizeof(png_text));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002105 if (text_ptr == NULL)
2106 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002107 png_warning(png_ptr, "Not enough memory to process zTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002108 png_free(png_ptr, png_ptr->chunkdata);
2109 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002110 return;
2111 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002112 text_ptr->compression = comp_type;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002113 text_ptr->key = png_ptr->chunkdata;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002114#ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002115 text_ptr->lang = NULL;
2116 text_ptr->lang_key = NULL;
2117 text_ptr->itxt_length = 0;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002118#endif
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002119 text_ptr->text = png_ptr->chunkdata + prefix_len;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002120 text_ptr->text_length = data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002121
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002122 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002123
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002124 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002125 png_free(png_ptr, png_ptr->chunkdata);
2126 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002127 if (ret)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05002128 png_error(png_ptr, "Insufficient memory to store zTXt chunk");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002129}
2130#endif
2131
2132#if defined(PNG_READ_iTXt_SUPPORTED)
2133/* note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002134void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002135png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2136{
2137 png_textp text_ptr;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002138 png_charp key, lang, text, lang_key;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002139 int comp_flag;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002140 int comp_type = 0;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002141 int ret;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002142 png_size_t slength, prefix_len, data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002143
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002144 png_debug(1, "in png_handle_iTXt");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002145
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002146#ifdef PNG_SET_USER_LIMITS_SUPPORTED
2147 if (png_ptr->user_chunk_cache_max != 0)
2148 {
2149 if (png_ptr->user_chunk_cache_max == 1)
2150 {
2151 png_crc_finish(png_ptr, length);
2152 return;
2153 }
2154 if (--png_ptr->user_chunk_cache_max == 1)
2155 {
2156 png_warning(png_ptr, "No space in chunk cache for iTXt");
2157 png_crc_finish(png_ptr, length);
2158 return;
2159 }
2160 }
2161#endif
2162
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002163 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2164 png_error(png_ptr, "Missing IHDR before iTXt");
2165
2166 if (png_ptr->mode & PNG_HAVE_IDAT)
2167 png_ptr->mode |= PNG_AFTER_IDAT;
2168
2169#ifdef PNG_MAX_MALLOC_64K
2170 /* We will no doubt have problems with chunks even half this size, but
2171 there is no hard and fast rule to tell us where to stop. */
2172 if (length > (png_uint_32)65535L)
2173 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002174 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002175 png_crc_finish(png_ptr, length);
2176 return;
2177 }
2178#endif
2179
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002180 png_free(png_ptr, png_ptr->chunkdata);
2181 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2182 if (png_ptr->chunkdata == NULL)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002183 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05002184 png_warning(png_ptr, "No memory to process iTXt chunk");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002185 return;
2186 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002187 slength = (png_size_t)length;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002188 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002189 if (png_crc_finish(png_ptr, 0))
2190 {
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002191 png_free(png_ptr, png_ptr->chunkdata);
2192 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002193 return;
2194 }
2195
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002196 png_ptr->chunkdata[slength] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002197
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002198 for (lang = png_ptr->chunkdata; *lang; lang++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002199 /* empty loop */ ;
2200 lang++; /* skip NUL separator */
2201
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002202 /* iTXt must have a language tag (possibly empty), two compression bytes,
2203 translated keyword (possibly empty), and possibly some text after the
2204 keyword */
2205
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002206 if (lang >= png_ptr->chunkdata + slength - 3)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002207 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002208 png_warning(png_ptr, "Truncated iTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002209 png_free(png_ptr, png_ptr->chunkdata);
2210 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002211 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002212 }
2213 else
2214 {
2215 comp_flag = *lang++;
2216 comp_type = *lang++;
2217 }
2218
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002219 for (lang_key = lang; *lang_key; lang_key++)
2220 /* empty loop */ ;
2221 lang_key++; /* skip NUL separator */
2222
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002223 if (lang_key >= png_ptr->chunkdata + slength)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002224 {
2225 png_warning(png_ptr, "Truncated iTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002226 png_free(png_ptr, png_ptr->chunkdata);
2227 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002228 return;
2229 }
2230
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002231 for (text = lang_key; *text; text++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002232 /* empty loop */ ;
2233 text++; /* skip NUL separator */
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002234 if (text >= png_ptr->chunkdata + slength)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002235 {
2236 png_warning(png_ptr, "Malformed iTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002237 png_free(png_ptr, png_ptr->chunkdata);
2238 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002239 return;
2240 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002241
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002242 prefix_len = text - png_ptr->chunkdata;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002243
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002244 key=png_ptr->chunkdata;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002245 if (comp_flag)
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -05002246 png_decompress_chunk(png_ptr, comp_type,
2247 (size_t)length, prefix_len, &data_len);
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002248 else
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002249 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002250 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2251 png_sizeof(png_text));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002252 if (text_ptr == NULL)
2253 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002254 png_warning(png_ptr, "Not enough memory to process iTXt chunk");
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002255 png_free(png_ptr, png_ptr->chunkdata);
2256 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002257 return;
2258 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002259 text_ptr->compression = (int)comp_flag + 1;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002260 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
2261 text_ptr->lang = png_ptr->chunkdata + (lang - key);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002262 text_ptr->itxt_length = data_len;
2263 text_ptr->text_length = 0;
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002264 text_ptr->key = png_ptr->chunkdata;
2265 text_ptr->text = png_ptr->chunkdata + prefix_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002266
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002267 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002268
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002269 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05002270 png_free(png_ptr, png_ptr->chunkdata);
2271 png_ptr->chunkdata = NULL;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002272 if (ret)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05002273 png_error(png_ptr, "Insufficient memory to store iTXt chunk");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002274}
2275#endif
2276
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002277/* This function is called when we haven't found a handler for a
2278 chunk. If there isn't a problem with the chunk itself (ie bad
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002279 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2280 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2281 case it will be saved away to be written out later. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002282void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002283png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2284{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002285 png_uint_32 skip = 0;
2286
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002287 png_debug(1, "in png_handle_unknown");
Andreas Dilger47a0c421997-05-16 02:46:07 -05002288
Glenn Randers-Pehrson800d1e92008-08-20 17:25:21 -05002289#ifdef PNG_SET_USER_LIMITS_SUPPORTED
2290 if (png_ptr->user_chunk_cache_max != 0)
2291 {
2292 if (png_ptr->user_chunk_cache_max == 1)
2293 {
2294 png_crc_finish(png_ptr, length);
2295 return;
2296 }
2297 if (--png_ptr->user_chunk_cache_max == 1)
2298 {
2299 png_warning(png_ptr, "No space in chunk cache for unknown chunk");
2300 png_crc_finish(png_ptr, length);
2301 return;
2302 }
2303 }
2304#endif
2305
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002306 if (png_ptr->mode & PNG_HAVE_IDAT)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002307 {
2308#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002309 PNG_CONST PNG_IDAT;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002310#endif
2311 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2312 png_ptr->mode |= PNG_AFTER_IDAT;
2313 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002314
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002315 if (!(png_ptr->chunk_name[0] & 0x20))
2316 {
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05002317#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002318 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -05002319 PNG_HANDLE_CHUNK_ALWAYS
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002320#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002321 && png_ptr->read_user_chunk_fn == NULL
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002322#endif
2323 )
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05002324#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002325 png_chunk_error(png_ptr, "unknown critical chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002326 }
2327
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002328#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06002329 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
2330 (png_ptr->read_user_chunk_fn != NULL))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002331 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002332#ifdef PNG_MAX_MALLOC_64K
2333 if (length > (png_uint_32)65535L)
2334 {
2335 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2336 skip = length - (png_uint_32)65535L;
2337 length = (png_uint_32)65535L;
2338 }
2339#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002340 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
2341 (png_charp)png_ptr->chunk_name,
2342 png_sizeof(png_ptr->unknown_chunk.name));
2343 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0';
2344 png_ptr->unknown_chunk.size = (png_size_t)length;
2345 if (length == 0)
2346 png_ptr->unknown_chunk.data = NULL;
2347 else
2348 {
2349 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2350 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2351 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002352#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002353 if (png_ptr->read_user_chunk_fn != NULL)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002354 {
2355 /* callback to user unknown chunk handler */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002356 int ret;
2357 ret = (*(png_ptr->read_user_chunk_fn))
2358 (png_ptr, &png_ptr->unknown_chunk);
2359 if (ret < 0)
2360 png_chunk_error(png_ptr, "error in user chunk");
2361 if (ret == 0)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002362 {
2363 if (!(png_ptr->chunk_name[0] & 0x20))
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002364 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -05002365 PNG_HANDLE_CHUNK_ALWAYS)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002366 png_chunk_error(png_ptr, "unknown critical chunk");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002367 png_set_unknown_chunks(png_ptr, info_ptr,
2368 &png_ptr->unknown_chunk, 1);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002369 }
2370 }
2371 else
2372#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002373 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
2374 png_free(png_ptr, png_ptr->unknown_chunk.data);
2375 png_ptr->unknown_chunk.data = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002376 }
2377 else
2378#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002379 skip = length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002380
2381 png_crc_finish(png_ptr, skip);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002382
2383#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002384 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002385#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002386}
2387
2388/* This function is called to verify that a chunk name is valid.
2389 This function can't have the "critical chunk check" incorporated
Andreas Dilger47a0c421997-05-16 02:46:07 -05002390 into it, since in the future we will need to be able to call user
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002391 functions to handle unknown critical chunks after we check that
2392 the chunk name itself is valid. */
Andreas Dilger47a0c421997-05-16 02:46:07 -05002393
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05002394#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
Andreas Dilger47a0c421997-05-16 02:46:07 -05002395
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002396void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002397png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2398{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002399 png_debug(1, "in png_check_chunk_name");
Andreas Dilger47a0c421997-05-16 02:46:07 -05002400 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -05002401 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002402 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06002403 png_chunk_error(png_ptr, "invalid chunk type");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002404 }
2405}
2406
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002407/* Combines the row recently read in with the existing pixels in the
2408 row. This routine takes care of alpha and transparency if requested.
Guy Schalnat0d580581995-07-20 02:43:20 -05002409 This routine also handles the two methods of progressive display
2410 of interlaced images, depending on the mask value.
2411 The mask value describes which pixels are to be combined with
2412 the row. The pattern always repeats every 8 pixels, so just 8
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002413 bits are needed. A one indicates the pixel is to be combined,
Guy Schalnat0d580581995-07-20 02:43:20 -05002414 a zero indicates the pixel is to be skipped. This is in addition
2415 to any alpha or transparency value associated with the pixel. If
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002416 you want all pixels to be combined, pass 0xff (255) in mask. */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002417
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002418void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002419png_combine_row(png_structp png_ptr, png_bytep row, int mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002420{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002421 png_debug(1, "in png_combine_row");
Guy Schalnat0d580581995-07-20 02:43:20 -05002422 if (mask == 0xff)
2423 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002424 png_memcpy(row, png_ptr->row_buf + 1,
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002425 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
Guy Schalnat0d580581995-07-20 02:43:20 -05002426 }
2427 else
2428 {
2429 switch (png_ptr->row_info.pixel_depth)
2430 {
2431 case 1:
2432 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002433 png_bytep sp = png_ptr->row_buf + 1;
2434 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002435 int s_inc, s_start, s_end;
2436 int m = 0x80;
2437 int shift;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002438 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002439 png_uint_32 row_width = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05002440
Andreas Dilger47a0c421997-05-16 02:46:07 -05002441#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2442 if (png_ptr->transformations & PNG_PACKSWAP)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002443 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002444 s_start = 0;
2445 s_end = 7;
2446 s_inc = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002447 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002448 else
2449#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002450 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002451 s_start = 7;
2452 s_end = 0;
2453 s_inc = -1;
2454 }
2455
2456 shift = s_start;
2457
2458 for (i = 0; i < row_width; i++)
2459 {
2460 if (m & mask)
2461 {
2462 int value;
2463
2464 value = (*sp >> shift) & 0x01;
2465 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2466 *dp |= (png_byte)(value << shift);
2467 }
2468
2469 if (shift == s_end)
2470 {
2471 shift = s_start;
2472 sp++;
2473 dp++;
2474 }
2475 else
2476 shift += s_inc;
2477
2478 if (m == 1)
2479 m = 0x80;
2480 else
2481 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002482 }
2483 break;
2484 }
2485 case 2:
2486 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002487 png_bytep sp = png_ptr->row_buf + 1;
2488 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002489 int s_start, s_end, s_inc;
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002490 int m = 0x80;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002491 int shift;
2492 png_uint_32 i;
2493 png_uint_32 row_width = png_ptr->width;
2494 int value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002495
Andreas Dilger47a0c421997-05-16 02:46:07 -05002496#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2497 if (png_ptr->transformations & PNG_PACKSWAP)
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002498 {
2499 s_start = 0;
2500 s_end = 6;
2501 s_inc = 2;
2502 }
2503 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002504#endif
2505 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002506 s_start = 6;
2507 s_end = 0;
2508 s_inc = -2;
2509 }
2510
2511 shift = s_start;
2512
2513 for (i = 0; i < row_width; i++)
2514 {
2515 if (m & mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002516 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002517 value = (*sp >> shift) & 0x03;
2518 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2519 *dp |= (png_byte)(value << shift);
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002520 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002521
2522 if (shift == s_end)
2523 {
2524 shift = s_start;
2525 sp++;
2526 dp++;
2527 }
2528 else
2529 shift += s_inc;
2530 if (m == 1)
2531 m = 0x80;
2532 else
2533 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002534 }
2535 break;
2536 }
2537 case 4:
2538 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002539 png_bytep sp = png_ptr->row_buf + 1;
2540 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002541 int s_start, s_end, s_inc;
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002542 int m = 0x80;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002543 int shift;
2544 png_uint_32 i;
2545 png_uint_32 row_width = png_ptr->width;
2546 int value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002547
Andreas Dilger47a0c421997-05-16 02:46:07 -05002548#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2549 if (png_ptr->transformations & PNG_PACKSWAP)
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002550 {
2551 s_start = 0;
2552 s_end = 4;
2553 s_inc = 4;
2554 }
2555 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002556#endif
2557 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002558 s_start = 4;
2559 s_end = 0;
2560 s_inc = -4;
2561 }
2562 shift = s_start;
2563
2564 for (i = 0; i < row_width; i++)
2565 {
2566 if (m & mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002567 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002568 value = (*sp >> shift) & 0xf;
2569 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2570 *dp |= (png_byte)(value << shift);
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002571 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002572
2573 if (shift == s_end)
2574 {
2575 shift = s_start;
2576 sp++;
2577 dp++;
2578 }
2579 else
2580 shift += s_inc;
2581 if (m == 1)
2582 m = 0x80;
2583 else
2584 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002585 }
2586 break;
2587 }
2588 default:
2589 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002590 png_bytep sp = png_ptr->row_buf + 1;
2591 png_bytep dp = row;
2592 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2593 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002594 png_uint_32 row_width = png_ptr->width;
2595 png_byte m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05002596
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002597
2598 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002599 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002600 if (m & mask)
2601 {
2602 png_memcpy(dp, sp, pixel_bytes);
2603 }
2604
2605 sp += pixel_bytes;
2606 dp += pixel_bytes;
2607
2608 if (m == 1)
2609 m = 0x80;
2610 else
2611 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002612 }
2613 break;
2614 }
2615 }
2616 }
2617}
2618
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002619#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002620/* OLD pre-1.0.9 interface:
2621void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2622 png_uint_32 transformations)
2623 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002624void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002625png_do_read_interlace(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002626{
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002627 png_row_infop row_info = &(png_ptr->row_info);
2628 png_bytep row = png_ptr->row_buf + 1;
2629 int pass = png_ptr->pass;
2630 png_uint_32 transformations = png_ptr->transformations;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002631#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002632 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002633 /* offset to next interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002634 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002635#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002636
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002637 png_debug(1, "in png_do_read_interlace");
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002638 if (row != NULL && row_info != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002639 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002640 png_uint_32 final_width;
2641
2642 final_width = row_info->width * png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05002643
2644 switch (row_info->pixel_depth)
2645 {
2646 case 1:
2647 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002648 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2649 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002650 int sshift, dshift;
2651 int s_start, s_end, s_inc;
2652 int jstop = png_pass_inc[pass];
2653 png_byte v;
Guy Schalnat0d580581995-07-20 02:43:20 -05002654 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002655 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -05002656
Andreas Dilger47a0c421997-05-16 02:46:07 -05002657#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2658 if (transformations & PNG_PACKSWAP)
2659 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002660 sshift = (int)((row_info->width + 7) & 0x07);
2661 dshift = (int)((final_width + 7) & 0x07);
2662 s_start = 7;
2663 s_end = 0;
2664 s_inc = -1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002665 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002666 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002667#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002668 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002669 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2670 dshift = 7 - (int)((final_width + 7) & 0x07);
2671 s_start = 0;
2672 s_end = 7;
2673 s_inc = 1;
2674 }
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002675
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002676 for (i = 0; i < row_info->width; i++)
2677 {
2678 v = (png_byte)((*sp >> sshift) & 0x01);
2679 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002680 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002681 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2682 *dp |= (png_byte)(v << dshift);
2683 if (dshift == s_end)
2684 {
2685 dshift = s_start;
2686 dp--;
2687 }
2688 else
2689 dshift += s_inc;
2690 }
2691 if (sshift == s_end)
2692 {
2693 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002694 sp--;
2695 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002696 else
2697 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002698 }
2699 break;
2700 }
2701 case 2:
2702 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002703 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2704 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2705 int sshift, dshift;
2706 int s_start, s_end, s_inc;
2707 int jstop = png_pass_inc[pass];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002708 png_uint_32 i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002709
Andreas Dilger47a0c421997-05-16 02:46:07 -05002710#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2711 if (transformations & PNG_PACKSWAP)
2712 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002713 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2714 dshift = (int)(((final_width + 3) & 0x03) << 1);
2715 s_start = 6;
2716 s_end = 0;
2717 s_inc = -2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002718 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002719 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002720#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002721 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002722 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2723 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2724 s_start = 0;
2725 s_end = 6;
2726 s_inc = 2;
2727 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002728
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002729 for (i = 0; i < row_info->width; i++)
2730 {
2731 png_byte v;
2732 int j;
2733
2734 v = (png_byte)((*sp >> sshift) & 0x03);
2735 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002736 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002737 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2738 *dp |= (png_byte)(v << dshift);
2739 if (dshift == s_end)
2740 {
2741 dshift = s_start;
2742 dp--;
2743 }
2744 else
2745 dshift += s_inc;
2746 }
2747 if (sshift == s_end)
2748 {
2749 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002750 sp--;
2751 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002752 else
2753 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002754 }
2755 break;
2756 }
2757 case 4:
2758 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002759 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2760 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002761 int sshift, dshift;
2762 int s_start, s_end, s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002763 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002764 int jstop = png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05002765
Andreas Dilger47a0c421997-05-16 02:46:07 -05002766#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2767 if (transformations & PNG_PACKSWAP)
2768 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002769 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2770 dshift = (int)(((final_width + 1) & 0x01) << 2);
2771 s_start = 4;
2772 s_end = 0;
2773 s_inc = -4;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002774 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002775 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002776#endif
2777 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002778 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2779 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2780 s_start = 0;
2781 s_end = 4;
2782 s_inc = 4;
2783 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002784
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002785 for (i = 0; i < row_info->width; i++)
2786 {
2787 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2788 int j;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002789
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002790 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002791 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002792 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2793 *dp |= (png_byte)(v << dshift);
2794 if (dshift == s_end)
2795 {
2796 dshift = s_start;
2797 dp--;
2798 }
2799 else
2800 dshift += s_inc;
2801 }
2802 if (sshift == s_end)
2803 {
2804 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002805 sp--;
2806 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002807 else
2808 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002809 }
2810 break;
2811 }
2812 default:
2813 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002814 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2815 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002816 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05002817
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002818 int jstop = png_pass_inc[pass];
2819 png_uint_32 i;
2820
2821 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002822 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002823 png_byte v[8];
2824 int j;
2825
2826 png_memcpy(v, sp, pixel_bytes);
2827 for (j = 0; j < jstop; j++)
2828 {
2829 png_memcpy(dp, v, pixel_bytes);
2830 dp -= pixel_bytes;
2831 }
2832 sp -= pixel_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05002833 }
2834 break;
2835 }
2836 }
2837 row_info->width = final_width;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002838 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
Guy Schalnat0d580581995-07-20 02:43:20 -05002839 }
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05002840#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002841 transformations = transformations; /* silence compiler warning */
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05002842#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002843}
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002844#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05002845
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002846void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002847png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002848 png_bytep prev_row, int filter)
2849{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002850 png_debug(1, "in png_read_filter_row");
2851 png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002852 switch (filter)
2853 {
2854 case PNG_FILTER_VALUE_NONE:
2855 break;
2856 case PNG_FILTER_VALUE_SUB:
2857 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002858 png_uint_32 i;
2859 png_uint_32 istop = row_info->rowbytes;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002860 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002861 png_bytep rp = row + bpp;
2862 png_bytep lp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002863
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002864 for (i = bpp; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002865 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002866 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2867 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002868 }
2869 break;
2870 }
2871 case PNG_FILTER_VALUE_UP:
2872 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002873 png_uint_32 i;
2874 png_uint_32 istop = row_info->rowbytes;
2875 png_bytep rp = row;
2876 png_bytep pp = prev_row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002877
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002878 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002879 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002880 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2881 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002882 }
2883 break;
2884 }
2885 case PNG_FILTER_VALUE_AVG:
2886 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002887 png_uint_32 i;
2888 png_bytep rp = row;
2889 png_bytep pp = prev_row;
2890 png_bytep lp = row;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002891 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002892 png_uint_32 istop = row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002893
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002894 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002895 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002896 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002897 ((int)(*pp++) / 2 )) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002898 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002899 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002900
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002901 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002902 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002903 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002904 (int)(*pp++ + *lp++) / 2 ) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002905 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002906 }
2907 break;
2908 }
2909 case PNG_FILTER_VALUE_PAETH:
2910 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002911 png_uint_32 i;
2912 png_bytep rp = row;
2913 png_bytep pp = prev_row;
2914 png_bytep lp = row;
2915 png_bytep cp = prev_row;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002916 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002917 png_uint_32 istop=row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002918
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002919 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002920 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002921 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2922 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002923 }
2924
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002925 for (i = 0; i < istop; i++) /* use leftover rp,pp */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002926 {
2927 int a, b, c, pa, pb, pc, p;
2928
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002929 a = *lp++;
2930 b = *pp++;
2931 c = *cp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002932
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002933 p = b - c;
2934 pc = a - c;
2935
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002936#ifdef PNG_USE_ABS
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002937 pa = abs(p);
2938 pb = abs(pc);
2939 pc = abs(p + pc);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002940#else
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002941 pa = p < 0 ? -p : p;
2942 pb = pc < 0 ? -pc : pc;
2943 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002944#endif
2945
2946 /*
2947 if (pa <= pb && pa <= pc)
2948 p = a;
2949 else if (pb <= pc)
2950 p = b;
2951 else
2952 p = c;
2953 */
2954
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002955 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002956
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002957 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2958 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002959 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002960 break;
2961 }
2962 default:
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002963 png_warning(png_ptr, "Ignoring bad adaptive filter type");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002964 *row = 0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002965 break;
2966 }
2967}
Guy Schalnat0d580581995-07-20 02:43:20 -05002968
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002969void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002970png_read_finish_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002971{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002972#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002973#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002974 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002975
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002976 /* start of interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002977 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002978
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002979 /* offset to next interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002980 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002981
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002982 /* start of interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002983 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002984
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002985 /* offset to next interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002986 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
2987#endif /* PNG_READ_INTERLACING_SUPPORTED */
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002988#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002989
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05002990 png_debug(1, "in png_read_finish_row");
Guy Schalnat0d580581995-07-20 02:43:20 -05002991 png_ptr->row_number++;
2992 if (png_ptr->row_number < png_ptr->num_rows)
2993 return;
2994
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05002995#ifdef PNG_READ_INTERLACING_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05002996 if (png_ptr->interlaced)
2997 {
2998 png_ptr->row_number = 0;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05002999 png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05003000 do
3001 {
3002 png_ptr->pass++;
3003 if (png_ptr->pass >= 7)
3004 break;
3005 png_ptr->iwidth = (png_ptr->width +
3006 png_pass_inc[png_ptr->pass] - 1 -
3007 png_pass_start[png_ptr->pass]) /
3008 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05003009
3010 png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
3011 png_ptr->iwidth) + 1;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003012
Guy Schalnat0d580581995-07-20 02:43:20 -05003013 if (!(png_ptr->transformations & PNG_INTERLACE))
3014 {
3015 png_ptr->num_rows = (png_ptr->height +
3016 png_pass_yinc[png_ptr->pass] - 1 -
3017 png_pass_ystart[png_ptr->pass]) /
3018 png_pass_yinc[png_ptr->pass];
3019 if (!(png_ptr->num_rows))
3020 continue;
3021 }
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05003022 else /* if (png_ptr->transformations & PNG_INTERLACE) */
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003023 break;
Guy Schalnat0d580581995-07-20 02:43:20 -05003024 } while (png_ptr->iwidth == 0);
3025
3026 if (png_ptr->pass < 7)
3027 return;
3028 }
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003029#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003030
Guy Schalnate5a37791996-06-05 15:50:50 -05003031 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
Guy Schalnat0d580581995-07-20 02:43:20 -05003032 {
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06003033#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003034 PNG_CONST PNG_IDAT;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06003035#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003036 char extra;
3037 int ret;
3038
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003039 png_ptr->zstream.next_out = (Byte *)&extra;
3040 png_ptr->zstream.avail_out = (uInt)1;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003041 for (;;)
Guy Schalnat0d580581995-07-20 02:43:20 -05003042 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003043 if (!(png_ptr->zstream.avail_in))
Guy Schalnat0d580581995-07-20 02:43:20 -05003044 {
3045 while (!png_ptr->idat_size)
3046 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003047 png_byte chunk_length[4];
Guy Schalnat0d580581995-07-20 02:43:20 -05003048
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003049 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -05003050
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003051 png_read_data(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05003052 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnat0d580581995-07-20 02:43:20 -05003053 png_reset_crc(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003054 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003055 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Guy Schalnat6d764711995-12-19 03:22:19 -06003056 png_error(png_ptr, "Not enough image data");
Guy Schalnat0d580581995-07-20 02:43:20 -05003057
3058 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003059 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
3060 png_ptr->zstream.next_in = png_ptr->zbuf;
Guy Schalnat0d580581995-07-20 02:43:20 -05003061 if (png_ptr->zbuf_size > png_ptr->idat_size)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003062 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
3063 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
3064 png_ptr->idat_size -= png_ptr->zstream.avail_in;
Guy Schalnat0d580581995-07-20 02:43:20 -05003065 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003066 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnat0d580581995-07-20 02:43:20 -05003067 if (ret == Z_STREAM_END)
3068 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003069 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
Guy Schalnat0d580581995-07-20 02:43:20 -05003070 png_ptr->idat_size)
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003071 png_warning(png_ptr, "Extra compressed data");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003072 png_ptr->mode |= PNG_AFTER_IDAT;
3073 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Guy Schalnat0d580581995-07-20 02:43:20 -05003074 break;
3075 }
3076 if (ret != Z_OK)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003077 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
Guy Schalnate5a37791996-06-05 15:50:50 -05003078 "Decompression Error");
Guy Schalnat0d580581995-07-20 02:43:20 -05003079
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003080 if (!(png_ptr->zstream.avail_out))
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003081 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003082 png_warning(png_ptr, "Extra compressed data");
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003083 png_ptr->mode |= PNG_AFTER_IDAT;
3084 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3085 break;
3086 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003087
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -06003088 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003089 png_ptr->zstream.avail_out = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003090 }
3091
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003092 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05003093 png_warning(png_ptr, "Extra compression data");
Guy Schalnat0d580581995-07-20 02:43:20 -05003094
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003095 inflateReset(&png_ptr->zstream);
Guy Schalnat0d580581995-07-20 02:43:20 -05003096
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003097 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnat0d580581995-07-20 02:43:20 -05003098}
3099
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05003100void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06003101png_read_start_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05003102{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06003103#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003104#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06003105 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003106
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06003107 /* start of interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003108 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003109
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06003110 /* offset to next interlace block */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003111 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003112
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06003113 /* start of interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003114 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003115
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06003116 /* offset to next interlace block in the y direction */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003117 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3118#endif
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06003119#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06003120
Guy Schalnat0d580581995-07-20 02:43:20 -05003121 int max_pixel_depth;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003122 png_size_t row_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05003123
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05003124 png_debug(1, "in png_read_start_row");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06003125 png_ptr->zstream.avail_in = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05003126 png_init_read_transformations(png_ptr);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003127#ifdef PNG_READ_INTERLACING_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05003128 if (png_ptr->interlaced)
3129 {
3130 if (!(png_ptr->transformations & PNG_INTERLACE))
3131 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
3132 png_pass_ystart[0]) / png_pass_yinc[0];
3133 else
3134 png_ptr->num_rows = png_ptr->height;
3135
3136 png_ptr->iwidth = (png_ptr->width +
3137 png_pass_inc[png_ptr->pass] - 1 -
3138 png_pass_start[png_ptr->pass]) /
3139 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003140
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003141 png_ptr->irowbytes =
3142 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05003143 }
3144 else
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003145#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05003146 {
3147 png_ptr->num_rows = png_ptr->height;
3148 png_ptr->iwidth = png_ptr->width;
3149 png_ptr->irowbytes = png_ptr->rowbytes + 1;
3150 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003151 max_pixel_depth = png_ptr->pixel_depth;
3152
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003153#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003154 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05003155 max_pixel_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003156#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003157
Guy Schalnate5a37791996-06-05 15:50:50 -05003158#if defined(PNG_READ_EXPAND_SUPPORTED)
3159 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05003160 {
3161 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3162 {
3163 if (png_ptr->num_trans)
3164 max_pixel_depth = 32;
3165 else
3166 max_pixel_depth = 24;
3167 }
3168 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3169 {
3170 if (max_pixel_depth < 8)
3171 max_pixel_depth = 8;
3172 if (png_ptr->num_trans)
3173 max_pixel_depth *= 2;
3174 }
3175 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3176 {
3177 if (png_ptr->num_trans)
3178 {
3179 max_pixel_depth *= 4;
3180 max_pixel_depth /= 3;
3181 }
3182 }
3183 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003184#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003185
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003186#if defined(PNG_READ_FILLER_SUPPORTED)
3187 if (png_ptr->transformations & (PNG_FILLER))
Guy Schalnat0d580581995-07-20 02:43:20 -05003188 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003189 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3190 max_pixel_depth = 32;
3191 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003192 {
3193 if (max_pixel_depth <= 8)
3194 max_pixel_depth = 16;
3195 else
3196 max_pixel_depth = 32;
3197 }
3198 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3199 {
3200 if (max_pixel_depth <= 32)
3201 max_pixel_depth = 32;
3202 else
3203 max_pixel_depth = 64;
3204 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003205 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003206#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003207
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003208#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003209 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3210 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003211 if (
3212#if defined(PNG_READ_EXPAND_SUPPORTED)
3213 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3214#endif
3215#if defined(PNG_READ_FILLER_SUPPORTED)
3216 (png_ptr->transformations & (PNG_FILLER)) ||
3217#endif
3218 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
Guy Schalnat0d580581995-07-20 02:43:20 -05003219 {
3220 if (max_pixel_depth <= 16)
3221 max_pixel_depth = 32;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003222 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003223 max_pixel_depth = 64;
3224 }
3225 else
3226 {
3227 if (max_pixel_depth <= 8)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06003228 {
3229 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3230 max_pixel_depth = 32;
3231 else
3232 max_pixel_depth = 24;
3233 }
3234 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3235 max_pixel_depth = 64;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003236 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003237 max_pixel_depth = 48;
3238 }
3239 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003240#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003241
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05003242#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3243defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003244 if (png_ptr->transformations & PNG_USER_TRANSFORM)
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003245 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003246 int user_pixel_depth = png_ptr->user_transform_depth*
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003247 png_ptr->user_transform_channels;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003248 if (user_pixel_depth > max_pixel_depth)
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003249 max_pixel_depth=user_pixel_depth;
3250 }
3251#endif
3252
Guy Schalnat0d580581995-07-20 02:43:20 -05003253 /* align the width on the next larger 8 pixels. Mainly used
3254 for interlacing */
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003255 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
Guy Schalnat0d580581995-07-20 02:43:20 -05003256 /* calculate the maximum bytes needed, adding a byte and a pixel
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003257 for safety's sake */
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003258 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
Guy Schalnat0d580581995-07-20 02:43:20 -05003259 1 + ((max_pixel_depth + 7) >> 3);
3260#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003261 if (row_bytes > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05003262 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05003263#endif
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003264
3265 if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
3266 {
3267 png_free(png_ptr, png_ptr->big_row_buf);
Glenn Randers-Pehrson6917b512009-03-09 15:31:08 -05003268 if (png_ptr->interlaced)
Glenn Randers-Pehrson8fb550c2009-03-21 08:15:32 -05003269 png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr, row_bytes + 64);
Glenn Randers-Pehrson6917b512009-03-09 15:31:08 -05003270 else
Glenn Randers-Pehrson8fb550c2009-03-21 08:15:32 -05003271 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes + 64);
3272 png_ptr->row_buf = png_ptr->big_row_buf + 32;
3273 png_ptr->old_big_row_buf_size = row_bytes + 64;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003274 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003275
3276#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003277 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05003278 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05003279#endif
Glenn Randers-Pehrsonebd7f9a2006-10-19 09:37:56 -05003280 if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003281 png_error(png_ptr, "Row has too many bytes to allocate in memory");
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05003282
3283 if (png_ptr->rowbytes+1 > png_ptr->old_prev_row_size)
3284 {
3285 png_free(png_ptr, png_ptr->prev_row);
3286 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3287 png_ptr->rowbytes + 1));
3288 png_ptr->old_prev_row_size = png_ptr->rowbytes+1;
3289 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003290
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05003291 png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003292
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05003293 png_debug1(3, "width = %lu,", png_ptr->width);
3294 png_debug1(3, "height = %lu,", png_ptr->height);
3295 png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
3296 png_debug1(3, "num_rows = %lu,", png_ptr->num_rows);
3297 png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
Glenn Randers-Pehrson79134c62009-02-14 10:32:18 -06003298 png_debug1(3, "irowbytes = %lu", png_ptr->irowbytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05003299
Guy Schalnate5a37791996-06-05 15:50:50 -05003300 png_ptr->flags |= PNG_FLAG_ROW_INIT;
Guy Schalnat0d580581995-07-20 02:43:20 -05003301}
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06003302#endif /* PNG_READ_SUPPORTED */