blob: 4a09c7f60a0792d0b2d1493e0a5ee875d33a8096 [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-Pehrsonf46918d2006-06-02 05:31:20 -05004 * Last changed in libpng 1.4.0 June 1, 2006
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06006 * Copyright (c) 1998-2006 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-Pehrson17218292006-04-20 07:20:46 -050015#include "pngintrn.h"
Guy Schalnat0d580581995-07-20 02:43:20 -050016
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060017#if defined(PNG_READ_SUPPORTED)
18
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{
Glenn Randers-Pehrsone826d7e2006-07-03 00:21:58 -050022#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050023 png_uint_32 i = png_get_uint_32(buf);
Glenn Randers-Pehrsone826d7e2006-07-03 00:21:58 -050024#else
25 /* Avoid an extra function call by inlining the result. */
26 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
27 ((png_uint_32)(*(buf + 1)) << 16) +
28 ((png_uint_32)(*(buf + 2)) << 8) +
29 (png_uint_32)(*(buf + 3));
30#endif
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050031 if (i > PNG_UINT_31_MAX)
Glenn Randers-Pehrsonc3d51c12006-03-02 07:23:18 -060032 png_error(png_ptr, "PNG unsigned integer out of range.");
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050033 return (i);
34}
Andreas Dilger47a0c421997-05-16 02:46:07 -050035#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050036/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060037png_uint_32 PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060038png_get_uint_32(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050039{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050040 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
Guy Schalnat0d580581995-07-20 02:43:20 -050041 ((png_uint_32)(*(buf + 1)) << 16) +
42 ((png_uint_32)(*(buf + 2)) << 8) +
43 (png_uint_32)(*(buf + 3));
44
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060045 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050046}
47
Glenn Randers-Pehrson86dc9812006-05-10 07:27:44 -050048#if defined(PNG_GET_INT_32_SUPPORTED)
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050049/* Grab a signed 32-bit integer from a buffer in big-endian format. The
Andreas Dilger47a0c421997-05-16 02:46:07 -050050 * data is stored in the PNG file in two's complement format, and it is
51 * assumed that the machine format for signed integers is the same. */
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060052png_int_32 PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050053png_get_int_32(png_bytep buf)
54{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050055 png_int_32 i = ((png_int_32)(*buf) << 24) +
Andreas Dilger47a0c421997-05-16 02:46:07 -050056 ((png_int_32)(*(buf + 1)) << 16) +
57 ((png_int_32)(*(buf + 2)) << 8) +
58 (png_int_32)(*(buf + 3));
59
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060060 return (i);
Andreas Dilger47a0c421997-05-16 02:46:07 -050061}
Glenn Randers-Pehrson86dc9812006-05-10 07:27:44 -050062#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -050063
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050064/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060065png_uint_16 PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060066png_get_uint_16(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050067{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050068 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060069 (png_uint_16)(*(buf + 1)));
Guy Schalnat0d580581995-07-20 02:43:20 -050070
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060071 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050072}
Andreas Dilger47a0c421997-05-16 02:46:07 -050073#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -050074
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060075/* Read data, and (optionally) run it through the CRC. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050076void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -050077png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
Guy Schalnat0d580581995-07-20 02:43:20 -050078{
Guy Schalnat6d764711995-12-19 03:22:19 -060079 png_read_data(png_ptr, buf, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -050080 png_calculate_crc(png_ptr, buf, length);
Guy Schalnat0d580581995-07-20 02:43:20 -050081}
82
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060083/* Optionally skip data and then check the CRC. Depending on whether we
84 are reading a ancillary or critical chunk, and how the program has set
Andreas Dilger47a0c421997-05-16 02:46:07 -050085 things up, we may calculate the CRC on the data and print a message.
86 Returns '1' if there was a CRC error, '0' otherwise. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050087int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060088png_crc_finish(png_structp png_ptr, png_uint_32 skip)
Guy Schalnat0d580581995-07-20 02:43:20 -050089{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050090 png_size_t i;
91 png_size_t istop = png_ptr->zbuf_size;
Guy Schalnat0d580581995-07-20 02:43:20 -050092
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -050093 for (i = (png_size_t)skip; i > istop; i -= istop)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060094 {
Andreas Dilger47a0c421997-05-16 02:46:07 -050095 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
Guy Schalnat0d580581995-07-20 02:43:20 -050096 }
97 if (i)
98 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050099 png_crc_read(png_ptr, png_ptr->zbuf, i);
Guy Schalnat0d580581995-07-20 02:43:20 -0500100 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600101
Andreas Dilger47a0c421997-05-16 02:46:07 -0500102 if (png_crc_error(png_ptr))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600103 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600104 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600105 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
106 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600107 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600108 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600109 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600110 }
111 else
112 {
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500113 png_chunk_benign_error(png_ptr, "CRC error");
114 return (0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600115 }
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600116 return (1);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600117 }
118
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600119 return (0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500120}
121
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600122/* Compare the CRC stored in the PNG file with that calculated by libpng from
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600123 the data it has read thus far. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500124int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600125png_crc_error(png_structp png_ptr)
126{
127 png_byte crc_bytes[4];
128 png_uint_32 crc;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500129 int need_crc = 1;
130
131 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
132 {
133 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
134 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
135 need_crc = 0;
136 }
137 else /* critical */
138 {
139 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
140 need_crc = 0;
141 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600142
143 png_read_data(png_ptr, crc_bytes, 4);
144
Andreas Dilger47a0c421997-05-16 02:46:07 -0500145 if (need_crc)
146 {
147 crc = png_get_uint_32(crc_bytes);
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600148 return ((int)(crc != png_ptr->crc));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500149 }
150 else
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600151 return (0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600152}
153
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600154#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500155 defined(PNG_READ_iCCP_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600156/*
157 * Decompress trailing data in a chunk. The assumption is that chunkdata
158 * points at an allocated area holding the contents of a chunk with a
159 * trailing compressed part. What we get back is an allocated area
160 * holding the original prefix part and an uncompressed version of the
161 * trailing part (the malloc area passed in is freed).
162 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500163png_charp /* PRIVATE */
164png_decompress_chunk(png_structp png_ptr, int comp_type,
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600165 png_charp chunkdata, png_size_t chunklength,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600166 png_size_t prefix_size, png_size_t *newlength)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600167{
168 static char msg[] = "Error decoding compressed text";
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500169 png_charp text;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600170 png_size_t text_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600171
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600172 if (comp_type == PNG_COMPRESSION_TYPE_BASE)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600173 {
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500174 int ret = Z_OK;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600175 png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
176 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
177 png_ptr->zstream.next_out = png_ptr->zbuf;
178 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
179
180 text_size = 0;
181 text = NULL;
182
183 while (png_ptr->zstream.avail_in)
184 {
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500185 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600186 if (ret != Z_OK && ret != Z_STREAM_END)
187 {
188 if (png_ptr->zstream.msg != NULL)
189 png_warning(png_ptr, png_ptr->zstream.msg);
190 else
191 png_warning(png_ptr, msg);
192 inflateReset(&png_ptr->zstream);
193 png_ptr->zstream.avail_in = 0;
194
195 if (text == NULL)
196 {
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500197 text_size = prefix_size + png_sizeof(msg) + 1;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500198 text = (png_charp)png_malloc_warn(png_ptr, text_size);
199 if (text == NULL)
200 {
201 png_free(png_ptr,chunkdata);
202 png_error(png_ptr,"Not enough memory to decompress chunk");
203 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500204 png_memcpy(text, chunkdata, prefix_size);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600205 }
206
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500207 text[text_size - 1] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600208
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500209 /* Copy what we can of the error message into the text chunk */
210 text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500211 text_size = png_sizeof(msg) > text_size ? text_size :
212 png_sizeof(msg);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500213 png_memcpy(text + prefix_size, msg, text_size + 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600214 break;
215 }
216 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
217 {
218 if (text == NULL)
219 {
220 text_size = prefix_size +
221 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500222 text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
223 if (text == NULL)
224 {
225 png_free(png_ptr,chunkdata);
226 png_error(png_ptr,"Not enough memory to decompress chunk.");
227 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500228 png_memcpy(text + prefix_size, png_ptr->zbuf,
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500229 text_size - prefix_size);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500230 png_memcpy(text, chunkdata, prefix_size);
231 *(text + text_size) = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600232 }
233 else
234 {
235 png_charp tmp;
236
237 tmp = text;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500238 text = (png_charp)png_malloc_warn(png_ptr,
239 (png_uint_32)(text_size +
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600240 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500241 if (text == NULL)
242 {
243 png_free(png_ptr, tmp);
244 png_free(png_ptr, chunkdata);
245 png_error(png_ptr,"Not enough memory to decompress chunk..");
246 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600247 png_memcpy(text, tmp, text_size);
248 png_free(png_ptr, tmp);
249 png_memcpy(text + text_size, png_ptr->zbuf,
250 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
251 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
252 *(text + text_size) = 0x00;
253 }
254 if (ret == Z_STREAM_END)
255 break;
256 else
257 {
258 png_ptr->zstream.next_out = png_ptr->zbuf;
259 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
260 }
261 }
262 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500263 if (ret != Z_STREAM_END)
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500264 {
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500265#ifndef PNG_NO_STDIO
Glenn Randers-Pehrsonf46918d2006-06-02 05:31:20 -0500266 char umsg[52];
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500267
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500268 if (ret == Z_BUF_ERROR)
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500269 png_sprintf(umsg,"Buffer error in compressed datastream in %s chunk",
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500270 png_ptr->chunk_name);
271 else if (ret == Z_DATA_ERROR)
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500272 png_sprintf(umsg,"Data error in compressed datastream in %s chunk",
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500273 png_ptr->chunk_name);
274 else
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500275 png_sprintf(umsg,"Incomplete compressed datastream in %s chunk",
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500276 png_ptr->chunk_name);
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500277 png_warning(png_ptr, umsg);
278#else
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500279 png_warning(png_ptr,
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500280 "Incomplete compressed datastream in chunk other than IDAT");
281#endif
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -0600282 text_size=prefix_size;
283 if (text == NULL)
284 {
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500285 text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
286 if (text == NULL)
287 {
288 png_free(png_ptr, chunkdata);
289 png_error(png_ptr,"Not enough memory for text.");
290 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500291 png_memcpy(text, chunkdata, prefix_size);
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -0600292 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500293 *(text + text_size) = 0x00;
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500294 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600295
296 inflateReset(&png_ptr->zstream);
297 png_ptr->zstream.avail_in = 0;
298
299 png_free(png_ptr, chunkdata);
300 chunkdata = text;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600301 *newlength=text_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600302 }
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600303 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600304 {
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500305#ifndef PNG_NO_STDIO
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600306 char umsg[50];
307
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500308 png_sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600309 png_warning(png_ptr, umsg);
310#else
311 png_warning(png_ptr, "Unknown zTXt compression type");
312#endif
313
Glenn Randers-Pehrsonf05f8032000-12-23 14:27:39 -0600314 *(chunkdata + prefix_size) = 0x00;
315 *newlength=prefix_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600316 }
317
318 return chunkdata;
319}
320#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600321
Guy Schalnat0d580581995-07-20 02:43:20 -0500322/* read and check the IDHR chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500323void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600324png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500325{
326 png_byte buf[13];
327 png_uint_32 width, height;
328 int bit_depth, color_type, compression_type, filter_type;
329 int interlace_type;
330
Andreas Dilger47a0c421997-05-16 02:46:07 -0500331 png_debug(1, "in png_handle_IHDR\n");
332
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600333 if (png_ptr->mode & PNG_HAVE_IHDR)
Guy Schalnate5a37791996-06-05 15:50:50 -0500334 png_error(png_ptr, "Out of place IHDR");
335
Guy Schalnat0d580581995-07-20 02:43:20 -0500336 /* check the length */
337 if (length != 13)
Guy Schalnat6d764711995-12-19 03:22:19 -0600338 png_error(png_ptr, "Invalid IHDR chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -0500339
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600340 png_ptr->mode |= PNG_HAVE_IHDR;
341
Guy Schalnat0d580581995-07-20 02:43:20 -0500342 png_crc_read(png_ptr, buf, 13);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600343 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500344
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500345 width = png_get_uint_31(png_ptr, buf);
346 height = png_get_uint_31(png_ptr, buf + 4);
Guy Schalnat0d580581995-07-20 02:43:20 -0500347 bit_depth = buf[8];
348 color_type = buf[9];
349 compression_type = buf[10];
350 filter_type = buf[11];
351 interlace_type = buf[12];
352
Guy Schalnat0d580581995-07-20 02:43:20 -0500353 /* set internal variables */
354 png_ptr->width = width;
355 png_ptr->height = height;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600356 png_ptr->bit_depth = (png_byte)bit_depth;
357 png_ptr->interlaced = (png_byte)interlace_type;
358 png_ptr->color_type = (png_byte)color_type;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500359#if defined(PNG_MNG_FEATURES_SUPPORTED)
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -0600360 png_ptr->filter_type = (png_byte)filter_type;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500361#endif
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500362 png_ptr->compression_type = (png_byte)compression_type;
Guy Schalnat0d580581995-07-20 02:43:20 -0500363
364 /* find number of channels */
365 switch (png_ptr->color_type)
366 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500367 case PNG_COLOR_TYPE_GRAY:
368 case PNG_COLOR_TYPE_PALETTE:
Guy Schalnat0d580581995-07-20 02:43:20 -0500369 png_ptr->channels = 1;
370 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500371 case PNG_COLOR_TYPE_RGB:
Guy Schalnat0d580581995-07-20 02:43:20 -0500372 png_ptr->channels = 3;
373 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500374 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500375 png_ptr->channels = 2;
376 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500377 case PNG_COLOR_TYPE_RGB_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500378 png_ptr->channels = 4;
379 break;
380 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600381
Guy Schalnat0d580581995-07-20 02:43:20 -0500382 /* set up other useful info */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600383 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600384 png_ptr->channels);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500385 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500386 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
387 png_debug1(3,"channels = %d\n", png_ptr->channels);
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500388 png_debug1(3,"rowbytes = %lu\n", (unsigned long) png_ptr->rowbytes);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500389 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
390 color_type, interlace_type, compression_type, filter_type);
Guy Schalnat0d580581995-07-20 02:43:20 -0500391}
392
393/* read and check the palette */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500394void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600395png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500396{
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600397 png_color palette[PNG_MAX_PALETTE_LENGTH];
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600398 int num, i;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500399#ifndef PNG_NO_POINTER_INDEXING
400 png_colorp pal_ptr;
401#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500402
Andreas Dilger47a0c421997-05-16 02:46:07 -0500403 png_debug(1, "in png_handle_PLTE\n");
404
Guy Schalnate5a37791996-06-05 15:50:50 -0500405 if (!(png_ptr->mode & PNG_HAVE_IHDR))
406 png_error(png_ptr, "Missing IHDR before PLTE");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600407 else if (png_ptr->mode & PNG_HAVE_IDAT)
408 {
409 png_warning(png_ptr, "Invalid PLTE after IDAT");
410 png_crc_finish(png_ptr, length);
411 return;
412 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500413 else if (png_ptr->mode & PNG_HAVE_PLTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600414 png_error(png_ptr, "Duplicate PLTE chunk");
415
416 png_ptr->mode |= PNG_HAVE_PLTE;
Guy Schalnate5a37791996-06-05 15:50:50 -0500417
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500418 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
419 {
420 png_warning(png_ptr,
421 "Ignoring PLTE chunk in grayscale PNG");
422 png_crc_finish(png_ptr, length);
423 return;
424 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500425#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
426 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
427 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600428 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500429 return;
430 }
431#endif
432
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600433 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
Guy Schalnate5a37791996-06-05 15:50:50 -0500434 {
435 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
436 {
437 png_warning(png_ptr, "Invalid palette chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600438 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500439 return;
440 }
441 else
442 {
443 png_error(png_ptr, "Invalid palette chunk");
444 }
445 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500446
447 num = (int)length / 3;
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500448
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500449#ifndef PNG_NO_POINTER_INDEXING
450 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
451 {
452 png_byte buf[3];
453
454 png_crc_read(png_ptr, buf, 3);
455 pal_ptr->red = buf[0];
456 pal_ptr->green = buf[1];
457 pal_ptr->blue = buf[2];
458 }
459#else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600460 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500461 {
462 png_byte buf[3];
463
464 png_crc_read(png_ptr, buf, 3);
465 /* don't depend upon png_color being any order */
466 palette[i].red = buf[0];
467 palette[i].green = buf[1];
468 palette[i].blue = buf[2];
469 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500470#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600471
472 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
473 whatever the normal CRC configuration tells us. However, if we
474 have an RGB image, the PLTE can be considered ancillary, so
475 we will act as though it is. */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600476#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600477 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600478#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600479 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500480 png_crc_finish(png_ptr, 0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600481 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600482#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600483 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
484 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600485 /* If we don't want to use the data from an ancillary chunk,
486 we have two options: an error abort, or a warning and we
487 ignore the data in this chunk (which should be OK, since
488 it's considered ancillary for a RGB or RGBA image). */
489 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
490 {
491 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
492 {
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500493 png_chunk_benign_error(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600494 }
495 else
496 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600497 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600498 return;
499 }
500 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500501 /* Otherwise, we (optionally) emit a warning and use the chunk. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600502 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
503 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600504 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600505 }
506 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600507#endif
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500508
Andreas Dilger47a0c421997-05-16 02:46:07 -0500509 png_set_PLTE(png_ptr, info_ptr, palette, num);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500510
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500511#if defined(PNG_READ_tRNS_SUPPORTED)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500512 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
513 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600514 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500515 {
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500516 if (png_ptr->num_trans > (png_uint_16)num)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500517 {
518 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500519 png_ptr->num_trans = (png_uint_16)num;
520 }
521 if (info_ptr->num_trans > (png_uint_16)num)
522 {
523 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
524 info_ptr->num_trans = (png_uint_16)num;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500525 }
526 }
527 }
528#endif
529
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600530}
Guy Schalnate5a37791996-06-05 15:50:50 -0500531
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500532void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600533png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
534{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500535 png_debug(1, "in png_handle_IEND\n");
536
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600537 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
538 {
539 png_error(png_ptr, "No image in file");
540 }
541
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600542 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600543
544 if (length != 0)
545 {
546 png_warning(png_ptr, "Incorrect IEND chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600547 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500548 png_crc_finish(png_ptr, length);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500549
550 if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
551 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500552}
553
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500554#if defined(PNG_READ_gAMA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500555void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600556png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500557{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600558 png_fixed_point igamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600559#ifdef PNG_FLOATING_POINT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500560 float file_gamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600561#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500562 png_byte buf[4];
563
Andreas Dilger47a0c421997-05-16 02:46:07 -0500564 png_debug(1, "in png_handle_gAMA\n");
565
Guy Schalnate5a37791996-06-05 15:50:50 -0500566 if (!(png_ptr->mode & PNG_HAVE_IHDR))
567 png_error(png_ptr, "Missing IHDR before gAMA");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600568 else if (png_ptr->mode & PNG_HAVE_IDAT)
569 {
570 png_warning(png_ptr, "Invalid gAMA after IDAT");
571 png_crc_finish(png_ptr, length);
572 return;
573 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500574 else if (png_ptr->mode & PNG_HAVE_PLTE)
575 /* Should be an error, but we can cope with it */
576 png_warning(png_ptr, "Out of place gAMA chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600577
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500578 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600579#if defined(PNG_READ_sRGB_SUPPORTED)
580 && !(info_ptr->valid & PNG_INFO_sRGB)
581#endif
582 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600583 {
584 png_warning(png_ptr, "Duplicate gAMA chunk");
585 png_crc_finish(png_ptr, length);
586 return;
587 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500588
Guy Schalnat0d580581995-07-20 02:43:20 -0500589 if (length != 4)
590 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600591 png_warning(png_ptr, "Incorrect gAMA chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600592 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500593 return;
594 }
595
596 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600597 if (png_crc_finish(png_ptr, 0))
598 return;
599
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600600 igamma = (png_fixed_point)png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500601 /* check for zero gamma */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500602 if (igamma == 0)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500603 {
604 png_warning(png_ptr,
605 "Ignoring gAMA chunk with gamma=0");
606 return;
607 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500608
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600609#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600610 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500611 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600612 {
613 png_warning(png_ptr,
614 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500615#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600616 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600617#endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600618 return;
619 }
620#endif /* PNG_READ_sRGB_SUPPORTED */
621
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600622#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600623 file_gamma = (float)igamma / (float)100000.0;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600624# ifdef PNG_READ_GAMMA_SUPPORTED
625 png_ptr->gamma = file_gamma;
626# endif
627 png_set_gAMA(png_ptr, info_ptr, file_gamma);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600628#endif
629#ifdef PNG_FIXED_POINT_SUPPORTED
630 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
631#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500632}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500633#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500634
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500635#if defined(PNG_READ_sBIT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500636void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600637png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500638{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500639 png_size_t truelen;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600640 png_byte buf[4];
Guy Schalnat69b14481996-01-10 02:56:49 -0600641
Andreas Dilger47a0c421997-05-16 02:46:07 -0500642 png_debug(1, "in png_handle_sBIT\n");
643
Guy Schalnat69b14481996-01-10 02:56:49 -0600644 buf[0] = buf[1] = buf[2] = buf[3] = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500645
Guy Schalnate5a37791996-06-05 15:50:50 -0500646 if (!(png_ptr->mode & PNG_HAVE_IHDR))
647 png_error(png_ptr, "Missing IHDR before sBIT");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600648 else if (png_ptr->mode & PNG_HAVE_IDAT)
649 {
650 png_warning(png_ptr, "Invalid sBIT after IDAT");
651 png_crc_finish(png_ptr, length);
652 return;
653 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500654 else if (png_ptr->mode & PNG_HAVE_PLTE)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600655 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500656 /* Should be an error, but we can cope with it */
657 png_warning(png_ptr, "Out of place sBIT chunk");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600658 }
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500659 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600660 {
661 png_warning(png_ptr, "Duplicate sBIT chunk");
662 png_crc_finish(png_ptr, length);
663 return;
664 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500665
Guy Schalnat0d580581995-07-20 02:43:20 -0500666 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600667 truelen = 3;
Guy Schalnat0d580581995-07-20 02:43:20 -0500668 else
Andreas Dilger47a0c421997-05-16 02:46:07 -0500669 truelen = (png_size_t)png_ptr->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500670
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500671 if (length != truelen || length > 4)
Guy Schalnat0d580581995-07-20 02:43:20 -0500672 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600673 png_warning(png_ptr, "Incorrect sBIT chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600674 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600675 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500676 }
677
Andreas Dilger47a0c421997-05-16 02:46:07 -0500678 png_crc_read(png_ptr, buf, truelen);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600679 if (png_crc_finish(png_ptr, 0))
680 return;
681
Guy Schalnat0d580581995-07-20 02:43:20 -0500682 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
683 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600684 png_ptr->sig_bit.red = buf[0];
685 png_ptr->sig_bit.green = buf[1];
686 png_ptr->sig_bit.blue = buf[2];
687 png_ptr->sig_bit.alpha = buf[3];
Guy Schalnat0d580581995-07-20 02:43:20 -0500688 }
689 else
690 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600691 png_ptr->sig_bit.gray = buf[0];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600692 png_ptr->sig_bit.red = buf[0];
693 png_ptr->sig_bit.green = buf[0];
694 png_ptr->sig_bit.blue = buf[0];
Guy Schalnat6d764711995-12-19 03:22:19 -0600695 png_ptr->sig_bit.alpha = buf[1];
Guy Schalnat0d580581995-07-20 02:43:20 -0500696 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500697 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
Guy Schalnat0d580581995-07-20 02:43:20 -0500698}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500699#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500700
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500701#if defined(PNG_READ_cHRM_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500702void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600703png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500704{
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500705 png_byte buf[32];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600706#ifdef PNG_FLOATING_POINT_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -0500707 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 -0600708#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600709 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 -0600710 int_y_green, int_x_blue, int_y_blue;
Guy Schalnat0d580581995-07-20 02:43:20 -0500711
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600712 png_uint_32 uint_x, uint_y;
713
Andreas Dilger47a0c421997-05-16 02:46:07 -0500714 png_debug(1, "in png_handle_cHRM\n");
715
Guy Schalnate5a37791996-06-05 15:50:50 -0500716 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600717 png_error(png_ptr, "Missing IHDR before cHRM");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600718 else if (png_ptr->mode & PNG_HAVE_IDAT)
719 {
720 png_warning(png_ptr, "Invalid cHRM after IDAT");
721 png_crc_finish(png_ptr, length);
722 return;
723 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500724 else if (png_ptr->mode & PNG_HAVE_PLTE)
725 /* Should be an error, but we can cope with it */
726 png_warning(png_ptr, "Missing PLTE before cHRM");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600727
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500728 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600729#if defined(PNG_READ_sRGB_SUPPORTED)
730 && !(info_ptr->valid & PNG_INFO_sRGB)
731#endif
732 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600733 {
734 png_warning(png_ptr, "Duplicate cHRM chunk");
735 png_crc_finish(png_ptr, length);
736 return;
737 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500738
Guy Schalnat0d580581995-07-20 02:43:20 -0500739 if (length != 32)
740 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600741 png_warning(png_ptr, "Incorrect cHRM chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600742 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600743 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500744 }
745
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500746 png_crc_read(png_ptr, buf, 32);
747 if (png_crc_finish(png_ptr, 0))
748 return;
749
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600750 uint_x = png_get_uint_32(buf);
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500751 uint_y = png_get_uint_32(buf + 4);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600752 if (uint_x > 80000L || uint_y > 80000L ||
753 uint_x + uint_y > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600754 {
755 png_warning(png_ptr, "Invalid cHRM white point");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600756 return;
757 }
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600758 int_x_white = (png_fixed_point)uint_x;
759 int_y_white = (png_fixed_point)uint_y;
Guy Schalnat0d580581995-07-20 02:43:20 -0500760
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500761 uint_x = png_get_uint_32(buf + 8);
762 uint_y = png_get_uint_32(buf + 12);
Glenn Randers-Pehrsonddfebd32006-02-22 09:19:25 -0600763 if (uint_x + uint_y > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600764 {
765 png_warning(png_ptr, "Invalid cHRM red point");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600766 return;
767 }
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600768 int_x_red = (png_fixed_point)uint_x;
769 int_y_red = (png_fixed_point)uint_y;
Guy Schalnat0d580581995-07-20 02:43:20 -0500770
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500771 uint_x = png_get_uint_32(buf + 16);
772 uint_y = png_get_uint_32(buf + 20);
Glenn Randers-Pehrsonddfebd32006-02-22 09:19:25 -0600773 if (uint_x + uint_y > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600774 {
775 png_warning(png_ptr, "Invalid cHRM green point");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600776 return;
777 }
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600778 int_x_green = (png_fixed_point)uint_x;
779 int_y_green = (png_fixed_point)uint_y;
Guy Schalnat0d580581995-07-20 02:43:20 -0500780
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500781 uint_x = png_get_uint_32(buf + 24);
782 uint_y = png_get_uint_32(buf + 28);
Glenn Randers-Pehrsonddfebd32006-02-22 09:19:25 -0600783 if (uint_x + uint_y > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600784 {
785 png_warning(png_ptr, "Invalid cHRM blue point");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600786 return;
787 }
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600788 int_x_blue = (png_fixed_point)uint_x;
789 int_y_blue = (png_fixed_point)uint_y;
790
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600791#ifdef PNG_FLOATING_POINT_SUPPORTED
792 white_x = (float)int_x_white / (float)100000.0;
793 white_y = (float)int_y_white / (float)100000.0;
794 red_x = (float)int_x_red / (float)100000.0;
795 red_y = (float)int_y_red / (float)100000.0;
796 green_x = (float)int_x_green / (float)100000.0;
797 green_y = (float)int_y_green / (float)100000.0;
798 blue_x = (float)int_x_blue / (float)100000.0;
799 blue_y = (float)int_y_blue / (float)100000.0;
800#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600801
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600802#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500803 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600804 {
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500805 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
806 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
807 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
808 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
809 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
810 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
811 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
812 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600813 {
814 png_warning(png_ptr,
815 "Ignoring incorrect cHRM value when sRGB is also present");
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500816#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600817#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600818 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
819 white_x, white_y, red_x, red_y);
820 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
821 green_x, green_y, blue_x, blue_y);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600822#else
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600823 fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600824 int_x_white, int_y_white, int_x_red, int_y_red);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600825 fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600826 int_x_green, int_y_green, int_x_blue, int_y_blue);
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600827#endif
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500828#endif /* PNG_NO_CONSOLE_IO */
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600829 }
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600830 return;
831 }
832#endif /* PNG_READ_sRGB_SUPPORTED */
833
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600834#ifdef PNG_FLOATING_POINT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500835 png_set_cHRM(png_ptr, info_ptr,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600836 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600837#endif
838#ifdef PNG_FIXED_POINT_SUPPORTED
839 png_set_cHRM_fixed(png_ptr, info_ptr,
840 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
841 int_y_green, int_x_blue, int_y_blue);
842#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500843}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500844#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500845
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600846#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500847void /* PRIVATE */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600848png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
849{
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600850 int intent;
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600851 png_byte buf[1];
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600852
853 png_debug(1, "in png_handle_sRGB\n");
854
855 if (!(png_ptr->mode & PNG_HAVE_IHDR))
856 png_error(png_ptr, "Missing IHDR before sRGB");
857 else if (png_ptr->mode & PNG_HAVE_IDAT)
858 {
859 png_warning(png_ptr, "Invalid sRGB after IDAT");
860 png_crc_finish(png_ptr, length);
861 return;
862 }
863 else if (png_ptr->mode & PNG_HAVE_PLTE)
864 /* Should be an error, but we can cope with it */
865 png_warning(png_ptr, "Out of place sRGB chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600866
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500867 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600868 {
869 png_warning(png_ptr, "Duplicate sRGB chunk");
870 png_crc_finish(png_ptr, length);
871 return;
872 }
873
874 if (length != 1)
875 {
876 png_warning(png_ptr, "Incorrect sRGB chunk length");
877 png_crc_finish(png_ptr, length);
878 return;
879 }
880
881 png_crc_read(png_ptr, buf, 1);
882 if (png_crc_finish(png_ptr, 0))
883 return;
884
885 intent = buf[0];
886 /* check for bad intent */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600887 if (intent >= PNG_sRGB_INTENT_LAST)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600888 {
889 png_warning(png_ptr, "Unknown sRGB intent");
890 return;
891 }
892
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600893#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600894 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600895 {
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500896 png_fixed_point igamma;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600897#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500898 igamma=info_ptr->int_gamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600899#else
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600900# ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500901 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600902# endif
903#endif
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500904 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600905 {
906 png_warning(png_ptr,
907 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500908#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600909# ifdef PNG_FIXED_POINT_SUPPORTED
910 fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
911# else
912# ifdef PNG_FLOATING_POINT_SUPPORTED
913 fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
914# endif
915# endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600916#endif
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600917 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600918 }
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600919#endif /* PNG_READ_gAMA_SUPPORTED */
920
921#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500922#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600923 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500924 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
925 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
926 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
927 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
928 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
929 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
930 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
931 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600932 {
933 png_warning(png_ptr,
934 "Ignoring incorrect cHRM value when sRGB is also present");
935 }
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500936#endif /* PNG_FIXED_POINT_SUPPORTED */
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600937#endif /* PNG_READ_cHRM_SUPPORTED */
938
939 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
940}
941#endif /* PNG_READ_sRGB_SUPPORTED */
942
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600943#if defined(PNG_READ_iCCP_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500944void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600945png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
946/* Note: this does not properly handle chunks that are > 64K under DOS */
947{
948 png_charp chunkdata;
949 png_byte compression_type;
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600950 png_bytep pC;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600951 png_charp profile;
952 png_uint_32 skip = 0;
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500953 png_uint_32 profile_size, profile_length;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600954 png_size_t slength, prefix_length, data_length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600955
956 png_debug(1, "in png_handle_iCCP\n");
957
958 if (!(png_ptr->mode & PNG_HAVE_IHDR))
959 png_error(png_ptr, "Missing IHDR before iCCP");
960 else if (png_ptr->mode & PNG_HAVE_IDAT)
961 {
962 png_warning(png_ptr, "Invalid iCCP after IDAT");
963 png_crc_finish(png_ptr, length);
964 return;
965 }
966 else if (png_ptr->mode & PNG_HAVE_PLTE)
967 /* Should be an error, but we can cope with it */
968 png_warning(png_ptr, "Out of place iCCP chunk");
969
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500970 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600971 {
972 png_warning(png_ptr, "Duplicate iCCP chunk");
973 png_crc_finish(png_ptr, length);
974 return;
975 }
976
977#ifdef PNG_MAX_MALLOC_64K
978 if (length > (png_uint_32)65535L)
979 {
980 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
981 skip = length - (png_uint_32)65535L;
982 length = (png_uint_32)65535L;
983 }
984#endif
985
986 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
987 slength = (png_size_t)length;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500988 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600989
990 if (png_crc_finish(png_ptr, skip))
991 {
992 png_free(png_ptr, chunkdata);
993 return;
994 }
995
996 chunkdata[slength] = 0x00;
997
998 for (profile = chunkdata; *profile; profile++)
999 /* empty loop to find end of name */ ;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001000
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001001 ++profile;
1002
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001003 /* there should be at least one zero (the compression type byte)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001004 following the separator, and we should be on it */
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001005 if ( profile >= chunkdata + slength)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001006 {
1007 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001008 png_warning(png_ptr, "Malformed iCCP chunk");
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001009 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001010 }
1011
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001012 /* compression_type should always be zero */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001013 compression_type = *profile++;
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001014 if (compression_type)
1015 {
1016 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1017 compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1018 wrote nonzero) */
1019 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001020
1021 prefix_length = profile - chunkdata;
1022 chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001023 slength, prefix_length, &data_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001024
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001025 profile_length = data_length - prefix_length;
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06001026
Glenn Randers-Pehrsondb3b88d2001-12-04 06:30:43 -06001027 if ( prefix_length > data_length || profile_length < 4)
Glenn Randers-Pehrsonb1828932001-06-23 08:03:17 -05001028 {
1029 png_free(png_ptr, chunkdata);
1030 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1031 return;
1032 }
1033
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06001034 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -06001035 pC = (png_bytep)(chunkdata+prefix_length);
1036 profile_size = ((*(pC ))<<24) |
1037 ((*(pC+1))<<16) |
1038 ((*(pC+2))<< 8) |
1039 ((*(pC+3)) );
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001040
1041 if(profile_size < profile_length)
1042 profile_length = profile_size;
1043
1044 if(profile_size > profile_length)
1045 {
Glenn Randers-Pehrsonb1828932001-06-23 08:03:17 -05001046 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrsonc3d51c12006-03-02 07:23:18 -06001047 png_warning(png_ptr, "Ignoring truncated iCCP profile.");
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001048 return;
1049 }
1050
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001051 png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001052 chunkdata + prefix_length, profile_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001053 png_free(png_ptr, chunkdata);
1054}
1055#endif /* PNG_READ_iCCP_SUPPORTED */
1056
1057#if defined(PNG_READ_sPLT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001058void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001059png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1060/* Note: this does not properly handle chunks that are > 64K under DOS */
1061{
1062 png_bytep chunkdata;
1063 png_bytep entry_start;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001064 png_sPLT_t new_palette;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001065#ifdef PNG_NO_POINTER_INDEXING
1066 png_sPLT_entryp pp;
1067#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001068 int data_length, entry_size, i;
1069 png_uint_32 skip = 0;
1070 png_size_t slength;
1071
1072 png_debug(1, "in png_handle_sPLT\n");
1073
1074 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1075 png_error(png_ptr, "Missing IHDR before sPLT");
1076 else if (png_ptr->mode & PNG_HAVE_IDAT)
1077 {
1078 png_warning(png_ptr, "Invalid sPLT after IDAT");
1079 png_crc_finish(png_ptr, length);
1080 return;
1081 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001082
1083#ifdef PNG_MAX_MALLOC_64K
1084 if (length > (png_uint_32)65535L)
1085 {
1086 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1087 skip = length - (png_uint_32)65535L;
1088 length = (png_uint_32)65535L;
1089 }
1090#endif
1091
1092 chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001093 slength = (png_size_t)length;
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001094 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001095
1096 if (png_crc_finish(png_ptr, skip))
1097 {
1098 png_free(png_ptr, chunkdata);
1099 return;
1100 }
1101
1102 chunkdata[slength] = 0x00;
1103
1104 for (entry_start = chunkdata; *entry_start; entry_start++)
1105 /* empty loop to find end of name */ ;
1106 ++entry_start;
1107
1108 /* a sample depth should follow the separator, and we should be on it */
1109 if (entry_start > chunkdata + slength)
1110 {
1111 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001112 png_warning(png_ptr, "malformed sPLT chunk");
1113 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001114 }
1115
1116 new_palette.depth = *entry_start++;
1117 entry_size = (new_palette.depth == 8 ? 6 : 10);
1118 data_length = (slength - (entry_start - chunkdata));
1119
1120 /* integrity-check the data length */
1121 if (data_length % entry_size)
1122 {
1123 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001124 png_warning(png_ptr, "sPLT chunk has bad length");
1125 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001126 }
1127
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06001128 new_palette.nentries = (png_int_32) ( data_length / entry_size);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001129 if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX /
1130 png_sizeof(png_sPLT_entry)))
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001131 {
1132 png_warning(png_ptr, "sPLT chunk too long");
1133 return;
1134 }
1135 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1136 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1137 if (new_palette.entries == NULL)
1138 {
1139 png_warning(png_ptr, "sPLT chunk requires too much memory");
1140 return;
1141 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001142
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001143#ifndef PNG_NO_POINTER_INDEXING
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001144 for (i = 0; i < new_palette.nentries; i++)
1145 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001146 png_sPLT_entryp pp = new_palette.entries + i;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001147
1148 if (new_palette.depth == 8)
1149 {
1150 pp->red = *entry_start++;
1151 pp->green = *entry_start++;
1152 pp->blue = *entry_start++;
1153 pp->alpha = *entry_start++;
1154 }
1155 else
1156 {
1157 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1158 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1159 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1160 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1161 }
1162 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1163 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001164#else
1165 pp = new_palette.entries;
1166 for (i = 0; i < new_palette.nentries; i++)
1167 {
1168
1169 if (new_palette.depth == 8)
1170 {
1171 pp[i].red = *entry_start++;
1172 pp[i].green = *entry_start++;
1173 pp[i].blue = *entry_start++;
1174 pp[i].alpha = *entry_start++;
1175 }
1176 else
1177 {
1178 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1179 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1180 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1181 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1182 }
1183 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1184 }
1185#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001186
1187 /* discard all chunk data except the name and stash that */
1188 new_palette.name = (png_charp)chunkdata;
1189
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001190 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001191
1192 png_free(png_ptr, chunkdata);
1193 png_free(png_ptr, new_palette.entries);
1194}
1195#endif /* PNG_READ_sPLT_SUPPORTED */
1196
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001197#if defined(PNG_READ_tRNS_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001198void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001199png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001200{
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001201 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001202
Andreas Dilger47a0c421997-05-16 02:46:07 -05001203 png_debug(1, "in png_handle_tRNS\n");
1204
Guy Schalnate5a37791996-06-05 15:50:50 -05001205 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1206 png_error(png_ptr, "Missing IHDR before tRNS");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001207 else if (png_ptr->mode & PNG_HAVE_IDAT)
1208 {
1209 png_warning(png_ptr, "Invalid tRNS after IDAT");
1210 png_crc_finish(png_ptr, length);
1211 return;
1212 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001213 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001214 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001215 png_warning(png_ptr, "Duplicate tRNS chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001216 png_crc_finish(png_ptr, length);
1217 return;
1218 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001219
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001220 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001221 {
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001222 png_byte buf[2];
Guy Schalnat0d580581995-07-20 02:43:20 -05001223
1224 if (length != 2)
1225 {
Guy Schalnat69b14481996-01-10 02:56:49 -06001226 png_warning(png_ptr, "Incorrect tRNS chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001227 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001228 return;
1229 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001230
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001231 png_crc_read(png_ptr, buf, 2);
1232 png_ptr->num_trans = 1;
1233 png_ptr->trans_values.gray = png_get_uint_16(buf);
1234 }
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001235 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1236 {
1237 png_byte buf[6];
1238
1239 if (length != 6)
1240 {
1241 png_warning(png_ptr, "Incorrect tRNS chunk length");
1242 png_crc_finish(png_ptr, length);
1243 return;
1244 }
1245 png_crc_read(png_ptr, buf, (png_size_t)length);
1246 png_ptr->num_trans = 1;
1247 png_ptr->trans_values.red = png_get_uint_16(buf);
1248 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1249 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1250 }
1251 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1252 {
1253 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1254 {
1255 /* Should be an error, but we can cope with it. */
1256 png_warning(png_ptr, "Missing PLTE before tRNS");
1257 }
1258 if (length > (png_uint_32)png_ptr->num_palette ||
1259 length > PNG_MAX_PALETTE_LENGTH)
1260 {
1261 png_warning(png_ptr, "Incorrect tRNS chunk length");
1262 png_crc_finish(png_ptr, length);
1263 return;
1264 }
1265 if (length == 0)
1266 {
1267 png_warning(png_ptr, "Zero length tRNS chunk");
1268 png_crc_finish(png_ptr, length);
1269 return;
1270 }
1271 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1272 png_ptr->num_trans = (png_uint_16)length;
1273 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001274 else
Guy Schalnate5a37791996-06-05 15:50:50 -05001275 {
1276 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001277 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001278 return;
1279 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001280
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001281 if (png_crc_finish(png_ptr, 0))
1282 return;
1283
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001284 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
Guy Schalnat0d580581995-07-20 02:43:20 -05001285 &(png_ptr->trans_values));
1286}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001287#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001288
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001289#if defined(PNG_READ_bKGD_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001290void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001291png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001292{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001293 png_size_t truelen;
Guy Schalnat0d580581995-07-20 02:43:20 -05001294 png_byte buf[6];
1295
Andreas Dilger47a0c421997-05-16 02:46:07 -05001296 png_debug(1, "in png_handle_bKGD\n");
1297
Guy Schalnate5a37791996-06-05 15:50:50 -05001298 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1299 png_error(png_ptr, "Missing IHDR before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001300 else if (png_ptr->mode & PNG_HAVE_IDAT)
1301 {
1302 png_warning(png_ptr, "Invalid bKGD after IDAT");
1303 png_crc_finish(png_ptr, length);
1304 return;
1305 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001306 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1307 !(png_ptr->mode & PNG_HAVE_PLTE))
1308 {
1309 png_warning(png_ptr, "Missing PLTE before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001310 png_crc_finish(png_ptr, length);
1311 return;
1312 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001313 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001314 {
1315 png_warning(png_ptr, "Duplicate bKGD chunk");
1316 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001317 return;
1318 }
1319
Guy Schalnat0d580581995-07-20 02:43:20 -05001320 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1321 truelen = 1;
1322 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1323 truelen = 6;
1324 else
1325 truelen = 2;
1326
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001327 if (length != truelen)
Guy Schalnat0d580581995-07-20 02:43:20 -05001328 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001329 png_warning(png_ptr, "Incorrect bKGD chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001330 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001331 return;
1332 }
1333
Andreas Dilger47a0c421997-05-16 02:46:07 -05001334 png_crc_read(png_ptr, buf, truelen);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001335 if (png_crc_finish(png_ptr, 0))
1336 return;
1337
Guy Schalnate5a37791996-06-05 15:50:50 -05001338 /* We convert the index value into RGB components so that we can allow
1339 * arbitrary RGB values for background when we have transparency, and
1340 * so it is easy to determine the RGB values of the background color
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001341 * from the info_ptr struct. */
Guy Schalnat0d580581995-07-20 02:43:20 -05001342 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnate5a37791996-06-05 15:50:50 -05001343 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001344 png_ptr->background.index = buf[0];
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001345 if(info_ptr->num_palette)
1346 {
1347 if(buf[0] > info_ptr->num_palette)
1348 {
1349 png_warning(png_ptr, "Incorrect bKGD chunk index value");
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001350 return;
1351 }
1352 png_ptr->background.red =
1353 (png_uint_16)png_ptr->palette[buf[0]].red;
1354 png_ptr->background.green =
1355 (png_uint_16)png_ptr->palette[buf[0]].green;
1356 png_ptr->background.blue =
1357 (png_uint_16)png_ptr->palette[buf[0]].blue;
1358 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001359 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001360 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
Guy Schalnate5a37791996-06-05 15:50:50 -05001361 {
1362 png_ptr->background.red =
1363 png_ptr->background.green =
1364 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -05001365 png_ptr->background.gray = png_get_uint_16(buf);
Guy Schalnate5a37791996-06-05 15:50:50 -05001366 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001367 else
1368 {
1369 png_ptr->background.red = png_get_uint_16(buf);
1370 png_ptr->background.green = png_get_uint_16(buf + 2);
1371 png_ptr->background.blue = png_get_uint_16(buf + 4);
1372 }
1373
Andreas Dilger47a0c421997-05-16 02:46:07 -05001374 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
Guy Schalnat0d580581995-07-20 02:43:20 -05001375}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001376#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001377
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001378#if defined(PNG_READ_hIST_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001379void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001380png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001381{
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001382 unsigned int num, i;
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001383 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
Guy Schalnat0d580581995-07-20 02:43:20 -05001384
Andreas Dilger47a0c421997-05-16 02:46:07 -05001385 png_debug(1, "in png_handle_hIST\n");
1386
Guy Schalnate5a37791996-06-05 15:50:50 -05001387 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1388 png_error(png_ptr, "Missing IHDR before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001389 else if (png_ptr->mode & PNG_HAVE_IDAT)
1390 {
1391 png_warning(png_ptr, "Invalid hIST after IDAT");
1392 png_crc_finish(png_ptr, length);
1393 return;
1394 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001395 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1396 {
1397 png_warning(png_ptr, "Missing PLTE before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001398 png_crc_finish(png_ptr, length);
1399 return;
1400 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001401 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001402 {
1403 png_warning(png_ptr, "Duplicate hIST chunk");
1404 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001405 return;
1406 }
1407
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001408 num = length / 2 ;
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001409 if (num != (unsigned int) png_ptr->num_palette || num >
1410 (unsigned int) PNG_MAX_PALETTE_LENGTH)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001411 {
1412 png_warning(png_ptr, "Incorrect hIST chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001413 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001414 return;
1415 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001416
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001417 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001418 {
1419 png_byte buf[2];
1420
1421 png_crc_read(png_ptr, buf, 2);
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001422 readbuf[i] = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001423 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001424
1425 if (png_crc_finish(png_ptr, 0))
1426 return;
1427
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001428 png_set_hIST(png_ptr, info_ptr, readbuf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001429}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001430#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001431
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001432#if defined(PNG_READ_pHYs_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001433void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001434png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001435{
1436 png_byte buf[9];
1437 png_uint_32 res_x, res_y;
1438 int unit_type;
1439
Andreas Dilger47a0c421997-05-16 02:46:07 -05001440 png_debug(1, "in png_handle_pHYs\n");
1441
Guy Schalnate5a37791996-06-05 15:50:50 -05001442 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001443 png_error(png_ptr, "Missing IHDR before pHYs");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001444 else if (png_ptr->mode & PNG_HAVE_IDAT)
1445 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001446 png_warning(png_ptr, "Invalid pHYs after IDAT");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001447 png_crc_finish(png_ptr, length);
1448 return;
1449 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001450 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001451 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001452 png_warning(png_ptr, "Duplicate pHYs chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001453 png_crc_finish(png_ptr, length);
1454 return;
1455 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001456
Guy Schalnat0d580581995-07-20 02:43:20 -05001457 if (length != 9)
1458 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001459 png_warning(png_ptr, "Incorrect pHYs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001460 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001461 return;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001462 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001463
1464 png_crc_read(png_ptr, buf, 9);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001465 if (png_crc_finish(png_ptr, 0))
1466 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001467
1468 res_x = png_get_uint_32(buf);
1469 res_y = png_get_uint_32(buf + 4);
1470 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001471 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
Guy Schalnat0d580581995-07-20 02:43:20 -05001472}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001473#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001474
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001475#if defined(PNG_READ_oFFs_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001476void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001477png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001478{
1479 png_byte buf[9];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001480 png_int_32 offset_x, offset_y;
Guy Schalnat0d580581995-07-20 02:43:20 -05001481 int unit_type;
1482
Andreas Dilger47a0c421997-05-16 02:46:07 -05001483 png_debug(1, "in png_handle_oFFs\n");
1484
Guy Schalnate5a37791996-06-05 15:50:50 -05001485 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1486 png_error(png_ptr, "Missing IHDR before oFFs");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001487 else if (png_ptr->mode & PNG_HAVE_IDAT)
1488 {
1489 png_warning(png_ptr, "Invalid oFFs after IDAT");
1490 png_crc_finish(png_ptr, length);
1491 return;
1492 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001493 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001494 {
1495 png_warning(png_ptr, "Duplicate oFFs chunk");
1496 png_crc_finish(png_ptr, length);
1497 return;
1498 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001499
Guy Schalnat0d580581995-07-20 02:43:20 -05001500 if (length != 9)
1501 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001502 png_warning(png_ptr, "Incorrect oFFs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001503 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001504 return;
1505 }
1506
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001507 png_crc_read(png_ptr, buf, 9);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001508 if (png_crc_finish(png_ptr, 0))
1509 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001510
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001511 offset_x = png_get_int_32(buf);
1512 offset_y = png_get_int_32(buf + 4);
Guy Schalnat0d580581995-07-20 02:43:20 -05001513 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001514 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1515}
1516#endif
1517
1518#if defined(PNG_READ_pCAL_SUPPORTED)
Glenn Randers-Pehrsonff9c9472000-07-11 07:12:36 -05001519/* read the pCAL chunk (described in the PNG Extensions document) */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001520void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001521png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1522{
1523 png_charp purpose;
1524 png_int_32 X0, X1;
1525 png_byte type, nparams;
1526 png_charp buf, units, endptr;
1527 png_charpp params;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001528 png_size_t slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001529 int i;
1530
1531 png_debug(1, "in png_handle_pCAL\n");
1532
1533 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1534 png_error(png_ptr, "Missing IHDR before pCAL");
1535 else if (png_ptr->mode & PNG_HAVE_IDAT)
1536 {
1537 png_warning(png_ptr, "Invalid pCAL after IDAT");
1538 png_crc_finish(png_ptr, length);
1539 return;
1540 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001541 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
Andreas Dilger47a0c421997-05-16 02:46:07 -05001542 {
1543 png_warning(png_ptr, "Duplicate pCAL chunk");
1544 png_crc_finish(png_ptr, length);
1545 return;
1546 }
1547
Glenn Randers-Pehrson4766a242000-07-17 06:17:09 -05001548 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -05001549 (unsigned long) (length + 1));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001550 purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
1551 if (purpose == NULL)
1552 {
1553 png_warning(png_ptr, "No memory for pCAL purpose.");
1554 return;
1555 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001556 slength = (png_size_t)length;
1557 png_crc_read(png_ptr, (png_bytep)purpose, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001558
1559 if (png_crc_finish(png_ptr, 0))
1560 {
1561 png_free(png_ptr, purpose);
1562 return;
1563 }
1564
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001565 purpose[slength] = 0x00; /* null terminate the last string */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001566
1567 png_debug(3, "Finding end of pCAL purpose string\n");
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001568 for (buf = purpose; *buf; buf++)
Glenn Randers-Pehrsond12aa501998-03-13 07:39:39 -06001569 /* empty loop */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001570
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001571 endptr = purpose + slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001572
1573 /* We need to have at least 12 bytes after the purpose string
1574 in order to get the parameter information. */
1575 if (endptr <= buf + 12)
1576 {
1577 png_warning(png_ptr, "Invalid pCAL data");
1578 png_free(png_ptr, purpose);
1579 return;
1580 }
1581
1582 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1583 X0 = png_get_int_32((png_bytep)buf+1);
1584 X1 = png_get_int_32((png_bytep)buf+5);
1585 type = buf[9];
1586 nparams = buf[10];
1587 units = buf + 11;
1588
1589 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1590 /* Check that we have the right number of parameters for known
1591 equation types. */
1592 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1593 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1594 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1595 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1596 {
1597 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1598 png_free(png_ptr, purpose);
1599 return;
1600 }
1601 else if (type >= PNG_EQUATION_LAST)
1602 {
1603 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1604 }
1605
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001606 for (buf = units; *buf; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001607 /* Empty loop to move past the units string. */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001608
1609 png_debug(3, "Allocating pCAL parameters array\n");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001610 params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001611 *png_sizeof(png_charp))) ;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001612 if (params == NULL)
1613 {
1614 png_free(png_ptr, purpose);
1615 png_warning(png_ptr, "No memory for pCAL params.");
1616 return;
1617 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001618
1619 /* Get pointers to the start of each parameter string. */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001620 for (i = 0; i < (int)nparams; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001621 {
1622 buf++; /* Skip the null string terminator from previous parameter. */
1623
1624 png_debug1(3, "Reading pCAL parameter %d\n", i);
Glenn Randers-Pehrsond12aa501998-03-13 07:39:39 -06001625 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001626 /* Empty loop to move past each parameter string */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001627
1628 /* Make sure we haven't run out of data yet */
1629 if (buf > endptr)
1630 {
1631 png_warning(png_ptr, "Invalid pCAL data");
1632 png_free(png_ptr, purpose);
1633 png_free(png_ptr, params);
1634 return;
1635 }
1636 }
1637
1638 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1639 units, params);
1640
1641 png_free(png_ptr, purpose);
1642 png_free(png_ptr, params);
Guy Schalnat0d580581995-07-20 02:43:20 -05001643}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001644#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001645
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001646#if defined(PNG_READ_sCAL_SUPPORTED)
1647/* read the sCAL chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001648void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001649png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1650{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001651 png_charp buffer, ep;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001652#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001653 double width, height;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001654 png_charp vp;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001655#else
1656#ifdef PNG_FIXED_POINT_SUPPORTED
1657 png_charp swidth, sheight;
1658#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001659#endif
1660 png_size_t slength;
1661
1662 png_debug(1, "in png_handle_sCAL\n");
1663
1664 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1665 png_error(png_ptr, "Missing IHDR before sCAL");
1666 else if (png_ptr->mode & PNG_HAVE_IDAT)
1667 {
1668 png_warning(png_ptr, "Invalid sCAL after IDAT");
1669 png_crc_finish(png_ptr, length);
1670 return;
1671 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001672 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001673 {
1674 png_warning(png_ptr, "Duplicate sCAL chunk");
1675 png_crc_finish(png_ptr, length);
1676 return;
1677 }
1678
Glenn Randers-Pehrson4766a242000-07-17 06:17:09 -05001679 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -05001680 (unsigned long) (length + 1));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001681 buffer = (png_charp)png_malloc_warn(png_ptr, length + 1);
1682 if (buffer == NULL)
1683 {
1684 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
1685 return;
1686 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001687 slength = (png_size_t)length;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001688 png_crc_read(png_ptr, (png_bytep)buffer, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001689
1690 if (png_crc_finish(png_ptr, 0))
1691 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001692 png_free(png_ptr, buffer);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001693 return;
1694 }
1695
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001696 buffer[slength] = 0x00; /* null terminate the last string */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001697
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001698 ep = buffer + 1; /* skip unit byte */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001699
1700#ifdef PNG_FLOATING_POINT_SUPPORTED
1701 width = strtod(ep, &vp);
1702 if (*vp)
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001703 {
1704 png_warning(png_ptr, "malformed width string in sCAL chunk");
1705 return;
1706 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001707#else
1708#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001709 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1710 if (swidth == NULL)
1711 {
1712 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
1713 return;
1714 }
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001715 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001716#endif
1717#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001718
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001719 for (ep = buffer; *ep; ep++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001720 /* empty loop */ ;
1721 ep++;
1722
1723#ifdef PNG_FLOATING_POINT_SUPPORTED
1724 height = strtod(ep, &vp);
1725 if (*vp)
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001726 {
1727 png_warning(png_ptr, "malformed height string in sCAL chunk");
1728 return;
1729 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001730#else
1731#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001732 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1733 if (swidth == NULL)
1734 {
1735 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
1736 return;
1737 }
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001738 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001739#endif
1740#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001741
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001742 if (buffer + slength < ep
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001743#ifdef PNG_FLOATING_POINT_SUPPORTED
1744 || width <= 0. || height <= 0.
1745#endif
1746 )
1747 {
1748 png_warning(png_ptr, "Invalid sCAL data");
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001749 png_free(png_ptr, buffer);
1750#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001751 png_free(png_ptr, swidth);
1752 png_free(png_ptr, sheight);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001753#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001754 return;
1755 }
1756
1757
1758#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001759 png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1760#else
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001761#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001762 png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1763#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001764#endif
1765
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001766 png_free(png_ptr, buffer);
1767#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1768 png_free(png_ptr, swidth);
1769 png_free(png_ptr, sheight);
1770#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001771}
1772#endif
1773
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001774#if defined(PNG_READ_tIME_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001775void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001776png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001777{
1778 png_byte buf[7];
1779 png_time mod_time;
1780
Andreas Dilger47a0c421997-05-16 02:46:07 -05001781 png_debug(1, "in png_handle_tIME\n");
1782
Guy Schalnate5a37791996-06-05 15:50:50 -05001783 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001784 png_error(png_ptr, "Out of place tIME chunk");
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001785 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001786 {
1787 png_warning(png_ptr, "Duplicate tIME chunk");
1788 png_crc_finish(png_ptr, length);
1789 return;
1790 }
1791
1792 if (png_ptr->mode & PNG_HAVE_IDAT)
1793 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnate5a37791996-06-05 15:50:50 -05001794
Guy Schalnat0d580581995-07-20 02:43:20 -05001795 if (length != 7)
1796 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001797 png_warning(png_ptr, "Incorrect tIME chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001798 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001799 return;
1800 }
1801
1802 png_crc_read(png_ptr, buf, 7);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001803 if (png_crc_finish(png_ptr, 0))
1804 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001805
1806 mod_time.second = buf[6];
1807 mod_time.minute = buf[5];
1808 mod_time.hour = buf[4];
1809 mod_time.day = buf[3];
1810 mod_time.month = buf[2];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001811 mod_time.year = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001812
Andreas Dilger47a0c421997-05-16 02:46:07 -05001813 png_set_tIME(png_ptr, info_ptr, &mod_time);
Guy Schalnat0d580581995-07-20 02:43:20 -05001814}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001815#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001816
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001817#if defined(PNG_READ_tEXt_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001818/* Note: this does not properly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001819void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001820png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001821{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001822 png_textp text_ptr;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001823 png_charp key;
Guy Schalnat6d764711995-12-19 03:22:19 -06001824 png_charp text;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001825 png_uint_32 skip = 0;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001826 png_size_t slength;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001827 int ret;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001828
1829 png_debug(1, "in png_handle_tEXt\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05001830
Guy Schalnate5a37791996-06-05 15:50:50 -05001831 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1832 png_error(png_ptr, "Missing IHDR before tEXt");
1833
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001834 if (png_ptr->mode & PNG_HAVE_IDAT)
1835 png_ptr->mode |= PNG_AFTER_IDAT;
1836
Andreas Dilger47a0c421997-05-16 02:46:07 -05001837#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001838 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001839 {
1840 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001841 skip = length - (png_uint_32)65535L;
1842 length = (png_uint_32)65535L;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001843 }
1844#endif
1845
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001846 key = (png_charp)png_malloc_warn(png_ptr, length + 1);
1847 if (key == NULL)
1848 {
1849 png_warning(png_ptr, "No memory to process text chunk.");
1850 return;
1851 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001852 slength = (png_size_t)length;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001853 png_crc_read(png_ptr, (png_bytep)key, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001854
1855 if (png_crc_finish(png_ptr, skip))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001856 {
1857 png_free(png_ptr, key);
1858 return;
1859 }
1860
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001861 key[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05001862
1863 for (text = key; *text; text++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001864 /* empty loop to find end of key */ ;
Guy Schalnat0d580581995-07-20 02:43:20 -05001865
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001866 if (text != key + slength)
Guy Schalnat0d580581995-07-20 02:43:20 -05001867 text++;
1868
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001869 text_ptr = (png_textp)png_malloc_warn(png_ptr,
1870 (png_uint_32)png_sizeof(png_text));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001871 if (text_ptr == NULL)
1872 {
1873 png_warning(png_ptr, "Not enough memory to process text chunk.");
1874 png_free(png_ptr, key);
1875 return;
1876 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001877 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1878 text_ptr->key = key;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001879#ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001880 text_ptr->lang = NULL;
1881 text_ptr->lang_key = NULL;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001882 text_ptr->itxt_length = 0;
1883#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001884 text_ptr->text = text;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001885 text_ptr->text_length = png_strlen(text);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001886
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001887 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001888
Glenn Randers-Pehrsone1eff582001-04-14 20:15:41 -05001889 png_free(png_ptr, key);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001890 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001891 if (ret)
1892 png_warning(png_ptr, "Insufficient memory to process text chunk.");
Guy Schalnat0d580581995-07-20 02:43:20 -05001893}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001894#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001895
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001896#if defined(PNG_READ_zTXt_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001897/* note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001898void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001899png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001900{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001901 png_textp text_ptr;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001902 png_charp chunkdata;
Guy Schalnat6d764711995-12-19 03:22:19 -06001903 png_charp text;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001904 int comp_type;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001905 int ret;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001906 png_size_t slength, prefix_len, data_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001907
1908 png_debug(1, "in png_handle_zTXt\n");
Guy Schalnate5a37791996-06-05 15:50:50 -05001909 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1910 png_error(png_ptr, "Missing IHDR before zTXt");
1911
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001912 if (png_ptr->mode & PNG_HAVE_IDAT)
1913 png_ptr->mode |= PNG_AFTER_IDAT;
1914
Andreas Dilger47a0c421997-05-16 02:46:07 -05001915#ifdef PNG_MAX_MALLOC_64K
1916 /* We will no doubt have problems with chunks even half this size, but
1917 there is no hard and fast rule to tell us where to stop. */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001918 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001919 {
1920 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1921 png_crc_finish(png_ptr, length);
1922 return;
1923 }
1924#endif
1925
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001926 chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1927 if (chunkdata == NULL)
1928 {
1929 png_warning(png_ptr,"Out of memory processing zTXt chunk.");
1930 return;
1931 }
1932 slength = (png_size_t)length;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001933 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001934 if (png_crc_finish(png_ptr, 0))
1935 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001936 png_free(png_ptr, chunkdata);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001937 return;
1938 }
1939
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001940 chunkdata[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05001941
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001942 for (text = chunkdata; *text; text++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001943 /* empty loop */ ;
1944
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001945 /* zTXt must have some text after the chunkdataword */
1946 if (text == chunkdata + slength)
Guy Schalnat0d580581995-07-20 02:43:20 -05001947 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001948 comp_type = PNG_TEXT_COMPRESSION_NONE;
Guy Schalnat69b14481996-01-10 02:56:49 -06001949 png_warning(png_ptr, "Zero length zTXt chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -05001950 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001951 else
Guy Schalnat0d580581995-07-20 02:43:20 -05001952 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001953 comp_type = *(++text);
Glenn Randers-Pehrsonf05f8032000-12-23 14:27:39 -06001954 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
1955 {
1956 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
1957 comp_type = PNG_TEXT_COMPRESSION_zTXt;
1958 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001959 text++; /* skip the compression_method byte */
Guy Schalnat0d580581995-07-20 02:43:20 -05001960 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001961 prefix_len = text - chunkdata;
Guy Schalnat0d580581995-07-20 02:43:20 -05001962
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001963 chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001964 (png_size_t)length, prefix_len, &data_len);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001965
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001966 text_ptr = (png_textp)png_malloc_warn(png_ptr,
1967 (png_uint_32)png_sizeof(png_text));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001968 if (text_ptr == NULL)
1969 {
1970 png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
1971 png_free(png_ptr, chunkdata);
1972 return;
1973 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001974 text_ptr->compression = comp_type;
1975 text_ptr->key = chunkdata;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001976#ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001977 text_ptr->lang = NULL;
1978 text_ptr->lang_key = NULL;
1979 text_ptr->itxt_length = 0;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001980#endif
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001981 text_ptr->text = chunkdata + prefix_len;
1982 text_ptr->text_length = data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001983
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001984 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001985
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001986 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001987 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001988 if (ret)
1989 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001990}
1991#endif
1992
1993#if defined(PNG_READ_iTXt_SUPPORTED)
1994/* note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001995void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001996png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1997{
1998 png_textp text_ptr;
1999 png_charp chunkdata;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002000 png_charp key, lang, text, lang_key;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002001 int comp_flag;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002002 int comp_type = 0;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002003 int ret;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002004 png_size_t slength, prefix_len, data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002005
2006 png_debug(1, "in png_handle_iTXt\n");
2007
2008 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2009 png_error(png_ptr, "Missing IHDR before iTXt");
2010
2011 if (png_ptr->mode & PNG_HAVE_IDAT)
2012 png_ptr->mode |= PNG_AFTER_IDAT;
2013
2014#ifdef PNG_MAX_MALLOC_64K
2015 /* We will no doubt have problems with chunks even half this size, but
2016 there is no hard and fast rule to tell us where to stop. */
2017 if (length > (png_uint_32)65535L)
2018 {
2019 png_warning(png_ptr,"iTXt chunk too large to fit in memory");
2020 png_crc_finish(png_ptr, length);
2021 return;
2022 }
2023#endif
2024
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002025 chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2026 if (chunkdata == NULL)
2027 {
2028 png_warning(png_ptr, "No memory to process iTXt chunk.");
2029 return;
2030 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002031 slength = (png_size_t)length;
2032 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002033 if (png_crc_finish(png_ptr, 0))
2034 {
2035 png_free(png_ptr, chunkdata);
2036 return;
2037 }
2038
2039 chunkdata[slength] = 0x00;
2040
2041 for (lang = chunkdata; *lang; lang++)
2042 /* empty loop */ ;
2043 lang++; /* skip NUL separator */
2044
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002045 /* iTXt must have a language tag (possibly empty), two compression bytes,
2046 translated keyword (possibly empty), and possibly some text after the
2047 keyword */
2048
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002049 if (lang >= chunkdata + slength)
2050 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002051 comp_flag = PNG_TEXT_COMPRESSION_NONE;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002052 png_warning(png_ptr, "Zero length iTXt chunk");
2053 }
2054 else
2055 {
2056 comp_flag = *lang++;
2057 comp_type = *lang++;
2058 }
2059
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002060 for (lang_key = lang; *lang_key; lang_key++)
2061 /* empty loop */ ;
2062 lang_key++; /* skip NUL separator */
2063
2064 for (text = lang_key; *text; text++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002065 /* empty loop */ ;
2066 text++; /* skip NUL separator */
2067
2068 prefix_len = text - chunkdata;
2069
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002070 key=chunkdata;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002071 if (comp_flag)
2072 chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002073 (size_t)length, prefix_len, &data_len);
2074 else
2075 data_len=png_strlen(chunkdata + prefix_len);
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05002076 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2077 (png_uint_32)png_sizeof(png_text));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002078 if (text_ptr == NULL)
2079 {
2080 png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
2081 png_free(png_ptr, chunkdata);
2082 return;
2083 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002084 text_ptr->compression = (int)comp_flag + 1;
2085 text_ptr->lang_key = chunkdata+(lang_key-key);
2086 text_ptr->lang = chunkdata+(lang-key);
2087 text_ptr->itxt_length = data_len;
2088 text_ptr->text_length = 0;
2089 text_ptr->key = chunkdata;
2090 text_ptr->text = chunkdata + prefix_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002091
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002092 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002093
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002094 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002095 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002096 if (ret)
2097 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002098}
2099#endif
2100
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002101/* This function is called when we haven't found a handler for a
2102 chunk. If there isn't a problem with the chunk itself (ie bad
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002103 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2104 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2105 case it will be saved away to be written out later. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002106void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002107png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2108{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002109 png_uint_32 skip = 0;
2110
Andreas Dilger47a0c421997-05-16 02:46:07 -05002111 png_debug(1, "in png_handle_unknown\n");
2112
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002113 if (png_ptr->mode & PNG_HAVE_IDAT)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002114 {
2115#ifdef PNG_USE_LOCAL_ARRAYS
2116 PNG_IDAT;
2117#endif
2118 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2119 png_ptr->mode |= PNG_AFTER_IDAT;
2120 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002121
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002122 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
2123
2124 if (!(png_ptr->chunk_name[0] & 0x20))
2125 {
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05002126#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002127 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -05002128 PNG_HANDLE_CHUNK_ALWAYS
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002129#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002130 && png_ptr->read_user_chunk_fn == NULL
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002131#endif
2132 )
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05002133#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002134 png_chunk_error(png_ptr, "unknown critical chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002135 }
2136
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002137#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06002138 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
2139 (png_ptr->read_user_chunk_fn != NULL))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002140 {
2141 png_unknown_chunk chunk;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002142
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002143#ifdef PNG_MAX_MALLOC_64K
2144 if (length > (png_uint_32)65535L)
2145 {
2146 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2147 skip = length - (png_uint_32)65535L;
2148 length = (png_uint_32)65535L;
2149 }
2150#endif
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002151 png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002152 chunk.data = (png_bytep)png_malloc(png_ptr, length);
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002153 chunk.size = (png_size_t)length;
2154 png_crc_read(png_ptr, (png_bytep)chunk.data, length);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002155#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002156 if(png_ptr->read_user_chunk_fn != NULL)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002157 {
2158 /* callback to user unknown chunk handler */
2159 if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
2160 {
2161 if (!(png_ptr->chunk_name[0] & 0x20))
2162 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -05002163 PNG_HANDLE_CHUNK_ALWAYS)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002164 {
2165 png_free(png_ptr, chunk.data);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002166 png_chunk_error(png_ptr, "unknown critical chunk");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002167 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002168 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2169 }
2170 }
2171 else
2172#endif
2173 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002174 png_free(png_ptr, chunk.data);
2175 }
2176 else
2177#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002178 skip = length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002179
2180 png_crc_finish(png_ptr, skip);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002181
2182#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002183 if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
2184 return;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002185#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002186}
2187
2188/* This function is called to verify that a chunk name is valid.
2189 This function can't have the "critical chunk check" incorporated
Andreas Dilger47a0c421997-05-16 02:46:07 -05002190 into it, since in the future we will need to be able to call user
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002191 functions to handle unknown critical chunks after we check that
2192 the chunk name itself is valid. */
Andreas Dilger47a0c421997-05-16 02:46:07 -05002193
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05002194#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
Andreas Dilger47a0c421997-05-16 02:46:07 -05002195
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002196void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002197png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2198{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002199 png_debug(1, "in png_check_chunk_name\n");
2200 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2201 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002202 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06002203 png_chunk_error(png_ptr, "invalid chunk type");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002204 }
2205}
2206
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002207/* Combines the row recently read in with the existing pixels in the
2208 row. This routine takes care of alpha and transparency if requested.
Guy Schalnat0d580581995-07-20 02:43:20 -05002209 This routine also handles the two methods of progressive display
2210 of interlaced images, depending on the mask value.
2211 The mask value describes which pixels are to be combined with
2212 the row. The pattern always repeats every 8 pixels, so just 8
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002213 bits are needed. A one indicates the pixel is to be combined,
Guy Schalnat0d580581995-07-20 02:43:20 -05002214 a zero indicates the pixel is to be skipped. This is in addition
2215 to any alpha or transparency value associated with the pixel. If
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002216 you want all pixels to be combined, pass 0xff (255) in mask. */
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002217#ifndef PNG_HAVE_MMX_COMBINE_ROW
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002218void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002219png_combine_row(png_structp png_ptr, png_bytep row, int mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002220{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002221 png_debug(1,"in png_combine_row\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05002222 if (mask == 0xff)
2223 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002224 png_memcpy(row, png_ptr->row_buf + 1,
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002225 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
Guy Schalnat0d580581995-07-20 02:43:20 -05002226 }
2227 else
2228 {
2229 switch (png_ptr->row_info.pixel_depth)
2230 {
2231 case 1:
2232 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002233 png_bytep sp = png_ptr->row_buf + 1;
2234 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002235 int s_inc, s_start, s_end;
2236 int m = 0x80;
2237 int shift;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002238 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002239 png_uint_32 row_width = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05002240
Andreas Dilger47a0c421997-05-16 02:46:07 -05002241#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2242 if (png_ptr->transformations & PNG_PACKSWAP)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002243 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002244 s_start = 0;
2245 s_end = 7;
2246 s_inc = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002247 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002248 else
2249#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002250 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002251 s_start = 7;
2252 s_end = 0;
2253 s_inc = -1;
2254 }
2255
2256 shift = s_start;
2257
2258 for (i = 0; i < row_width; i++)
2259 {
2260 if (m & mask)
2261 {
2262 int value;
2263
2264 value = (*sp >> shift) & 0x01;
2265 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2266 *dp |= (png_byte)(value << shift);
2267 }
2268
2269 if (shift == s_end)
2270 {
2271 shift = s_start;
2272 sp++;
2273 dp++;
2274 }
2275 else
2276 shift += s_inc;
2277
2278 if (m == 1)
2279 m = 0x80;
2280 else
2281 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002282 }
2283 break;
2284 }
2285 case 2:
2286 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002287 png_bytep sp = png_ptr->row_buf + 1;
2288 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002289 int s_start, s_end, s_inc;
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002290 int m = 0x80;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002291 int shift;
2292 png_uint_32 i;
2293 png_uint_32 row_width = png_ptr->width;
2294 int value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002295
Andreas Dilger47a0c421997-05-16 02:46:07 -05002296#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2297 if (png_ptr->transformations & PNG_PACKSWAP)
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002298 {
2299 s_start = 0;
2300 s_end = 6;
2301 s_inc = 2;
2302 }
2303 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002304#endif
2305 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002306 s_start = 6;
2307 s_end = 0;
2308 s_inc = -2;
2309 }
2310
2311 shift = s_start;
2312
2313 for (i = 0; i < row_width; i++)
2314 {
2315 if (m & mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002316 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002317 value = (*sp >> shift) & 0x03;
2318 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2319 *dp |= (png_byte)(value << shift);
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002320 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002321
2322 if (shift == s_end)
2323 {
2324 shift = s_start;
2325 sp++;
2326 dp++;
2327 }
2328 else
2329 shift += s_inc;
2330 if (m == 1)
2331 m = 0x80;
2332 else
2333 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002334 }
2335 break;
2336 }
2337 case 4:
2338 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002339 png_bytep sp = png_ptr->row_buf + 1;
2340 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002341 int s_start, s_end, s_inc;
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002342 int m = 0x80;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002343 int shift;
2344 png_uint_32 i;
2345 png_uint_32 row_width = png_ptr->width;
2346 int value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002347
Andreas Dilger47a0c421997-05-16 02:46:07 -05002348#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2349 if (png_ptr->transformations & PNG_PACKSWAP)
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002350 {
2351 s_start = 0;
2352 s_end = 4;
2353 s_inc = 4;
2354 }
2355 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002356#endif
2357 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002358 s_start = 4;
2359 s_end = 0;
2360 s_inc = -4;
2361 }
2362 shift = s_start;
2363
2364 for (i = 0; i < row_width; i++)
2365 {
2366 if (m & mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002367 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002368 value = (*sp >> shift) & 0xf;
2369 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2370 *dp |= (png_byte)(value << shift);
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002371 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002372
2373 if (shift == s_end)
2374 {
2375 shift = s_start;
2376 sp++;
2377 dp++;
2378 }
2379 else
2380 shift += s_inc;
2381 if (m == 1)
2382 m = 0x80;
2383 else
2384 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002385 }
2386 break;
2387 }
2388 default:
2389 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002390 png_bytep sp = png_ptr->row_buf + 1;
2391 png_bytep dp = row;
2392 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2393 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002394 png_uint_32 row_width = png_ptr->width;
2395 png_byte m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05002396
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002397
2398 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002399 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002400 if (m & mask)
2401 {
2402 png_memcpy(dp, sp, pixel_bytes);
2403 }
2404
2405 sp += pixel_bytes;
2406 dp += pixel_bytes;
2407
2408 if (m == 1)
2409 m = 0x80;
2410 else
2411 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002412 }
2413 break;
2414 }
2415 }
2416 }
2417}
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002418#endif /* !PNG_HAVE_MMX_COMBINE_ROW */
Guy Schalnat0d580581995-07-20 02:43:20 -05002419
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002420#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002421#ifndef PNG_HAVE_MMX_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002422/* OLD pre-1.0.9 interface:
2423void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2424 png_uint_32 transformations)
2425 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002426void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002427png_do_read_interlace(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002428{
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002429 png_row_infop row_info = &(png_ptr->row_info);
2430 png_bytep row = png_ptr->row_buf + 1;
2431 int pass = png_ptr->pass;
2432 png_uint_32 transformations = png_ptr->transformations;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002433#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002434 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002435 /* offset to next interlace block */
2436 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002437#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002438
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002439 png_debug(1,"in png_do_read_interlace (stock C version)\n");
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002440 if (row != NULL && row_info != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002441 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002442 png_uint_32 final_width;
2443
2444 final_width = row_info->width * png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05002445
2446 switch (row_info->pixel_depth)
2447 {
2448 case 1:
2449 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002450 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2451 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002452 int sshift, dshift;
2453 int s_start, s_end, s_inc;
2454 int jstop = png_pass_inc[pass];
2455 png_byte v;
Guy Schalnat0d580581995-07-20 02:43:20 -05002456 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002457 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -05002458
Andreas Dilger47a0c421997-05-16 02:46:07 -05002459#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2460 if (transformations & PNG_PACKSWAP)
2461 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002462 sshift = (int)((row_info->width + 7) & 0x07);
2463 dshift = (int)((final_width + 7) & 0x07);
2464 s_start = 7;
2465 s_end = 0;
2466 s_inc = -1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002467 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002468 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002469#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002470 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002471 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2472 dshift = 7 - (int)((final_width + 7) & 0x07);
2473 s_start = 0;
2474 s_end = 7;
2475 s_inc = 1;
2476 }
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002477
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002478 for (i = 0; i < row_info->width; i++)
2479 {
2480 v = (png_byte)((*sp >> sshift) & 0x01);
2481 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002482 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002483 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2484 *dp |= (png_byte)(v << dshift);
2485 if (dshift == s_end)
2486 {
2487 dshift = s_start;
2488 dp--;
2489 }
2490 else
2491 dshift += s_inc;
2492 }
2493 if (sshift == s_end)
2494 {
2495 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002496 sp--;
2497 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002498 else
2499 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002500 }
2501 break;
2502 }
2503 case 2:
2504 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002505 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2506 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2507 int sshift, dshift;
2508 int s_start, s_end, s_inc;
2509 int jstop = png_pass_inc[pass];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002510 png_uint_32 i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002511
Andreas Dilger47a0c421997-05-16 02:46:07 -05002512#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2513 if (transformations & PNG_PACKSWAP)
2514 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002515 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2516 dshift = (int)(((final_width + 3) & 0x03) << 1);
2517 s_start = 6;
2518 s_end = 0;
2519 s_inc = -2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002520 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002521 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002522#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002523 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002524 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2525 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2526 s_start = 0;
2527 s_end = 6;
2528 s_inc = 2;
2529 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002530
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002531 for (i = 0; i < row_info->width; i++)
2532 {
2533 png_byte v;
2534 int j;
2535
2536 v = (png_byte)((*sp >> sshift) & 0x03);
2537 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002538 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002539 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2540 *dp |= (png_byte)(v << dshift);
2541 if (dshift == s_end)
2542 {
2543 dshift = s_start;
2544 dp--;
2545 }
2546 else
2547 dshift += s_inc;
2548 }
2549 if (sshift == s_end)
2550 {
2551 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002552 sp--;
2553 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002554 else
2555 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002556 }
2557 break;
2558 }
2559 case 4:
2560 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002561 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2562 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002563 int sshift, dshift;
2564 int s_start, s_end, s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002565 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002566 int jstop = png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05002567
Andreas Dilger47a0c421997-05-16 02:46:07 -05002568#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2569 if (transformations & PNG_PACKSWAP)
2570 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002571 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2572 dshift = (int)(((final_width + 1) & 0x01) << 2);
2573 s_start = 4;
2574 s_end = 0;
2575 s_inc = -4;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002576 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002577 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002578#endif
2579 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002580 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2581 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2582 s_start = 0;
2583 s_end = 4;
2584 s_inc = 4;
2585 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002586
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002587 for (i = 0; i < row_info->width; i++)
2588 {
2589 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2590 int j;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002591
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002592 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002593 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002594 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2595 *dp |= (png_byte)(v << dshift);
2596 if (dshift == s_end)
2597 {
2598 dshift = s_start;
2599 dp--;
2600 }
2601 else
2602 dshift += s_inc;
2603 }
2604 if (sshift == s_end)
2605 {
2606 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002607 sp--;
2608 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002609 else
2610 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002611 }
2612 break;
2613 }
2614 default:
2615 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002616 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2617 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002618 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05002619
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002620 int jstop = png_pass_inc[pass];
2621 png_uint_32 i;
2622
2623 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002624 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002625 png_byte v[8];
2626 int j;
2627
2628 png_memcpy(v, sp, pixel_bytes);
2629 for (j = 0; j < jstop; j++)
2630 {
2631 png_memcpy(dp, v, pixel_bytes);
2632 dp -= pixel_bytes;
2633 }
2634 sp -= pixel_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05002635 }
2636 break;
2637 }
2638 }
2639 row_info->width = final_width;
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002640 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
Guy Schalnat0d580581995-07-20 02:43:20 -05002641 }
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05002642#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002643 if (&transformations == NULL) /* silence compiler warning */
2644 return;
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05002645#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002646}
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002647#endif /* !PNG_HAVE_MMX_READ_INTERLACE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002648#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05002649
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002650#ifndef PNG_HAVE_MMX_READ_FILTER_ROW
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002651void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002652png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002653 png_bytep prev_row, int filter)
2654{
2655 png_debug(1, "in png_read_filter_row\n");
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -05002656 png_debug2(2,"row = %lu, filter = %d\n",
2657 (unsigned long) png_ptr->row_number, filter);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002658 switch (filter)
2659 {
2660 case PNG_FILTER_VALUE_NONE:
2661 break;
2662 case PNG_FILTER_VALUE_SUB:
2663 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002664 png_uint_32 i;
2665 png_uint_32 istop = row_info->rowbytes;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002666 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002667 png_bytep rp = row + bpp;
2668 png_bytep lp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002669
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002670 for (i = bpp; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002671 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002672 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2673 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002674 }
2675 break;
2676 }
2677 case PNG_FILTER_VALUE_UP:
2678 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002679 png_uint_32 i;
2680 png_uint_32 istop = row_info->rowbytes;
2681 png_bytep rp = row;
2682 png_bytep pp = prev_row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002683
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002684 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002685 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002686 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2687 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002688 }
2689 break;
2690 }
2691 case PNG_FILTER_VALUE_AVG:
2692 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002693 png_uint_32 i;
2694 png_bytep rp = row;
2695 png_bytep pp = prev_row;
2696 png_bytep lp = row;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002697 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002698 png_uint_32 istop = row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002699
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002700 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002701 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002702 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002703 ((int)(*pp++) / 2 )) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002704 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002705 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002706
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002707 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002708 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002709 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002710 (int)(*pp++ + *lp++) / 2 ) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002711 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002712 }
2713 break;
2714 }
2715 case PNG_FILTER_VALUE_PAETH:
2716 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002717 png_uint_32 i;
2718 png_bytep rp = row;
2719 png_bytep pp = prev_row;
2720 png_bytep lp = row;
2721 png_bytep cp = prev_row;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002722 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002723 png_uint_32 istop=row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002724
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002725 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002726 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002727 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2728 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002729 }
2730
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002731 for (i = 0; i < istop; i++) /* use leftover rp,pp */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002732 {
2733 int a, b, c, pa, pb, pc, p;
2734
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002735 a = *lp++;
2736 b = *pp++;
2737 c = *cp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002738
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002739 p = b - c;
2740 pc = a - c;
2741
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002742#ifdef PNG_USE_ABS
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002743 pa = abs(p);
2744 pb = abs(pc);
2745 pc = abs(p + pc);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002746#else
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002747 pa = p < 0 ? -p : p;
2748 pb = pc < 0 ? -pc : pc;
2749 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002750#endif
2751
2752 /*
2753 if (pa <= pb && pa <= pc)
2754 p = a;
2755 else if (pb <= pc)
2756 p = b;
2757 else
2758 p = c;
2759 */
2760
2761 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2762
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002763 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2764 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002765 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002766 break;
2767 }
2768 default:
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002769 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2770 *row=0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002771 break;
2772 }
2773}
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002774#endif /* !PNG_HAVE_MMX_READ_FILTER_ROW */
Guy Schalnat0d580581995-07-20 02:43:20 -05002775
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002776void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002777png_read_finish_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002778{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002779#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002780 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002781
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002782 /* start of interlace block */
2783 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002784
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002785 /* offset to next interlace block */
2786 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002787
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002788 /* start of interlace block in the y direction */
2789 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002790
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002791 /* offset to next interlace block in the y direction */
2792 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002793#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002794
Andreas Dilger47a0c421997-05-16 02:46:07 -05002795 png_debug(1, "in png_read_finish_row\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05002796 png_ptr->row_number++;
2797 if (png_ptr->row_number < png_ptr->num_rows)
2798 return;
2799
2800 if (png_ptr->interlaced)
2801 {
2802 png_ptr->row_number = 0;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002803 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05002804 do
2805 {
2806 png_ptr->pass++;
2807 if (png_ptr->pass >= 7)
2808 break;
2809 png_ptr->iwidth = (png_ptr->width +
2810 png_pass_inc[png_ptr->pass] - 1 -
2811 png_pass_start[png_ptr->pass]) /
2812 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002813
2814 png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
2815 png_ptr->iwidth) + 1;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002816
Guy Schalnat0d580581995-07-20 02:43:20 -05002817 if (!(png_ptr->transformations & PNG_INTERLACE))
2818 {
2819 png_ptr->num_rows = (png_ptr->height +
2820 png_pass_yinc[png_ptr->pass] - 1 -
2821 png_pass_ystart[png_ptr->pass]) /
2822 png_pass_yinc[png_ptr->pass];
2823 if (!(png_ptr->num_rows))
2824 continue;
2825 }
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002826 else /* if (png_ptr->transformations & PNG_INTERLACE) */
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002827 break;
Guy Schalnat0d580581995-07-20 02:43:20 -05002828 } while (png_ptr->iwidth == 0);
2829
2830 if (png_ptr->pass < 7)
2831 return;
2832 }
2833
Guy Schalnate5a37791996-06-05 15:50:50 -05002834 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
Guy Schalnat0d580581995-07-20 02:43:20 -05002835 {
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002836#ifdef PNG_USE_LOCAL_ARRAYS
2837 PNG_IDAT;
2838#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002839 char extra;
2840 int ret;
2841
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002842 png_ptr->zstream.next_out = (Byte *)&extra;
2843 png_ptr->zstream.avail_out = (uInt)1;
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -06002844 for(;;)
Guy Schalnat0d580581995-07-20 02:43:20 -05002845 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002846 if (!(png_ptr->zstream.avail_in))
Guy Schalnat0d580581995-07-20 02:43:20 -05002847 {
2848 while (!png_ptr->idat_size)
2849 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002850 png_byte chunk_length[4];
Guy Schalnat0d580581995-07-20 02:43:20 -05002851
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002852 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -05002853
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002854 png_read_data(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05002855 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnat0d580581995-07-20 02:43:20 -05002856 png_reset_crc(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002857 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002858 if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
Guy Schalnat6d764711995-12-19 03:22:19 -06002859 png_error(png_ptr, "Not enough image data");
Guy Schalnat0d580581995-07-20 02:43:20 -05002860
2861 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002862 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2863 png_ptr->zstream.next_in = png_ptr->zbuf;
Guy Schalnat0d580581995-07-20 02:43:20 -05002864 if (png_ptr->zbuf_size > png_ptr->idat_size)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002865 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2866 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2867 png_ptr->idat_size -= png_ptr->zstream.avail_in;
Guy Schalnat0d580581995-07-20 02:43:20 -05002868 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002869 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnat0d580581995-07-20 02:43:20 -05002870 if (ret == Z_STREAM_END)
2871 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002872 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
Guy Schalnat0d580581995-07-20 02:43:20 -05002873 png_ptr->idat_size)
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05002874 png_warning(png_ptr, "Extra compressed data");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002875 png_ptr->mode |= PNG_AFTER_IDAT;
2876 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Guy Schalnat0d580581995-07-20 02:43:20 -05002877 break;
2878 }
2879 if (ret != Z_OK)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002880 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
Guy Schalnate5a37791996-06-05 15:50:50 -05002881 "Decompression Error");
Guy Schalnat0d580581995-07-20 02:43:20 -05002882
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002883 if (!(png_ptr->zstream.avail_out))
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05002884 {
2885 png_warning(png_ptr, "Extra compressed data.");
2886 png_ptr->mode |= PNG_AFTER_IDAT;
2887 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2888 break;
2889 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002890
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -06002891 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002892 png_ptr->zstream.avail_out = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002893 }
2894
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002895 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05002896 png_warning(png_ptr, "Extra compression data");
Guy Schalnat0d580581995-07-20 02:43:20 -05002897
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002898 inflateReset(&png_ptr->zstream);
Guy Schalnat0d580581995-07-20 02:43:20 -05002899
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002900 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnat0d580581995-07-20 02:43:20 -05002901}
2902
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002903void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002904png_read_start_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002905{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002906#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002907 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002908
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002909 /* start of interlace block */
2910 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002911
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002912 /* offset to next interlace block */
2913 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002914
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002915 /* start of interlace block in the y direction */
2916 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002917
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002918 /* offset to next interlace block in the y direction */
2919 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002920#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002921
Guy Schalnat0d580581995-07-20 02:43:20 -05002922 int max_pixel_depth;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002923 png_uint_32 row_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05002924
Andreas Dilger47a0c421997-05-16 02:46:07 -05002925 png_debug(1, "in png_read_start_row\n");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002926 png_ptr->zstream.avail_in = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002927 png_init_read_transformations(png_ptr);
2928 if (png_ptr->interlaced)
2929 {
2930 if (!(png_ptr->transformations & PNG_INTERLACE))
2931 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2932 png_pass_ystart[0]) / png_pass_yinc[0];
2933 else
2934 png_ptr->num_rows = png_ptr->height;
2935
2936 png_ptr->iwidth = (png_ptr->width +
2937 png_pass_inc[png_ptr->pass] - 1 -
2938 png_pass_start[png_ptr->pass]) /
2939 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002940
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002941 row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;
2942
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002943 png_ptr->irowbytes = (png_size_t)row_bytes;
2944 if((png_uint_32)png_ptr->irowbytes != row_bytes)
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002945 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
Guy Schalnat0d580581995-07-20 02:43:20 -05002946 }
2947 else
2948 {
2949 png_ptr->num_rows = png_ptr->height;
2950 png_ptr->iwidth = png_ptr->width;
2951 png_ptr->irowbytes = png_ptr->rowbytes + 1;
2952 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002953 max_pixel_depth = png_ptr->pixel_depth;
2954
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002955#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05002956 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05002957 max_pixel_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002958#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002959
Guy Schalnate5a37791996-06-05 15:50:50 -05002960#if defined(PNG_READ_EXPAND_SUPPORTED)
2961 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05002962 {
2963 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2964 {
2965 if (png_ptr->num_trans)
2966 max_pixel_depth = 32;
2967 else
2968 max_pixel_depth = 24;
2969 }
2970 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2971 {
2972 if (max_pixel_depth < 8)
2973 max_pixel_depth = 8;
2974 if (png_ptr->num_trans)
2975 max_pixel_depth *= 2;
2976 }
2977 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2978 {
2979 if (png_ptr->num_trans)
2980 {
2981 max_pixel_depth *= 4;
2982 max_pixel_depth /= 3;
2983 }
2984 }
2985 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002986#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002987
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002988#if defined(PNG_READ_FILLER_SUPPORTED)
2989 if (png_ptr->transformations & (PNG_FILLER))
Guy Schalnat0d580581995-07-20 02:43:20 -05002990 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002991 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2992 max_pixel_depth = 32;
2993 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002994 {
2995 if (max_pixel_depth <= 8)
2996 max_pixel_depth = 16;
2997 else
2998 max_pixel_depth = 32;
2999 }
3000 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3001 {
3002 if (max_pixel_depth <= 32)
3003 max_pixel_depth = 32;
3004 else
3005 max_pixel_depth = 64;
3006 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003007 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003008#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003009
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003010#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003011 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3012 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003013 if (
3014#if defined(PNG_READ_EXPAND_SUPPORTED)
3015 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3016#endif
3017#if defined(PNG_READ_FILLER_SUPPORTED)
3018 (png_ptr->transformations & (PNG_FILLER)) ||
3019#endif
3020 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
Guy Schalnat0d580581995-07-20 02:43:20 -05003021 {
3022 if (max_pixel_depth <= 16)
3023 max_pixel_depth = 32;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003024 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003025 max_pixel_depth = 64;
3026 }
3027 else
3028 {
3029 if (max_pixel_depth <= 8)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06003030 {
3031 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3032 max_pixel_depth = 32;
3033 else
3034 max_pixel_depth = 24;
3035 }
3036 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3037 max_pixel_depth = 64;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003038 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003039 max_pixel_depth = 48;
3040 }
3041 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003042#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003043
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05003044#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3045defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003046 if(png_ptr->transformations & PNG_USER_TRANSFORM)
3047 {
3048 int user_pixel_depth=png_ptr->user_transform_depth*
3049 png_ptr->user_transform_channels;
3050 if(user_pixel_depth > max_pixel_depth)
3051 max_pixel_depth=user_pixel_depth;
3052 }
3053#endif
3054
Guy Schalnat0d580581995-07-20 02:43:20 -05003055 /* align the width on the next larger 8 pixels. Mainly used
3056 for interlacing */
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003057 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
Guy Schalnat0d580581995-07-20 02:43:20 -05003058 /* calculate the maximum bytes needed, adding a byte and a pixel
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003059 for safety's sake */
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05003060 row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) +
Guy Schalnat0d580581995-07-20 02:43:20 -05003061 1 + ((max_pixel_depth + 7) >> 3);
3062#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003063 if (row_bytes > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05003064 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05003065#endif
Glenn Randers-Pehrson1b8e5672001-08-25 06:46:06 -05003066 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
3067 png_ptr->row_buf = png_ptr->big_row_buf+32;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -05003068#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05003069 png_ptr->row_buf_size = row_bytes;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -05003070#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003071
3072#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003073 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05003074 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05003075#endif
Glenn Randers-Pehrson78067772004-11-02 21:49:39 -06003076 if ((png_uint_32)png_ptr->rowbytes > PNG_SIZE_MAX - 1)
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05003077 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003078 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3079 png_ptr->rowbytes + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05003080
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06003081 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003082
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -05003083 png_debug1(3, "width = %lu,\n", (unsigned long) png_ptr->width);
3084 png_debug1(3, "height = %lu,\n", (unsigned long) png_ptr->height);
3085 png_debug1(3, "iwidth = %lu,\n", (unsigned long) png_ptr->iwidth);
3086 png_debug1(3, "num_rows = %lu\n", (unsigned long) png_ptr->num_rows);
3087 png_debug1(3, "rowbytes = %lu,\n", (unsigned long) png_ptr->rowbytes);
3088 png_debug1(3, "irowbytes = %lu,\n", (unsigned long) png_ptr->irowbytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05003089
Guy Schalnate5a37791996-06-05 15:50:50 -05003090 png_ptr->flags |= PNG_FLAG_ROW_INIT;
Guy Schalnat0d580581995-07-20 02:43:20 -05003091}
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06003092#endif /* PNG_READ_SUPPORTED */