blob: d4820f0ef52b33483a590954c08936626df1fb52 [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-Pehrson3a5a7592006-04-15 14:14:42 -05004 * Last changed in libpng 1.2.9 April 14, 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{
22 png_uint_32 i = png_get_uint_32(buf);
23 if (i > PNG_UINT_31_MAX)
Glenn Randers-Pehrsonc3d51c12006-03-02 07:23:18 -060024 png_error(png_ptr, "PNG unsigned integer out of range.");
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -050025 return (i);
26}
Andreas Dilger47a0c421997-05-16 02:46:07 -050027#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050028/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060029png_uint_32 PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060030png_get_uint_32(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050031{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050032 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
Guy Schalnat0d580581995-07-20 02:43:20 -050033 ((png_uint_32)(*(buf + 1)) << 16) +
34 ((png_uint_32)(*(buf + 2)) << 8) +
35 (png_uint_32)(*(buf + 3));
36
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060037 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050038}
39
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050040/* Grab a signed 32-bit integer from a buffer in big-endian format. The
Andreas Dilger47a0c421997-05-16 02:46:07 -050041 * data is stored in the PNG file in two's complement format, and it is
42 * assumed that the machine format for signed integers is the same. */
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060043png_int_32 PNGAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -050044png_get_int_32(png_bytep buf)
45{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050046 png_int_32 i = ((png_int_32)(*buf) << 24) +
Andreas Dilger47a0c421997-05-16 02:46:07 -050047 ((png_int_32)(*(buf + 1)) << 16) +
48 ((png_int_32)(*(buf + 2)) << 8) +
49 (png_int_32)(*(buf + 3));
50
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060051 return (i);
Andreas Dilger47a0c421997-05-16 02:46:07 -050052}
Andreas Dilger47a0c421997-05-16 02:46:07 -050053
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050054/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060055png_uint_16 PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -060056png_get_uint_16(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050057{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050058 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060059 (png_uint_16)(*(buf + 1)));
Guy Schalnat0d580581995-07-20 02:43:20 -050060
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060061 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050062}
Andreas Dilger47a0c421997-05-16 02:46:07 -050063#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -050064
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060065/* Read data, and (optionally) run it through the CRC. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050066void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -050067png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
Guy Schalnat0d580581995-07-20 02:43:20 -050068{
Guy Schalnat6d764711995-12-19 03:22:19 -060069 png_read_data(png_ptr, buf, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -050070 png_calculate_crc(png_ptr, buf, length);
Guy Schalnat0d580581995-07-20 02:43:20 -050071}
72
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060073/* Optionally skip data and then check the CRC. Depending on whether we
74 are reading a ancillary or critical chunk, and how the program has set
Andreas Dilger47a0c421997-05-16 02:46:07 -050075 things up, we may calculate the CRC on the data and print a message.
76 Returns '1' if there was a CRC error, '0' otherwise. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050077int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060078png_crc_finish(png_structp png_ptr, png_uint_32 skip)
Guy Schalnat0d580581995-07-20 02:43:20 -050079{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050080 png_size_t i;
81 png_size_t istop = png_ptr->zbuf_size;
Guy Schalnat0d580581995-07-20 02:43:20 -050082
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -050083 for (i = (png_size_t)skip; i > istop; i -= istop)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060084 {
Andreas Dilger47a0c421997-05-16 02:46:07 -050085 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
Guy Schalnat0d580581995-07-20 02:43:20 -050086 }
87 if (i)
88 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050089 png_crc_read(png_ptr, png_ptr->zbuf, i);
Guy Schalnat0d580581995-07-20 02:43:20 -050090 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060091
Andreas Dilger47a0c421997-05-16 02:46:07 -050092 if (png_crc_error(png_ptr))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060093 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -060094 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060095 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
96 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -060097 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060098 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -060099 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600100 }
101 else
102 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600103 png_chunk_error(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600104 }
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600105 return (1);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600106 }
107
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600108 return (0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500109}
110
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600111/* Compare the CRC stored in the PNG file with that calculated by libpng from
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600112 the data it has read thus far. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500113int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600114png_crc_error(png_structp png_ptr)
115{
116 png_byte crc_bytes[4];
117 png_uint_32 crc;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500118 int need_crc = 1;
119
120 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
121 {
122 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
123 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
124 need_crc = 0;
125 }
126 else /* critical */
127 {
128 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
129 need_crc = 0;
130 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600131
132 png_read_data(png_ptr, crc_bytes, 4);
133
Andreas Dilger47a0c421997-05-16 02:46:07 -0500134 if (need_crc)
135 {
136 crc = png_get_uint_32(crc_bytes);
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600137 return ((int)(crc != png_ptr->crc));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500138 }
139 else
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600140 return (0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600141}
142
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600143#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500144 defined(PNG_READ_iCCP_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600145/*
146 * Decompress trailing data in a chunk. The assumption is that chunkdata
147 * points at an allocated area holding the contents of a chunk with a
148 * trailing compressed part. What we get back is an allocated area
149 * holding the original prefix part and an uncompressed version of the
150 * trailing part (the malloc area passed in is freed).
151 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500152png_charp /* PRIVATE */
153png_decompress_chunk(png_structp png_ptr, int comp_type,
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600154 png_charp chunkdata, png_size_t chunklength,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600155 png_size_t prefix_size, png_size_t *newlength)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600156{
157 static char msg[] = "Error decoding compressed text";
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500158 png_charp text;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600159 png_size_t text_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600160
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600161 if (comp_type == PNG_COMPRESSION_TYPE_BASE)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600162 {
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500163 int ret = Z_OK;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600164 png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
165 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
166 png_ptr->zstream.next_out = png_ptr->zbuf;
167 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
168
169 text_size = 0;
170 text = NULL;
171
172 while (png_ptr->zstream.avail_in)
173 {
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500174 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600175 if (ret != Z_OK && ret != Z_STREAM_END)
176 {
177 if (png_ptr->zstream.msg != NULL)
178 png_warning(png_ptr, png_ptr->zstream.msg);
179 else
180 png_warning(png_ptr, msg);
181 inflateReset(&png_ptr->zstream);
182 png_ptr->zstream.avail_in = 0;
183
184 if (text == NULL)
185 {
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500186 text_size = prefix_size + png_sizeof(msg) + 1;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500187 text = (png_charp)png_malloc_warn(png_ptr, text_size);
188 if (text == NULL)
189 {
190 png_free(png_ptr,chunkdata);
191 png_error(png_ptr,"Not enough memory to decompress chunk");
192 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500193 png_memcpy(text, chunkdata, prefix_size);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600194 }
195
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500196 text[text_size - 1] = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600197
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500198 /* Copy what we can of the error message into the text chunk */
199 text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500200 text_size = png_sizeof(msg) > text_size ? text_size :
201 png_sizeof(msg);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500202 png_memcpy(text + prefix_size, msg, text_size + 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600203 break;
204 }
205 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
206 {
207 if (text == NULL)
208 {
209 text_size = prefix_size +
210 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500211 text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
212 if (text == NULL)
213 {
214 png_free(png_ptr,chunkdata);
215 png_error(png_ptr,"Not enough memory to decompress chunk.");
216 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500217 png_memcpy(text + prefix_size, png_ptr->zbuf,
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500218 text_size - prefix_size);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500219 png_memcpy(text, chunkdata, prefix_size);
220 *(text + text_size) = 0x00;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600221 }
222 else
223 {
224 png_charp tmp;
225
226 tmp = text;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500227 text = (png_charp)png_malloc_warn(png_ptr,
228 (png_uint_32)(text_size +
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600229 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500230 if (text == NULL)
231 {
232 png_free(png_ptr, tmp);
233 png_free(png_ptr, chunkdata);
234 png_error(png_ptr,"Not enough memory to decompress chunk..");
235 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600236 png_memcpy(text, tmp, text_size);
237 png_free(png_ptr, tmp);
238 png_memcpy(text + text_size, png_ptr->zbuf,
239 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
240 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
241 *(text + text_size) = 0x00;
242 }
243 if (ret == Z_STREAM_END)
244 break;
245 else
246 {
247 png_ptr->zstream.next_out = png_ptr->zbuf;
248 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
249 }
250 }
251 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500252 if (ret != Z_STREAM_END)
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500253 {
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500254#ifndef PNG_NO_STDIO
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500255 char umsg[50];
256
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500257 if (ret == Z_BUF_ERROR)
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500258 png_sprintf(umsg,"Buffer error in compressed datastream in %s chunk",
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500259 png_ptr->chunk_name);
260 else if (ret == Z_DATA_ERROR)
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500261 png_sprintf(umsg,"Data error in compressed datastream in %s chunk",
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500262 png_ptr->chunk_name);
263 else
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500264 png_sprintf(umsg,"Incomplete compressed datastream in %s chunk",
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500265 png_ptr->chunk_name);
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500266 png_warning(png_ptr, umsg);
267#else
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500268 png_warning(png_ptr,
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500269 "Incomplete compressed datastream in chunk other than IDAT");
270#endif
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -0600271 text_size=prefix_size;
272 if (text == NULL)
273 {
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -0500274 text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
275 if (text == NULL)
276 {
277 png_free(png_ptr, chunkdata);
278 png_error(png_ptr,"Not enough memory for text.");
279 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500280 png_memcpy(text, chunkdata, prefix_size);
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -0600281 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500282 *(text + text_size) = 0x00;
Glenn Randers-Pehrson13944802000-06-24 07:42:42 -0500283 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600284
285 inflateReset(&png_ptr->zstream);
286 png_ptr->zstream.avail_in = 0;
287
288 png_free(png_ptr, chunkdata);
289 chunkdata = text;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600290 *newlength=text_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600291 }
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600292 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600293 {
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500294#ifndef PNG_NO_STDIO
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600295 char umsg[50];
296
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -0500297 png_sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600298 png_warning(png_ptr, umsg);
299#else
300 png_warning(png_ptr, "Unknown zTXt compression type");
301#endif
302
Glenn Randers-Pehrsonf05f8032000-12-23 14:27:39 -0600303 *(chunkdata + prefix_size) = 0x00;
304 *newlength=prefix_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600305 }
306
307 return chunkdata;
308}
309#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600310
Guy Schalnat0d580581995-07-20 02:43:20 -0500311/* read and check the IDHR chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500312void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600313png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500314{
315 png_byte buf[13];
316 png_uint_32 width, height;
317 int bit_depth, color_type, compression_type, filter_type;
318 int interlace_type;
319
Andreas Dilger47a0c421997-05-16 02:46:07 -0500320 png_debug(1, "in png_handle_IHDR\n");
321
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600322 if (png_ptr->mode & PNG_HAVE_IHDR)
Guy Schalnate5a37791996-06-05 15:50:50 -0500323 png_error(png_ptr, "Out of place IHDR");
324
Guy Schalnat0d580581995-07-20 02:43:20 -0500325 /* check the length */
326 if (length != 13)
Guy Schalnat6d764711995-12-19 03:22:19 -0600327 png_error(png_ptr, "Invalid IHDR chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -0500328
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600329 png_ptr->mode |= PNG_HAVE_IHDR;
330
Guy Schalnat0d580581995-07-20 02:43:20 -0500331 png_crc_read(png_ptr, buf, 13);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600332 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500333
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500334 width = png_get_uint_31(png_ptr, buf);
335 height = png_get_uint_31(png_ptr, buf + 4);
Guy Schalnat0d580581995-07-20 02:43:20 -0500336 bit_depth = buf[8];
337 color_type = buf[9];
338 compression_type = buf[10];
339 filter_type = buf[11];
340 interlace_type = buf[12];
341
Guy Schalnat0d580581995-07-20 02:43:20 -0500342 /* set internal variables */
343 png_ptr->width = width;
344 png_ptr->height = height;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600345 png_ptr->bit_depth = (png_byte)bit_depth;
346 png_ptr->interlaced = (png_byte)interlace_type;
347 png_ptr->color_type = (png_byte)color_type;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500348#if defined(PNG_MNG_FEATURES_SUPPORTED)
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -0600349 png_ptr->filter_type = (png_byte)filter_type;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500350#endif
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500351 png_ptr->compression_type = (png_byte)compression_type;
Guy Schalnat0d580581995-07-20 02:43:20 -0500352
353 /* find number of channels */
354 switch (png_ptr->color_type)
355 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500356 case PNG_COLOR_TYPE_GRAY:
357 case PNG_COLOR_TYPE_PALETTE:
Guy Schalnat0d580581995-07-20 02:43:20 -0500358 png_ptr->channels = 1;
359 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500360 case PNG_COLOR_TYPE_RGB:
Guy Schalnat0d580581995-07-20 02:43:20 -0500361 png_ptr->channels = 3;
362 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500363 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500364 png_ptr->channels = 2;
365 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500366 case PNG_COLOR_TYPE_RGB_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500367 png_ptr->channels = 4;
368 break;
369 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600370
Guy Schalnat0d580581995-07-20 02:43:20 -0500371 /* set up other useful info */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600372 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600373 png_ptr->channels);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500374 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500375 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
376 png_debug1(3,"channels = %d\n", png_ptr->channels);
Glenn Randers-Pehrson4766a242000-07-17 06:17:09 -0500377 png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500378 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
379 color_type, interlace_type, compression_type, filter_type);
Guy Schalnat0d580581995-07-20 02:43:20 -0500380}
381
382/* read and check the palette */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500383void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600384png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500385{
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600386 png_color palette[PNG_MAX_PALETTE_LENGTH];
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600387 int num, i;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500388#ifndef PNG_NO_POINTER_INDEXING
389 png_colorp pal_ptr;
390#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500391
Andreas Dilger47a0c421997-05-16 02:46:07 -0500392 png_debug(1, "in png_handle_PLTE\n");
393
Guy Schalnate5a37791996-06-05 15:50:50 -0500394 if (!(png_ptr->mode & PNG_HAVE_IHDR))
395 png_error(png_ptr, "Missing IHDR before PLTE");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600396 else if (png_ptr->mode & PNG_HAVE_IDAT)
397 {
398 png_warning(png_ptr, "Invalid PLTE after IDAT");
399 png_crc_finish(png_ptr, length);
400 return;
401 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500402 else if (png_ptr->mode & PNG_HAVE_PLTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600403 png_error(png_ptr, "Duplicate PLTE chunk");
404
405 png_ptr->mode |= PNG_HAVE_PLTE;
Guy Schalnate5a37791996-06-05 15:50:50 -0500406
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500407 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
408 {
409 png_warning(png_ptr,
410 "Ignoring PLTE chunk in grayscale PNG");
411 png_crc_finish(png_ptr, length);
412 return;
413 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500414#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
415 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
416 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600417 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500418 return;
419 }
420#endif
421
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -0600422 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
Guy Schalnate5a37791996-06-05 15:50:50 -0500423 {
424 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
425 {
426 png_warning(png_ptr, "Invalid palette chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600427 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500428 return;
429 }
430 else
431 {
432 png_error(png_ptr, "Invalid palette chunk");
433 }
434 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500435
436 num = (int)length / 3;
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500437
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500438#ifndef PNG_NO_POINTER_INDEXING
439 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
440 {
441 png_byte buf[3];
442
443 png_crc_read(png_ptr, buf, 3);
444 pal_ptr->red = buf[0];
445 pal_ptr->green = buf[1];
446 pal_ptr->blue = buf[2];
447 }
448#else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600449 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500450 {
451 png_byte buf[3];
452
453 png_crc_read(png_ptr, buf, 3);
454 /* don't depend upon png_color being any order */
455 palette[i].red = buf[0];
456 palette[i].green = buf[1];
457 palette[i].blue = buf[2];
458 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -0500459#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600460
461 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
462 whatever the normal CRC configuration tells us. However, if we
463 have an RGB image, the PLTE can be considered ancillary, so
464 we will act as though it is. */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600465#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600466 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600467#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600468 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500469 png_crc_finish(png_ptr, 0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600470 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600471#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600472 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
473 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600474 /* If we don't want to use the data from an ancillary chunk,
475 we have two options: an error abort, or a warning and we
476 ignore the data in this chunk (which should be OK, since
477 it's considered ancillary for a RGB or RGBA image). */
478 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
479 {
480 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
481 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600482 png_chunk_error(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600483 }
484 else
485 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600486 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600487 return;
488 }
489 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500490 /* Otherwise, we (optionally) emit a warning and use the chunk. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600491 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
492 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600493 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600494 }
495 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600496#endif
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500497
Andreas Dilger47a0c421997-05-16 02:46:07 -0500498 png_set_PLTE(png_ptr, info_ptr, palette, num);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500499
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500500#if defined(PNG_READ_tRNS_SUPPORTED)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500501 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
502 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600503 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500504 {
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500505 if (png_ptr->num_trans > (png_uint_16)num)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500506 {
507 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500508 png_ptr->num_trans = (png_uint_16)num;
509 }
510 if (info_ptr->num_trans > (png_uint_16)num)
511 {
512 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
513 info_ptr->num_trans = (png_uint_16)num;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500514 }
515 }
516 }
517#endif
518
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600519}
Guy Schalnate5a37791996-06-05 15:50:50 -0500520
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500521void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600522png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
523{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500524 png_debug(1, "in png_handle_IEND\n");
525
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600526 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
527 {
528 png_error(png_ptr, "No image in file");
529 }
530
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600531 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600532
533 if (length != 0)
534 {
535 png_warning(png_ptr, "Incorrect IEND chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600536 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500537 png_crc_finish(png_ptr, length);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500538
539 if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
540 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500541}
542
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500543#if defined(PNG_READ_gAMA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500544void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600545png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500546{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600547 png_fixed_point igamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600548#ifdef PNG_FLOATING_POINT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500549 float file_gamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600550#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500551 png_byte buf[4];
552
Andreas Dilger47a0c421997-05-16 02:46:07 -0500553 png_debug(1, "in png_handle_gAMA\n");
554
Guy Schalnate5a37791996-06-05 15:50:50 -0500555 if (!(png_ptr->mode & PNG_HAVE_IHDR))
556 png_error(png_ptr, "Missing IHDR before gAMA");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600557 else if (png_ptr->mode & PNG_HAVE_IDAT)
558 {
559 png_warning(png_ptr, "Invalid gAMA after IDAT");
560 png_crc_finish(png_ptr, length);
561 return;
562 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500563 else if (png_ptr->mode & PNG_HAVE_PLTE)
564 /* Should be an error, but we can cope with it */
565 png_warning(png_ptr, "Out of place gAMA chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600566
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500567 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600568#if defined(PNG_READ_sRGB_SUPPORTED)
569 && !(info_ptr->valid & PNG_INFO_sRGB)
570#endif
571 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600572 {
573 png_warning(png_ptr, "Duplicate gAMA chunk");
574 png_crc_finish(png_ptr, length);
575 return;
576 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500577
Guy Schalnat0d580581995-07-20 02:43:20 -0500578 if (length != 4)
579 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600580 png_warning(png_ptr, "Incorrect gAMA chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600581 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500582 return;
583 }
584
585 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600586 if (png_crc_finish(png_ptr, 0))
587 return;
588
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600589 igamma = (png_fixed_point)png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500590 /* check for zero gamma */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500591 if (igamma == 0)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -0500592 {
593 png_warning(png_ptr,
594 "Ignoring gAMA chunk with gamma=0");
595 return;
596 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500597
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600598#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600599 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500600 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600601 {
602 png_warning(png_ptr,
603 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500604#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600605 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600606#endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600607 return;
608 }
609#endif /* PNG_READ_sRGB_SUPPORTED */
610
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600611#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600612 file_gamma = (float)igamma / (float)100000.0;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600613# ifdef PNG_READ_GAMMA_SUPPORTED
614 png_ptr->gamma = file_gamma;
615# endif
616 png_set_gAMA(png_ptr, info_ptr, file_gamma);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600617#endif
618#ifdef PNG_FIXED_POINT_SUPPORTED
619 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
620#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500621}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500622#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500623
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500624#if defined(PNG_READ_sBIT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500625void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600626png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500627{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500628 png_size_t truelen;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600629 png_byte buf[4];
Guy Schalnat69b14481996-01-10 02:56:49 -0600630
Andreas Dilger47a0c421997-05-16 02:46:07 -0500631 png_debug(1, "in png_handle_sBIT\n");
632
Guy Schalnat69b14481996-01-10 02:56:49 -0600633 buf[0] = buf[1] = buf[2] = buf[3] = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500634
Guy Schalnate5a37791996-06-05 15:50:50 -0500635 if (!(png_ptr->mode & PNG_HAVE_IHDR))
636 png_error(png_ptr, "Missing IHDR before sBIT");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600637 else if (png_ptr->mode & PNG_HAVE_IDAT)
638 {
639 png_warning(png_ptr, "Invalid sBIT after IDAT");
640 png_crc_finish(png_ptr, length);
641 return;
642 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500643 else if (png_ptr->mode & PNG_HAVE_PLTE)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600644 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500645 /* Should be an error, but we can cope with it */
646 png_warning(png_ptr, "Out of place sBIT chunk");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600647 }
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500648 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600649 {
650 png_warning(png_ptr, "Duplicate sBIT chunk");
651 png_crc_finish(png_ptr, length);
652 return;
653 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500654
Guy Schalnat0d580581995-07-20 02:43:20 -0500655 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600656 truelen = 3;
Guy Schalnat0d580581995-07-20 02:43:20 -0500657 else
Andreas Dilger47a0c421997-05-16 02:46:07 -0500658 truelen = (png_size_t)png_ptr->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500659
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -0500660 if (length != truelen || length > 4)
Guy Schalnat0d580581995-07-20 02:43:20 -0500661 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600662 png_warning(png_ptr, "Incorrect sBIT chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600663 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600664 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500665 }
666
Andreas Dilger47a0c421997-05-16 02:46:07 -0500667 png_crc_read(png_ptr, buf, truelen);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600668 if (png_crc_finish(png_ptr, 0))
669 return;
670
Guy Schalnat0d580581995-07-20 02:43:20 -0500671 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
672 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600673 png_ptr->sig_bit.red = buf[0];
674 png_ptr->sig_bit.green = buf[1];
675 png_ptr->sig_bit.blue = buf[2];
676 png_ptr->sig_bit.alpha = buf[3];
Guy Schalnat0d580581995-07-20 02:43:20 -0500677 }
678 else
679 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600680 png_ptr->sig_bit.gray = buf[0];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600681 png_ptr->sig_bit.red = buf[0];
682 png_ptr->sig_bit.green = buf[0];
683 png_ptr->sig_bit.blue = buf[0];
Guy Schalnat6d764711995-12-19 03:22:19 -0600684 png_ptr->sig_bit.alpha = buf[1];
Guy Schalnat0d580581995-07-20 02:43:20 -0500685 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500686 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
Guy Schalnat0d580581995-07-20 02:43:20 -0500687}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500688#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500689
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500690#if defined(PNG_READ_cHRM_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500691void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600692png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500693{
694 png_byte buf[4];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600695#ifdef PNG_FLOATING_POINT_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -0500696 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 -0600697#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600698 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 -0600699 int_y_green, int_x_blue, int_y_blue;
Guy Schalnat0d580581995-07-20 02:43:20 -0500700
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600701 png_uint_32 uint_x, uint_y;
702
Andreas Dilger47a0c421997-05-16 02:46:07 -0500703 png_debug(1, "in png_handle_cHRM\n");
704
Guy Schalnate5a37791996-06-05 15:50:50 -0500705 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600706 png_error(png_ptr, "Missing IHDR before cHRM");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600707 else if (png_ptr->mode & PNG_HAVE_IDAT)
708 {
709 png_warning(png_ptr, "Invalid cHRM after IDAT");
710 png_crc_finish(png_ptr, length);
711 return;
712 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500713 else if (png_ptr->mode & PNG_HAVE_PLTE)
714 /* Should be an error, but we can cope with it */
715 png_warning(png_ptr, "Missing PLTE before cHRM");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600716
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500717 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600718#if defined(PNG_READ_sRGB_SUPPORTED)
719 && !(info_ptr->valid & PNG_INFO_sRGB)
720#endif
721 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600722 {
723 png_warning(png_ptr, "Duplicate cHRM chunk");
724 png_crc_finish(png_ptr, length);
725 return;
726 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500727
Guy Schalnat0d580581995-07-20 02:43:20 -0500728 if (length != 32)
729 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600730 png_warning(png_ptr, "Incorrect cHRM chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600731 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600732 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500733 }
734
735 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600736 uint_x = png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500737
738 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600739 uint_y = png_get_uint_32(buf);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600740
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600741 if (uint_x > 80000L || uint_y > 80000L ||
742 uint_x + uint_y > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600743 {
744 png_warning(png_ptr, "Invalid cHRM white point");
745 png_crc_finish(png_ptr, 24);
746 return;
747 }
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600748 int_x_white = (png_fixed_point)uint_x;
749 int_y_white = (png_fixed_point)uint_y;
Guy Schalnat0d580581995-07-20 02:43:20 -0500750
751 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600752 uint_x = png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500753
754 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600755 uint_y = png_get_uint_32(buf);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600756
Glenn Randers-Pehrsonddfebd32006-02-22 09:19:25 -0600757 if (uint_x + uint_y > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600758 {
759 png_warning(png_ptr, "Invalid cHRM red point");
760 png_crc_finish(png_ptr, 16);
761 return;
762 }
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600763 int_x_red = (png_fixed_point)uint_x;
764 int_y_red = (png_fixed_point)uint_y;
Guy Schalnat0d580581995-07-20 02:43:20 -0500765
766 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600767 uint_x = png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500768
769 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600770 uint_y = png_get_uint_32(buf);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600771
Glenn Randers-Pehrsonddfebd32006-02-22 09:19:25 -0600772 if (uint_x + uint_y > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600773 {
774 png_warning(png_ptr, "Invalid cHRM green point");
775 png_crc_finish(png_ptr, 8);
776 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
781 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600782 uint_x = png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500783
784 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600785 uint_y = png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500786
Glenn Randers-Pehrsonddfebd32006-02-22 09:19:25 -0600787 if (uint_x + uint_y > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600788 {
789 png_warning(png_ptr, "Invalid cHRM blue point");
790 png_crc_finish(png_ptr, 0);
791 return;
792 }
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600793 int_x_blue = (png_fixed_point)uint_x;
794 int_y_blue = (png_fixed_point)uint_y;
795
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600796#ifdef PNG_FLOATING_POINT_SUPPORTED
797 white_x = (float)int_x_white / (float)100000.0;
798 white_y = (float)int_y_white / (float)100000.0;
799 red_x = (float)int_x_red / (float)100000.0;
800 red_y = (float)int_y_red / (float)100000.0;
801 green_x = (float)int_x_green / (float)100000.0;
802 green_y = (float)int_y_green / (float)100000.0;
803 blue_x = (float)int_x_blue / (float)100000.0;
804 blue_y = (float)int_y_blue / (float)100000.0;
805#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600806
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600807#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600808 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600809 {
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500810 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
811 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
812 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
813 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
814 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
815 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
816 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
817 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600818 {
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600819
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600820 png_warning(png_ptr,
821 "Ignoring incorrect cHRM value when sRGB is also present");
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500822#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600823#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600824 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
825 white_x, white_y, red_x, red_y);
826 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
827 green_x, green_y, blue_x, blue_y);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600828#else
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600829 fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600830 int_x_white, int_y_white, int_x_red, int_y_red);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600831 fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600832 int_x_green, int_y_green, int_x_blue, int_y_blue);
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600833#endif
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500834#endif /* PNG_NO_CONSOLE_IO */
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600835 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600836 png_crc_finish(png_ptr, 0);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600837 return;
838 }
839#endif /* PNG_READ_sRGB_SUPPORTED */
840
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600841#ifdef PNG_FLOATING_POINT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500842 png_set_cHRM(png_ptr, info_ptr,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600843 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600844#endif
845#ifdef PNG_FIXED_POINT_SUPPORTED
846 png_set_cHRM_fixed(png_ptr, info_ptr,
847 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
848 int_y_green, int_x_blue, int_y_blue);
849#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600850 if (png_crc_finish(png_ptr, 0))
851 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500852}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500853#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500854
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600855#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500856void /* PRIVATE */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600857png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
858{
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600859 int intent;
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600860 png_byte buf[1];
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600861
862 png_debug(1, "in png_handle_sRGB\n");
863
864 if (!(png_ptr->mode & PNG_HAVE_IHDR))
865 png_error(png_ptr, "Missing IHDR before sRGB");
866 else if (png_ptr->mode & PNG_HAVE_IDAT)
867 {
868 png_warning(png_ptr, "Invalid sRGB after IDAT");
869 png_crc_finish(png_ptr, length);
870 return;
871 }
872 else if (png_ptr->mode & PNG_HAVE_PLTE)
873 /* Should be an error, but we can cope with it */
874 png_warning(png_ptr, "Out of place sRGB chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600875
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500876 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600877 {
878 png_warning(png_ptr, "Duplicate sRGB chunk");
879 png_crc_finish(png_ptr, length);
880 return;
881 }
882
883 if (length != 1)
884 {
885 png_warning(png_ptr, "Incorrect sRGB chunk length");
886 png_crc_finish(png_ptr, length);
887 return;
888 }
889
890 png_crc_read(png_ptr, buf, 1);
891 if (png_crc_finish(png_ptr, 0))
892 return;
893
894 intent = buf[0];
895 /* check for bad intent */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600896 if (intent >= PNG_sRGB_INTENT_LAST)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600897 {
898 png_warning(png_ptr, "Unknown sRGB intent");
899 return;
900 }
901
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600902#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600903 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600904 {
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500905 png_fixed_point igamma;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600906#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500907 igamma=info_ptr->int_gamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600908#else
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600909# ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500910 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600911# endif
912#endif
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500913 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600914 {
915 png_warning(png_ptr,
916 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrson316f97a2000-07-08 13:19:41 -0500917#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600918# ifdef PNG_FIXED_POINT_SUPPORTED
919 fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
920# else
921# ifdef PNG_FLOATING_POINT_SUPPORTED
922 fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
923# endif
924# endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600925#endif
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600926 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600927 }
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600928#endif /* PNG_READ_gAMA_SUPPORTED */
929
930#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500931#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson170b70c2006-03-10 10:19:04 -0600932 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500933 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
934 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
935 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
936 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
937 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
938 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
939 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
940 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600941 {
942 png_warning(png_ptr,
943 "Ignoring incorrect cHRM value when sRGB is also present");
944 }
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500945#endif /* PNG_FIXED_POINT_SUPPORTED */
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600946#endif /* PNG_READ_cHRM_SUPPORTED */
947
948 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
949}
950#endif /* PNG_READ_sRGB_SUPPORTED */
951
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600952#if defined(PNG_READ_iCCP_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500953void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600954png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
955/* Note: this does not properly handle chunks that are > 64K under DOS */
956{
957 png_charp chunkdata;
958 png_byte compression_type;
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -0600959 png_bytep pC;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600960 png_charp profile;
961 png_uint_32 skip = 0;
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -0500962 png_uint_32 profile_size, profile_length;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600963 png_size_t slength, prefix_length, data_length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600964
965 png_debug(1, "in png_handle_iCCP\n");
966
967 if (!(png_ptr->mode & PNG_HAVE_IHDR))
968 png_error(png_ptr, "Missing IHDR before iCCP");
969 else if (png_ptr->mode & PNG_HAVE_IDAT)
970 {
971 png_warning(png_ptr, "Invalid iCCP after IDAT");
972 png_crc_finish(png_ptr, length);
973 return;
974 }
975 else if (png_ptr->mode & PNG_HAVE_PLTE)
976 /* Should be an error, but we can cope with it */
977 png_warning(png_ptr, "Out of place iCCP chunk");
978
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -0500979 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600980 {
981 png_warning(png_ptr, "Duplicate iCCP chunk");
982 png_crc_finish(png_ptr, length);
983 return;
984 }
985
986#ifdef PNG_MAX_MALLOC_64K
987 if (length > (png_uint_32)65535L)
988 {
989 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
990 skip = length - (png_uint_32)65535L;
991 length = (png_uint_32)65535L;
992 }
993#endif
994
995 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
996 slength = (png_size_t)length;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500997 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600998
999 if (png_crc_finish(png_ptr, skip))
1000 {
1001 png_free(png_ptr, chunkdata);
1002 return;
1003 }
1004
1005 chunkdata[slength] = 0x00;
1006
1007 for (profile = chunkdata; *profile; profile++)
1008 /* empty loop to find end of name */ ;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001009
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001010 ++profile;
1011
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001012 /* there should be at least one zero (the compression type byte)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001013 following the separator, and we should be on it */
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001014 if ( profile >= chunkdata + slength)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001015 {
1016 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001017 png_warning(png_ptr, "Malformed iCCP chunk");
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001018 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001019 }
1020
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001021 /* compression_type should always be zero */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001022 compression_type = *profile++;
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001023 if (compression_type)
1024 {
1025 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1026 compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1027 wrote nonzero) */
1028 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001029
1030 prefix_length = profile - chunkdata;
1031 chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001032 slength, prefix_length, &data_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001033
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001034 profile_length = data_length - prefix_length;
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06001035
Glenn Randers-Pehrsondb3b88d2001-12-04 06:30:43 -06001036 if ( prefix_length > data_length || profile_length < 4)
Glenn Randers-Pehrsonb1828932001-06-23 08:03:17 -05001037 {
1038 png_free(png_ptr, chunkdata);
1039 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1040 return;
1041 }
1042
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06001043 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -06001044 pC = (png_bytep)(chunkdata+prefix_length);
1045 profile_size = ((*(pC ))<<24) |
1046 ((*(pC+1))<<16) |
1047 ((*(pC+2))<< 8) |
1048 ((*(pC+3)) );
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001049
1050 if(profile_size < profile_length)
1051 profile_length = profile_size;
1052
1053 if(profile_size > profile_length)
1054 {
Glenn Randers-Pehrsonb1828932001-06-23 08:03:17 -05001055 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrsonc3d51c12006-03-02 07:23:18 -06001056 png_warning(png_ptr, "Ignoring truncated iCCP profile.");
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -06001057 return;
1058 }
1059
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001060 png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001061 chunkdata + prefix_length, profile_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001062 png_free(png_ptr, chunkdata);
1063}
1064#endif /* PNG_READ_iCCP_SUPPORTED */
1065
1066#if defined(PNG_READ_sPLT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001067void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001068png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1069/* Note: this does not properly handle chunks that are > 64K under DOS */
1070{
1071 png_bytep chunkdata;
1072 png_bytep entry_start;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001073 png_sPLT_t new_palette;
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001074#ifdef PNG_NO_POINTER_INDEXING
1075 png_sPLT_entryp pp;
1076#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001077 int data_length, entry_size, i;
1078 png_uint_32 skip = 0;
1079 png_size_t slength;
1080
1081 png_debug(1, "in png_handle_sPLT\n");
1082
1083 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1084 png_error(png_ptr, "Missing IHDR before sPLT");
1085 else if (png_ptr->mode & PNG_HAVE_IDAT)
1086 {
1087 png_warning(png_ptr, "Invalid sPLT after IDAT");
1088 png_crc_finish(png_ptr, length);
1089 return;
1090 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001091
1092#ifdef PNG_MAX_MALLOC_64K
1093 if (length > (png_uint_32)65535L)
1094 {
1095 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1096 skip = length - (png_uint_32)65535L;
1097 length = (png_uint_32)65535L;
1098 }
1099#endif
1100
1101 chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001102 slength = (png_size_t)length;
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001103 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001104
1105 if (png_crc_finish(png_ptr, skip))
1106 {
1107 png_free(png_ptr, chunkdata);
1108 return;
1109 }
1110
1111 chunkdata[slength] = 0x00;
1112
1113 for (entry_start = chunkdata; *entry_start; entry_start++)
1114 /* empty loop to find end of name */ ;
1115 ++entry_start;
1116
1117 /* a sample depth should follow the separator, and we should be on it */
1118 if (entry_start > chunkdata + slength)
1119 {
1120 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001121 png_warning(png_ptr, "malformed sPLT chunk");
1122 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001123 }
1124
1125 new_palette.depth = *entry_start++;
1126 entry_size = (new_palette.depth == 8 ? 6 : 10);
1127 data_length = (slength - (entry_start - chunkdata));
1128
1129 /* integrity-check the data length */
1130 if (data_length % entry_size)
1131 {
1132 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001133 png_warning(png_ptr, "sPLT chunk has bad length");
1134 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001135 }
1136
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06001137 new_palette.nentries = (png_int_32) ( data_length / entry_size);
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001138 if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX /
1139 png_sizeof(png_sPLT_entry)))
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001140 {
1141 png_warning(png_ptr, "sPLT chunk too long");
1142 return;
1143 }
1144 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1145 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1146 if (new_palette.entries == NULL)
1147 {
1148 png_warning(png_ptr, "sPLT chunk requires too much memory");
1149 return;
1150 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001151
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001152#ifndef PNG_NO_POINTER_INDEXING
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001153 for (i = 0; i < new_palette.nentries; i++)
1154 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001155 png_sPLT_entryp pp = new_palette.entries + i;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001156
1157 if (new_palette.depth == 8)
1158 {
1159 pp->red = *entry_start++;
1160 pp->green = *entry_start++;
1161 pp->blue = *entry_start++;
1162 pp->alpha = *entry_start++;
1163 }
1164 else
1165 {
1166 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1167 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1168 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1169 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1170 }
1171 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1172 }
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05001173#else
1174 pp = new_palette.entries;
1175 for (i = 0; i < new_palette.nentries; i++)
1176 {
1177
1178 if (new_palette.depth == 8)
1179 {
1180 pp[i].red = *entry_start++;
1181 pp[i].green = *entry_start++;
1182 pp[i].blue = *entry_start++;
1183 pp[i].alpha = *entry_start++;
1184 }
1185 else
1186 {
1187 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1188 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1189 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1190 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1191 }
1192 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1193 }
1194#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001195
1196 /* discard all chunk data except the name and stash that */
1197 new_palette.name = (png_charp)chunkdata;
1198
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001199 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001200
1201 png_free(png_ptr, chunkdata);
1202 png_free(png_ptr, new_palette.entries);
1203}
1204#endif /* PNG_READ_sPLT_SUPPORTED */
1205
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001206#if defined(PNG_READ_tRNS_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001207void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001208png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001209{
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001210 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001211
Andreas Dilger47a0c421997-05-16 02:46:07 -05001212 png_debug(1, "in png_handle_tRNS\n");
1213
Guy Schalnate5a37791996-06-05 15:50:50 -05001214 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1215 png_error(png_ptr, "Missing IHDR before tRNS");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001216 else if (png_ptr->mode & PNG_HAVE_IDAT)
1217 {
1218 png_warning(png_ptr, "Invalid tRNS after IDAT");
1219 png_crc_finish(png_ptr, length);
1220 return;
1221 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001222 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001223 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001224 png_warning(png_ptr, "Duplicate tRNS chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001225 png_crc_finish(png_ptr, length);
1226 return;
1227 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001228
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001229 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Guy Schalnat0d580581995-07-20 02:43:20 -05001230 {
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001231 png_byte buf[2];
Guy Schalnat0d580581995-07-20 02:43:20 -05001232
1233 if (length != 2)
1234 {
Guy Schalnat69b14481996-01-10 02:56:49 -06001235 png_warning(png_ptr, "Incorrect tRNS chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001236 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001237 return;
1238 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001239
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001240 png_crc_read(png_ptr, buf, 2);
1241 png_ptr->num_trans = 1;
1242 png_ptr->trans_values.gray = png_get_uint_16(buf);
1243 }
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001244 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1245 {
1246 png_byte buf[6];
1247
1248 if (length != 6)
1249 {
1250 png_warning(png_ptr, "Incorrect tRNS chunk length");
1251 png_crc_finish(png_ptr, length);
1252 return;
1253 }
1254 png_crc_read(png_ptr, buf, (png_size_t)length);
1255 png_ptr->num_trans = 1;
1256 png_ptr->trans_values.red = png_get_uint_16(buf);
1257 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1258 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1259 }
1260 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1261 {
1262 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1263 {
1264 /* Should be an error, but we can cope with it. */
1265 png_warning(png_ptr, "Missing PLTE before tRNS");
1266 }
1267 if (length > (png_uint_32)png_ptr->num_palette ||
1268 length > PNG_MAX_PALETTE_LENGTH)
1269 {
1270 png_warning(png_ptr, "Incorrect tRNS chunk length");
1271 png_crc_finish(png_ptr, length);
1272 return;
1273 }
1274 if (length == 0)
1275 {
1276 png_warning(png_ptr, "Zero length tRNS chunk");
1277 png_crc_finish(png_ptr, length);
1278 return;
1279 }
1280 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1281 png_ptr->num_trans = (png_uint_16)length;
1282 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001283 else
Guy Schalnate5a37791996-06-05 15:50:50 -05001284 {
1285 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001286 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001287 return;
1288 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001289
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001290 if (png_crc_finish(png_ptr, 0))
1291 return;
1292
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001293 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
Guy Schalnat0d580581995-07-20 02:43:20 -05001294 &(png_ptr->trans_values));
1295}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001296#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001297
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001298#if defined(PNG_READ_bKGD_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001299void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001300png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001301{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001302 png_size_t truelen;
Guy Schalnat0d580581995-07-20 02:43:20 -05001303 png_byte buf[6];
1304
Andreas Dilger47a0c421997-05-16 02:46:07 -05001305 png_debug(1, "in png_handle_bKGD\n");
1306
Guy Schalnate5a37791996-06-05 15:50:50 -05001307 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1308 png_error(png_ptr, "Missing IHDR before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001309 else if (png_ptr->mode & PNG_HAVE_IDAT)
1310 {
1311 png_warning(png_ptr, "Invalid bKGD after IDAT");
1312 png_crc_finish(png_ptr, length);
1313 return;
1314 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001315 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1316 !(png_ptr->mode & PNG_HAVE_PLTE))
1317 {
1318 png_warning(png_ptr, "Missing PLTE before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001319 png_crc_finish(png_ptr, length);
1320 return;
1321 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001322 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001323 {
1324 png_warning(png_ptr, "Duplicate bKGD chunk");
1325 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001326 return;
1327 }
1328
Guy Schalnat0d580581995-07-20 02:43:20 -05001329 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1330 truelen = 1;
1331 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1332 truelen = 6;
1333 else
1334 truelen = 2;
1335
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001336 if (length != truelen)
Guy Schalnat0d580581995-07-20 02:43:20 -05001337 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001338 png_warning(png_ptr, "Incorrect bKGD chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001339 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001340 return;
1341 }
1342
Andreas Dilger47a0c421997-05-16 02:46:07 -05001343 png_crc_read(png_ptr, buf, truelen);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001344 if (png_crc_finish(png_ptr, 0))
1345 return;
1346
Guy Schalnate5a37791996-06-05 15:50:50 -05001347 /* We convert the index value into RGB components so that we can allow
1348 * arbitrary RGB values for background when we have transparency, and
1349 * so it is easy to determine the RGB values of the background color
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001350 * from the info_ptr struct. */
Guy Schalnat0d580581995-07-20 02:43:20 -05001351 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnate5a37791996-06-05 15:50:50 -05001352 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001353 png_ptr->background.index = buf[0];
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001354 if(info_ptr->num_palette)
1355 {
1356 if(buf[0] > info_ptr->num_palette)
1357 {
1358 png_warning(png_ptr, "Incorrect bKGD chunk index value");
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001359 return;
1360 }
1361 png_ptr->background.red =
1362 (png_uint_16)png_ptr->palette[buf[0]].red;
1363 png_ptr->background.green =
1364 (png_uint_16)png_ptr->palette[buf[0]].green;
1365 png_ptr->background.blue =
1366 (png_uint_16)png_ptr->palette[buf[0]].blue;
1367 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001368 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001369 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
Guy Schalnate5a37791996-06-05 15:50:50 -05001370 {
1371 png_ptr->background.red =
1372 png_ptr->background.green =
1373 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -05001374 png_ptr->background.gray = png_get_uint_16(buf);
Guy Schalnate5a37791996-06-05 15:50:50 -05001375 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001376 else
1377 {
1378 png_ptr->background.red = png_get_uint_16(buf);
1379 png_ptr->background.green = png_get_uint_16(buf + 2);
1380 png_ptr->background.blue = png_get_uint_16(buf + 4);
1381 }
1382
Andreas Dilger47a0c421997-05-16 02:46:07 -05001383 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
Guy Schalnat0d580581995-07-20 02:43:20 -05001384}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001385#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001386
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001387#if defined(PNG_READ_hIST_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001388void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001389png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001390{
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001391 unsigned int num, i;
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001392 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
Guy Schalnat0d580581995-07-20 02:43:20 -05001393
Andreas Dilger47a0c421997-05-16 02:46:07 -05001394 png_debug(1, "in png_handle_hIST\n");
1395
Guy Schalnate5a37791996-06-05 15:50:50 -05001396 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1397 png_error(png_ptr, "Missing IHDR before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001398 else if (png_ptr->mode & PNG_HAVE_IDAT)
1399 {
1400 png_warning(png_ptr, "Invalid hIST after IDAT");
1401 png_crc_finish(png_ptr, length);
1402 return;
1403 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001404 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1405 {
1406 png_warning(png_ptr, "Missing PLTE before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001407 png_crc_finish(png_ptr, length);
1408 return;
1409 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001410 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001411 {
1412 png_warning(png_ptr, "Duplicate hIST chunk");
1413 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001414 return;
1415 }
1416
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001417 num = length / 2 ;
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001418 if (num != (unsigned int) png_ptr->num_palette || num >
1419 (unsigned int) PNG_MAX_PALETTE_LENGTH)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001420 {
1421 png_warning(png_ptr, "Incorrect hIST chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001422 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001423 return;
1424 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001425
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001426 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001427 {
1428 png_byte buf[2];
1429
1430 png_crc_read(png_ptr, buf, 2);
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001431 readbuf[i] = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001432 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001433
1434 if (png_crc_finish(png_ptr, 0))
1435 return;
1436
Glenn Randers-Pehrson76e5fd62000-12-28 07:50:05 -06001437 png_set_hIST(png_ptr, info_ptr, readbuf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001438}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001439#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001440
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001441#if defined(PNG_READ_pHYs_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001442void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001443png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001444{
1445 png_byte buf[9];
1446 png_uint_32 res_x, res_y;
1447 int unit_type;
1448
Andreas Dilger47a0c421997-05-16 02:46:07 -05001449 png_debug(1, "in png_handle_pHYs\n");
1450
Guy Schalnate5a37791996-06-05 15:50:50 -05001451 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001452 png_error(png_ptr, "Missing IHDR before pHYs");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001453 else if (png_ptr->mode & PNG_HAVE_IDAT)
1454 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001455 png_warning(png_ptr, "Invalid pHYs after IDAT");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001456 png_crc_finish(png_ptr, length);
1457 return;
1458 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001459 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001460 {
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05001461 png_warning(png_ptr, "Duplicate pHYs chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001462 png_crc_finish(png_ptr, length);
1463 return;
1464 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001465
Guy Schalnat0d580581995-07-20 02:43:20 -05001466 if (length != 9)
1467 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001468 png_warning(png_ptr, "Incorrect pHYs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001469 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001470 return;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001471 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001472
1473 png_crc_read(png_ptr, buf, 9);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001474 if (png_crc_finish(png_ptr, 0))
1475 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001476
1477 res_x = png_get_uint_32(buf);
1478 res_y = png_get_uint_32(buf + 4);
1479 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001480 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
Guy Schalnat0d580581995-07-20 02:43:20 -05001481}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001482#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001483
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001484#if defined(PNG_READ_oFFs_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001485void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001486png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001487{
1488 png_byte buf[9];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001489 png_int_32 offset_x, offset_y;
Guy Schalnat0d580581995-07-20 02:43:20 -05001490 int unit_type;
1491
Andreas Dilger47a0c421997-05-16 02:46:07 -05001492 png_debug(1, "in png_handle_oFFs\n");
1493
Guy Schalnate5a37791996-06-05 15:50:50 -05001494 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1495 png_error(png_ptr, "Missing IHDR before oFFs");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001496 else if (png_ptr->mode & PNG_HAVE_IDAT)
1497 {
1498 png_warning(png_ptr, "Invalid oFFs after IDAT");
1499 png_crc_finish(png_ptr, length);
1500 return;
1501 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001502 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001503 {
1504 png_warning(png_ptr, "Duplicate oFFs chunk");
1505 png_crc_finish(png_ptr, length);
1506 return;
1507 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001508
Guy Schalnat0d580581995-07-20 02:43:20 -05001509 if (length != 9)
1510 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001511 png_warning(png_ptr, "Incorrect oFFs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001512 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001513 return;
1514 }
1515
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001516 png_crc_read(png_ptr, buf, 9);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001517 if (png_crc_finish(png_ptr, 0))
1518 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001519
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001520 offset_x = png_get_int_32(buf);
1521 offset_y = png_get_int_32(buf + 4);
Guy Schalnat0d580581995-07-20 02:43:20 -05001522 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001523 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1524}
1525#endif
1526
1527#if defined(PNG_READ_pCAL_SUPPORTED)
Glenn Randers-Pehrsonff9c9472000-07-11 07:12:36 -05001528/* read the pCAL chunk (described in the PNG Extensions document) */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001529void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001530png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1531{
1532 png_charp purpose;
1533 png_int_32 X0, X1;
1534 png_byte type, nparams;
1535 png_charp buf, units, endptr;
1536 png_charpp params;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001537 png_size_t slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001538 int i;
1539
1540 png_debug(1, "in png_handle_pCAL\n");
1541
1542 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1543 png_error(png_ptr, "Missing IHDR before pCAL");
1544 else if (png_ptr->mode & PNG_HAVE_IDAT)
1545 {
1546 png_warning(png_ptr, "Invalid pCAL after IDAT");
1547 png_crc_finish(png_ptr, length);
1548 return;
1549 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001550 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
Andreas Dilger47a0c421997-05-16 02:46:07 -05001551 {
1552 png_warning(png_ptr, "Duplicate pCAL chunk");
1553 png_crc_finish(png_ptr, length);
1554 return;
1555 }
1556
Glenn Randers-Pehrson4766a242000-07-17 06:17:09 -05001557 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
Andreas Dilger47a0c421997-05-16 02:46:07 -05001558 length + 1);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001559 purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
1560 if (purpose == NULL)
1561 {
1562 png_warning(png_ptr, "No memory for pCAL purpose.");
1563 return;
1564 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001565 slength = (png_size_t)length;
1566 png_crc_read(png_ptr, (png_bytep)purpose, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001567
1568 if (png_crc_finish(png_ptr, 0))
1569 {
1570 png_free(png_ptr, purpose);
1571 return;
1572 }
1573
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001574 purpose[slength] = 0x00; /* null terminate the last string */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001575
1576 png_debug(3, "Finding end of pCAL purpose string\n");
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001577 for (buf = purpose; *buf; buf++)
Glenn Randers-Pehrsond12aa501998-03-13 07:39:39 -06001578 /* empty loop */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001579
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001580 endptr = purpose + slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001581
1582 /* We need to have at least 12 bytes after the purpose string
1583 in order to get the parameter information. */
1584 if (endptr <= buf + 12)
1585 {
1586 png_warning(png_ptr, "Invalid pCAL data");
1587 png_free(png_ptr, purpose);
1588 return;
1589 }
1590
1591 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1592 X0 = png_get_int_32((png_bytep)buf+1);
1593 X1 = png_get_int_32((png_bytep)buf+5);
1594 type = buf[9];
1595 nparams = buf[10];
1596 units = buf + 11;
1597
1598 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1599 /* Check that we have the right number of parameters for known
1600 equation types. */
1601 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1602 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1603 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1604 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1605 {
1606 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1607 png_free(png_ptr, purpose);
1608 return;
1609 }
1610 else if (type >= PNG_EQUATION_LAST)
1611 {
1612 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1613 }
1614
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001615 for (buf = units; *buf; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001616 /* Empty loop to move past the units string. */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001617
1618 png_debug(3, "Allocating pCAL parameters array\n");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001619 params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001620 *png_sizeof(png_charp))) ;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001621 if (params == NULL)
1622 {
1623 png_free(png_ptr, purpose);
1624 png_warning(png_ptr, "No memory for pCAL params.");
1625 return;
1626 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001627
1628 /* Get pointers to the start of each parameter string. */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001629 for (i = 0; i < (int)nparams; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001630 {
1631 buf++; /* Skip the null string terminator from previous parameter. */
1632
1633 png_debug1(3, "Reading pCAL parameter %d\n", i);
Glenn Randers-Pehrsond12aa501998-03-13 07:39:39 -06001634 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001635 /* Empty loop to move past each parameter string */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001636
1637 /* Make sure we haven't run out of data yet */
1638 if (buf > endptr)
1639 {
1640 png_warning(png_ptr, "Invalid pCAL data");
1641 png_free(png_ptr, purpose);
1642 png_free(png_ptr, params);
1643 return;
1644 }
1645 }
1646
1647 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1648 units, params);
1649
1650 png_free(png_ptr, purpose);
1651 png_free(png_ptr, params);
Guy Schalnat0d580581995-07-20 02:43:20 -05001652}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001653#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001654
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001655#if defined(PNG_READ_sCAL_SUPPORTED)
1656/* read the sCAL chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001657void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001658png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1659{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001660 png_charp buffer, ep;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001661#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001662 double width, height;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001663 png_charp vp;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001664#else
1665#ifdef PNG_FIXED_POINT_SUPPORTED
1666 png_charp swidth, sheight;
1667#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001668#endif
1669 png_size_t slength;
1670
1671 png_debug(1, "in png_handle_sCAL\n");
1672
1673 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1674 png_error(png_ptr, "Missing IHDR before sCAL");
1675 else if (png_ptr->mode & PNG_HAVE_IDAT)
1676 {
1677 png_warning(png_ptr, "Invalid sCAL after IDAT");
1678 png_crc_finish(png_ptr, length);
1679 return;
1680 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001681 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001682 {
1683 png_warning(png_ptr, "Duplicate sCAL chunk");
1684 png_crc_finish(png_ptr, length);
1685 return;
1686 }
1687
Glenn Randers-Pehrson4766a242000-07-17 06:17:09 -05001688 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001689 length + 1);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001690 buffer = (png_charp)png_malloc_warn(png_ptr, length + 1);
1691 if (buffer == NULL)
1692 {
1693 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
1694 return;
1695 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001696 slength = (png_size_t)length;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001697 png_crc_read(png_ptr, (png_bytep)buffer, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001698
1699 if (png_crc_finish(png_ptr, 0))
1700 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001701 png_free(png_ptr, buffer);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001702 return;
1703 }
1704
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001705 buffer[slength] = 0x00; /* null terminate the last string */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001706
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001707 ep = buffer + 1; /* skip unit byte */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001708
1709#ifdef PNG_FLOATING_POINT_SUPPORTED
1710 width = strtod(ep, &vp);
1711 if (*vp)
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001712 {
1713 png_warning(png_ptr, "malformed width string in sCAL chunk");
1714 return;
1715 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001716#else
1717#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001718 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1719 if (swidth == NULL)
1720 {
1721 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
1722 return;
1723 }
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001724 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001725#endif
1726#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001727
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001728 for (ep = buffer; *ep; ep++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001729 /* empty loop */ ;
1730 ep++;
1731
1732#ifdef PNG_FLOATING_POINT_SUPPORTED
1733 height = strtod(ep, &vp);
1734 if (*vp)
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001735 {
1736 png_warning(png_ptr, "malformed height string in sCAL chunk");
1737 return;
1738 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001739#else
1740#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001741 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1742 if (swidth == NULL)
1743 {
1744 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
1745 return;
1746 }
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001747 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001748#endif
1749#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001750
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001751 if (buffer + slength < ep
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001752#ifdef PNG_FLOATING_POINT_SUPPORTED
1753 || width <= 0. || height <= 0.
1754#endif
1755 )
1756 {
1757 png_warning(png_ptr, "Invalid sCAL data");
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001758 png_free(png_ptr, buffer);
1759#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001760 png_free(png_ptr, swidth);
1761 png_free(png_ptr, sheight);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001762#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001763 return;
1764 }
1765
1766
1767#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001768 png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1769#else
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001770#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001771 png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1772#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001773#endif
1774
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001775 png_free(png_ptr, buffer);
1776#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1777 png_free(png_ptr, swidth);
1778 png_free(png_ptr, sheight);
1779#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001780}
1781#endif
1782
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001783#if defined(PNG_READ_tIME_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001784void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001785png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001786{
1787 png_byte buf[7];
1788 png_time mod_time;
1789
Andreas Dilger47a0c421997-05-16 02:46:07 -05001790 png_debug(1, "in png_handle_tIME\n");
1791
Guy Schalnate5a37791996-06-05 15:50:50 -05001792 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001793 png_error(png_ptr, "Out of place tIME chunk");
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001794 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001795 {
1796 png_warning(png_ptr, "Duplicate tIME chunk");
1797 png_crc_finish(png_ptr, length);
1798 return;
1799 }
1800
1801 if (png_ptr->mode & PNG_HAVE_IDAT)
1802 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnate5a37791996-06-05 15:50:50 -05001803
Guy Schalnat0d580581995-07-20 02:43:20 -05001804 if (length != 7)
1805 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001806 png_warning(png_ptr, "Incorrect tIME chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001807 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001808 return;
1809 }
1810
1811 png_crc_read(png_ptr, buf, 7);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001812 if (png_crc_finish(png_ptr, 0))
1813 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001814
1815 mod_time.second = buf[6];
1816 mod_time.minute = buf[5];
1817 mod_time.hour = buf[4];
1818 mod_time.day = buf[3];
1819 mod_time.month = buf[2];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001820 mod_time.year = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001821
Andreas Dilger47a0c421997-05-16 02:46:07 -05001822 png_set_tIME(png_ptr, info_ptr, &mod_time);
Guy Schalnat0d580581995-07-20 02:43:20 -05001823}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001824#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001825
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001826#if defined(PNG_READ_tEXt_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001827/* Note: this does not properly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001828void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001829png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001830{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001831 png_textp text_ptr;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001832 png_charp key;
Guy Schalnat6d764711995-12-19 03:22:19 -06001833 png_charp text;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001834 png_uint_32 skip = 0;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001835 png_size_t slength;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001836 int ret;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001837
1838 png_debug(1, "in png_handle_tEXt\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05001839
Guy Schalnate5a37791996-06-05 15:50:50 -05001840 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1841 png_error(png_ptr, "Missing IHDR before tEXt");
1842
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001843 if (png_ptr->mode & PNG_HAVE_IDAT)
1844 png_ptr->mode |= PNG_AFTER_IDAT;
1845
Andreas Dilger47a0c421997-05-16 02:46:07 -05001846#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001847 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001848 {
1849 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001850 skip = length - (png_uint_32)65535L;
1851 length = (png_uint_32)65535L;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001852 }
1853#endif
1854
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001855 key = (png_charp)png_malloc_warn(png_ptr, length + 1);
1856 if (key == NULL)
1857 {
1858 png_warning(png_ptr, "No memory to process text chunk.");
1859 return;
1860 }
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001861 slength = (png_size_t)length;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001862 png_crc_read(png_ptr, (png_bytep)key, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001863
1864 if (png_crc_finish(png_ptr, skip))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001865 {
1866 png_free(png_ptr, key);
1867 return;
1868 }
1869
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001870 key[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05001871
1872 for (text = key; *text; text++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001873 /* empty loop to find end of key */ ;
Guy Schalnat0d580581995-07-20 02:43:20 -05001874
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001875 if (text != key + slength)
Guy Schalnat0d580581995-07-20 02:43:20 -05001876 text++;
1877
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001878 text_ptr = (png_textp)png_malloc_warn(png_ptr,
1879 (png_uint_32)png_sizeof(png_text));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001880 if (text_ptr == NULL)
1881 {
1882 png_warning(png_ptr, "Not enough memory to process text chunk.");
1883 png_free(png_ptr, key);
1884 return;
1885 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001886 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1887 text_ptr->key = key;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001888#ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001889 text_ptr->lang = NULL;
1890 text_ptr->lang_key = NULL;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001891 text_ptr->itxt_length = 0;
1892#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001893 text_ptr->text = text;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001894 text_ptr->text_length = png_strlen(text);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001895
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001896 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001897
Glenn Randers-Pehrsone1eff582001-04-14 20:15:41 -05001898 png_free(png_ptr, key);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001899 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001900 if (ret)
1901 png_warning(png_ptr, "Insufficient memory to process text chunk.");
Guy Schalnat0d580581995-07-20 02:43:20 -05001902}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001903#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001904
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001905#if defined(PNG_READ_zTXt_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001906/* note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001907void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001908png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001909{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001910 png_textp text_ptr;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001911 png_charp chunkdata;
Guy Schalnat6d764711995-12-19 03:22:19 -06001912 png_charp text;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001913 int comp_type;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001914 int ret;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001915 png_size_t slength, prefix_len, data_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001916
1917 png_debug(1, "in png_handle_zTXt\n");
Guy Schalnate5a37791996-06-05 15:50:50 -05001918 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1919 png_error(png_ptr, "Missing IHDR before zTXt");
1920
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001921 if (png_ptr->mode & PNG_HAVE_IDAT)
1922 png_ptr->mode |= PNG_AFTER_IDAT;
1923
Andreas Dilger47a0c421997-05-16 02:46:07 -05001924#ifdef PNG_MAX_MALLOC_64K
1925 /* We will no doubt have problems with chunks even half this size, but
1926 there is no hard and fast rule to tell us where to stop. */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001927 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001928 {
1929 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1930 png_crc_finish(png_ptr, length);
1931 return;
1932 }
1933#endif
1934
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001935 chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1936 if (chunkdata == NULL)
1937 {
1938 png_warning(png_ptr,"Out of memory processing zTXt chunk.");
1939 return;
1940 }
1941 slength = (png_size_t)length;
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001942 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001943 if (png_crc_finish(png_ptr, 0))
1944 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001945 png_free(png_ptr, chunkdata);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001946 return;
1947 }
1948
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001949 chunkdata[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05001950
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001951 for (text = chunkdata; *text; text++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001952 /* empty loop */ ;
1953
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001954 /* zTXt must have some text after the chunkdataword */
1955 if (text == chunkdata + slength)
Guy Schalnat0d580581995-07-20 02:43:20 -05001956 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001957 comp_type = PNG_TEXT_COMPRESSION_NONE;
Guy Schalnat69b14481996-01-10 02:56:49 -06001958 png_warning(png_ptr, "Zero length zTXt chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -05001959 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001960 else
Guy Schalnat0d580581995-07-20 02:43:20 -05001961 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001962 comp_type = *(++text);
Glenn Randers-Pehrsonf05f8032000-12-23 14:27:39 -06001963 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
1964 {
1965 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
1966 comp_type = PNG_TEXT_COMPRESSION_zTXt;
1967 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001968 text++; /* skip the compression_method byte */
Guy Schalnat0d580581995-07-20 02:43:20 -05001969 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001970 prefix_len = text - chunkdata;
Guy Schalnat0d580581995-07-20 02:43:20 -05001971
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001972 chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001973 (png_size_t)length, prefix_len, &data_len);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001974
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001975 text_ptr = (png_textp)png_malloc_warn(png_ptr,
1976 (png_uint_32)png_sizeof(png_text));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001977 if (text_ptr == NULL)
1978 {
1979 png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
1980 png_free(png_ptr, chunkdata);
1981 return;
1982 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001983 text_ptr->compression = comp_type;
1984 text_ptr->key = chunkdata;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001985#ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001986 text_ptr->lang = NULL;
1987 text_ptr->lang_key = NULL;
1988 text_ptr->itxt_length = 0;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001989#endif
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001990 text_ptr->text = chunkdata + prefix_len;
1991 text_ptr->text_length = data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001992
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001993 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001994
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05001995 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001996 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05001997 if (ret)
1998 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001999}
2000#endif
2001
2002#if defined(PNG_READ_iTXt_SUPPORTED)
2003/* note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002004void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002005png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2006{
2007 png_textp text_ptr;
2008 png_charp chunkdata;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002009 png_charp key, lang, text, lang_key;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06002010 int comp_flag;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002011 int comp_type = 0;
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002012 int ret;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002013 png_size_t slength, prefix_len, data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002014
2015 png_debug(1, "in png_handle_iTXt\n");
2016
2017 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2018 png_error(png_ptr, "Missing IHDR before iTXt");
2019
2020 if (png_ptr->mode & PNG_HAVE_IDAT)
2021 png_ptr->mode |= PNG_AFTER_IDAT;
2022
2023#ifdef PNG_MAX_MALLOC_64K
2024 /* We will no doubt have problems with chunks even half this size, but
2025 there is no hard and fast rule to tell us where to stop. */
2026 if (length > (png_uint_32)65535L)
2027 {
2028 png_warning(png_ptr,"iTXt chunk too large to fit in memory");
2029 png_crc_finish(png_ptr, length);
2030 return;
2031 }
2032#endif
2033
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002034 chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2035 if (chunkdata == NULL)
2036 {
2037 png_warning(png_ptr, "No memory to process iTXt chunk.");
2038 return;
2039 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002040 slength = (png_size_t)length;
2041 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002042 if (png_crc_finish(png_ptr, 0))
2043 {
2044 png_free(png_ptr, chunkdata);
2045 return;
2046 }
2047
2048 chunkdata[slength] = 0x00;
2049
2050 for (lang = chunkdata; *lang; lang++)
2051 /* empty loop */ ;
2052 lang++; /* skip NUL separator */
2053
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002054 /* iTXt must have a language tag (possibly empty), two compression bytes,
2055 translated keyword (possibly empty), and possibly some text after the
2056 keyword */
2057
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002058 if (lang >= chunkdata + slength)
2059 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002060 comp_flag = PNG_TEXT_COMPRESSION_NONE;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002061 png_warning(png_ptr, "Zero length iTXt chunk");
2062 }
2063 else
2064 {
2065 comp_flag = *lang++;
2066 comp_type = *lang++;
2067 }
2068
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002069 for (lang_key = lang; *lang_key; lang_key++)
2070 /* empty loop */ ;
2071 lang_key++; /* skip NUL separator */
2072
2073 for (text = lang_key; *text; text++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002074 /* empty loop */ ;
2075 text++; /* skip NUL separator */
2076
2077 prefix_len = text - chunkdata;
2078
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002079 key=chunkdata;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002080 if (comp_flag)
2081 chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06002082 (size_t)length, prefix_len, &data_len);
2083 else
2084 data_len=png_strlen(chunkdata + prefix_len);
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05002085 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2086 (png_uint_32)png_sizeof(png_text));
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002087 if (text_ptr == NULL)
2088 {
2089 png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
2090 png_free(png_ptr, chunkdata);
2091 return;
2092 }
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002093 text_ptr->compression = (int)comp_flag + 1;
2094 text_ptr->lang_key = chunkdata+(lang_key-key);
2095 text_ptr->lang = chunkdata+(lang-key);
2096 text_ptr->itxt_length = data_len;
2097 text_ptr->text_length = 0;
2098 text_ptr->key = chunkdata;
2099 text_ptr->text = chunkdata + prefix_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002100
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002101 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002102
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -05002103 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002104 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002105 if (ret)
2106 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002107}
2108#endif
2109
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002110/* This function is called when we haven't found a handler for a
2111 chunk. If there isn't a problem with the chunk itself (ie bad
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002112 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2113 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2114 case it will be saved away to be written out later. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002115void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002116png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2117{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002118 png_uint_32 skip = 0;
2119
Andreas Dilger47a0c421997-05-16 02:46:07 -05002120 png_debug(1, "in png_handle_unknown\n");
2121
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002122 if (png_ptr->mode & PNG_HAVE_IDAT)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002123 {
2124#ifdef PNG_USE_LOCAL_ARRAYS
2125 PNG_IDAT;
2126#endif
2127 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2128 png_ptr->mode |= PNG_AFTER_IDAT;
2129 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002130
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002131 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
2132
2133 if (!(png_ptr->chunk_name[0] & 0x20))
2134 {
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05002135#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002136 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -05002137 PNG_HANDLE_CHUNK_ALWAYS
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002138#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002139 && png_ptr->read_user_chunk_fn == NULL
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002140#endif
2141 )
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05002142#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002143 png_chunk_error(png_ptr, "unknown critical chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002144 }
2145
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002146#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06002147 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
2148 (png_ptr->read_user_chunk_fn != NULL))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002149 {
2150 png_unknown_chunk chunk;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002151
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002152#ifdef PNG_MAX_MALLOC_64K
2153 if (length > (png_uint_32)65535L)
2154 {
2155 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2156 skip = length - (png_uint_32)65535L;
2157 length = (png_uint_32)65535L;
2158 }
2159#endif
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002160 png_strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002161 chunk.data = (png_bytep)png_malloc(png_ptr, length);
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002162 chunk.size = (png_size_t)length;
2163 png_crc_read(png_ptr, (png_bytep)chunk.data, length);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002164#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002165 if(png_ptr->read_user_chunk_fn != NULL)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002166 {
2167 /* callback to user unknown chunk handler */
2168 if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
2169 {
2170 if (!(png_ptr->chunk_name[0] & 0x20))
2171 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
Glenn Randers-Pehrsondff799e2004-08-07 21:42:49 -05002172 PNG_HANDLE_CHUNK_ALWAYS)
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002173 {
2174 png_free(png_ptr, chunk.data);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002175 png_chunk_error(png_ptr, "unknown critical chunk");
Glenn Randers-Pehrson07748d12002-05-25 11:12:10 -05002176 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002177 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
2178 }
2179 }
2180 else
2181#endif
2182 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002183 png_free(png_ptr, chunk.data);
2184 }
2185 else
2186#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002187 skip = length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002188
2189 png_crc_finish(png_ptr, skip);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002190
2191#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002192 if (&info_ptr == NULL) /* quiet compiler warnings about unused info_ptr */
2193 return;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002194#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002195}
2196
2197/* This function is called to verify that a chunk name is valid.
2198 This function can't have the "critical chunk check" incorporated
Andreas Dilger47a0c421997-05-16 02:46:07 -05002199 into it, since in the future we will need to be able to call user
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002200 functions to handle unknown critical chunks after we check that
2201 the chunk name itself is valid. */
Andreas Dilger47a0c421997-05-16 02:46:07 -05002202
Glenn Randers-Pehrson5b5dcf82004-07-17 22:45:44 -05002203#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
Andreas Dilger47a0c421997-05-16 02:46:07 -05002204
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002205void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002206png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2207{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002208 png_debug(1, "in png_check_chunk_name\n");
2209 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2210 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002211 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06002212 png_chunk_error(png_ptr, "invalid chunk type");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002213 }
2214}
2215
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002216/* Combines the row recently read in with the existing pixels in the
2217 row. This routine takes care of alpha and transparency if requested.
Guy Schalnat0d580581995-07-20 02:43:20 -05002218 This routine also handles the two methods of progressive display
2219 of interlaced images, depending on the mask value.
2220 The mask value describes which pixels are to be combined with
2221 the row. The pattern always repeats every 8 pixels, so just 8
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002222 bits are needed. A one indicates the pixel is to be combined,
Guy Schalnat0d580581995-07-20 02:43:20 -05002223 a zero indicates the pixel is to be skipped. This is in addition
2224 to any alpha or transparency value associated with the pixel. If
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002225 you want all pixels to be combined, pass 0xff (255) in mask. */
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002226#ifndef PNG_HAVE_MMX_COMBINE_ROW
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002227void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002228png_combine_row(png_structp png_ptr, png_bytep row, int mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002229{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002230 png_debug(1,"in png_combine_row\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05002231 if (mask == 0xff)
2232 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002233 png_memcpy(row, png_ptr->row_buf + 1,
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002234 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
Guy Schalnat0d580581995-07-20 02:43:20 -05002235 }
2236 else
2237 {
2238 switch (png_ptr->row_info.pixel_depth)
2239 {
2240 case 1:
2241 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002242 png_bytep sp = png_ptr->row_buf + 1;
2243 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002244 int s_inc, s_start, s_end;
2245 int m = 0x80;
2246 int shift;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002247 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002248 png_uint_32 row_width = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05002249
Andreas Dilger47a0c421997-05-16 02:46:07 -05002250#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2251 if (png_ptr->transformations & PNG_PACKSWAP)
Andreas Dilger47a0c421997-05-16 02:46:07 -05002252 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002253 s_start = 0;
2254 s_end = 7;
2255 s_inc = 1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002256 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002257 else
2258#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002259 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002260 s_start = 7;
2261 s_end = 0;
2262 s_inc = -1;
2263 }
2264
2265 shift = s_start;
2266
2267 for (i = 0; i < row_width; i++)
2268 {
2269 if (m & mask)
2270 {
2271 int value;
2272
2273 value = (*sp >> shift) & 0x01;
2274 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2275 *dp |= (png_byte)(value << shift);
2276 }
2277
2278 if (shift == s_end)
2279 {
2280 shift = s_start;
2281 sp++;
2282 dp++;
2283 }
2284 else
2285 shift += s_inc;
2286
2287 if (m == 1)
2288 m = 0x80;
2289 else
2290 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002291 }
2292 break;
2293 }
2294 case 2:
2295 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002296 png_bytep sp = png_ptr->row_buf + 1;
2297 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002298 int s_start, s_end, s_inc;
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002299 int m = 0x80;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002300 int shift;
2301 png_uint_32 i;
2302 png_uint_32 row_width = png_ptr->width;
2303 int value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002304
Andreas Dilger47a0c421997-05-16 02:46:07 -05002305#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2306 if (png_ptr->transformations & PNG_PACKSWAP)
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002307 {
2308 s_start = 0;
2309 s_end = 6;
2310 s_inc = 2;
2311 }
2312 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002313#endif
2314 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002315 s_start = 6;
2316 s_end = 0;
2317 s_inc = -2;
2318 }
2319
2320 shift = s_start;
2321
2322 for (i = 0; i < row_width; i++)
2323 {
2324 if (m & mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002325 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002326 value = (*sp >> shift) & 0x03;
2327 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2328 *dp |= (png_byte)(value << shift);
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002329 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002330
2331 if (shift == s_end)
2332 {
2333 shift = s_start;
2334 sp++;
2335 dp++;
2336 }
2337 else
2338 shift += s_inc;
2339 if (m == 1)
2340 m = 0x80;
2341 else
2342 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002343 }
2344 break;
2345 }
2346 case 4:
2347 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002348 png_bytep sp = png_ptr->row_buf + 1;
2349 png_bytep dp = row;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002350 int s_start, s_end, s_inc;
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002351 int m = 0x80;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002352 int shift;
2353 png_uint_32 i;
2354 png_uint_32 row_width = png_ptr->width;
2355 int value;
Guy Schalnat0d580581995-07-20 02:43:20 -05002356
Andreas Dilger47a0c421997-05-16 02:46:07 -05002357#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2358 if (png_ptr->transformations & PNG_PACKSWAP)
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002359 {
2360 s_start = 0;
2361 s_end = 4;
2362 s_inc = 4;
2363 }
2364 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002365#endif
2366 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002367 s_start = 4;
2368 s_end = 0;
2369 s_inc = -4;
2370 }
2371 shift = s_start;
2372
2373 for (i = 0; i < row_width; i++)
2374 {
2375 if (m & mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002376 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002377 value = (*sp >> shift) & 0xf;
2378 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2379 *dp |= (png_byte)(value << shift);
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002380 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002381
2382 if (shift == s_end)
2383 {
2384 shift = s_start;
2385 sp++;
2386 dp++;
2387 }
2388 else
2389 shift += s_inc;
2390 if (m == 1)
2391 m = 0x80;
2392 else
2393 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002394 }
2395 break;
2396 }
2397 default:
2398 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002399 png_bytep sp = png_ptr->row_buf + 1;
2400 png_bytep dp = row;
2401 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2402 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002403 png_uint_32 row_width = png_ptr->width;
2404 png_byte m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05002405
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002406
2407 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002408 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002409 if (m & mask)
2410 {
2411 png_memcpy(dp, sp, pixel_bytes);
2412 }
2413
2414 sp += pixel_bytes;
2415 dp += pixel_bytes;
2416
2417 if (m == 1)
2418 m = 0x80;
2419 else
2420 m >>= 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05002421 }
2422 break;
2423 }
2424 }
2425 }
2426}
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002427#endif /* !PNG_HAVE_MMX_COMBINE_ROW */
Guy Schalnat0d580581995-07-20 02:43:20 -05002428
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002429#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002430#ifndef PNG_HAVE_MMX_READ_INTERLACE /* else in pngvcrd.c, pnggccrd.c */
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05002431/* OLD pre-1.0.9 interface:
2432void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2433 png_uint_32 transformations)
2434 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002435void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002436png_do_read_interlace(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002437{
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002438 png_row_infop row_info = &(png_ptr->row_info);
2439 png_bytep row = png_ptr->row_buf + 1;
2440 int pass = png_ptr->pass;
2441 png_uint_32 transformations = png_ptr->transformations;
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002442#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002443 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002444 /* offset to next interlace block */
2445 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002446#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002447
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002448 png_debug(1,"in png_do_read_interlace (stock C version)\n");
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002449 if (row != NULL && row_info != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002450 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002451 png_uint_32 final_width;
2452
2453 final_width = row_info->width * png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05002454
2455 switch (row_info->pixel_depth)
2456 {
2457 case 1:
2458 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002459 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2460 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002461 int sshift, dshift;
2462 int s_start, s_end, s_inc;
2463 int jstop = png_pass_inc[pass];
2464 png_byte v;
Guy Schalnat0d580581995-07-20 02:43:20 -05002465 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002466 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -05002467
Andreas Dilger47a0c421997-05-16 02:46:07 -05002468#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2469 if (transformations & PNG_PACKSWAP)
2470 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002471 sshift = (int)((row_info->width + 7) & 0x07);
2472 dshift = (int)((final_width + 7) & 0x07);
2473 s_start = 7;
2474 s_end = 0;
2475 s_inc = -1;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002476 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002477 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002478#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002479 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002480 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2481 dshift = 7 - (int)((final_width + 7) & 0x07);
2482 s_start = 0;
2483 s_end = 7;
2484 s_inc = 1;
2485 }
Glenn Randers-Pehrson5dd2b8e2004-11-24 07:50:16 -06002486
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002487 for (i = 0; i < row_info->width; i++)
2488 {
2489 v = (png_byte)((*sp >> sshift) & 0x01);
2490 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002491 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002492 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2493 *dp |= (png_byte)(v << dshift);
2494 if (dshift == s_end)
2495 {
2496 dshift = s_start;
2497 dp--;
2498 }
2499 else
2500 dshift += s_inc;
2501 }
2502 if (sshift == s_end)
2503 {
2504 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002505 sp--;
2506 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002507 else
2508 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002509 }
2510 break;
2511 }
2512 case 2:
2513 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002514 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2515 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2516 int sshift, dshift;
2517 int s_start, s_end, s_inc;
2518 int jstop = png_pass_inc[pass];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002519 png_uint_32 i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002520
Andreas Dilger47a0c421997-05-16 02:46:07 -05002521#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2522 if (transformations & PNG_PACKSWAP)
2523 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002524 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2525 dshift = (int)(((final_width + 3) & 0x03) << 1);
2526 s_start = 6;
2527 s_end = 0;
2528 s_inc = -2;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002529 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002530 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002531#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002532 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002533 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2534 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2535 s_start = 0;
2536 s_end = 6;
2537 s_inc = 2;
2538 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002539
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002540 for (i = 0; i < row_info->width; i++)
2541 {
2542 png_byte v;
2543 int j;
2544
2545 v = (png_byte)((*sp >> sshift) & 0x03);
2546 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002547 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002548 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2549 *dp |= (png_byte)(v << dshift);
2550 if (dshift == s_end)
2551 {
2552 dshift = s_start;
2553 dp--;
2554 }
2555 else
2556 dshift += s_inc;
2557 }
2558 if (sshift == s_end)
2559 {
2560 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002561 sp--;
2562 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002563 else
2564 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002565 }
2566 break;
2567 }
2568 case 4:
2569 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002570 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2571 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002572 int sshift, dshift;
2573 int s_start, s_end, s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002574 png_uint_32 i;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002575 int jstop = png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05002576
Andreas Dilger47a0c421997-05-16 02:46:07 -05002577#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2578 if (transformations & PNG_PACKSWAP)
2579 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002580 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2581 dshift = (int)(((final_width + 1) & 0x01) << 2);
2582 s_start = 4;
2583 s_end = 0;
2584 s_inc = -4;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002585 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002586 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002587#endif
2588 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002589 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2590 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2591 s_start = 0;
2592 s_end = 4;
2593 s_inc = 4;
2594 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002595
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002596 for (i = 0; i < row_info->width; i++)
2597 {
2598 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2599 int j;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002600
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002601 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002602 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002603 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2604 *dp |= (png_byte)(v << dshift);
2605 if (dshift == s_end)
2606 {
2607 dshift = s_start;
2608 dp--;
2609 }
2610 else
2611 dshift += s_inc;
2612 }
2613 if (sshift == s_end)
2614 {
2615 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002616 sp--;
2617 }
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002618 else
2619 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002620 }
2621 break;
2622 }
2623 default:
2624 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002625 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2626 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002627 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05002628
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002629 int jstop = png_pass_inc[pass];
2630 png_uint_32 i;
2631
2632 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002633 {
Glenn Randers-Pehrsonc3dda6d2004-11-27 18:22:29 -06002634 png_byte v[8];
2635 int j;
2636
2637 png_memcpy(v, sp, pixel_bytes);
2638 for (j = 0; j < jstop; j++)
2639 {
2640 png_memcpy(dp, v, pixel_bytes);
2641 dp -= pixel_bytes;
2642 }
2643 sp -= pixel_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05002644 }
2645 break;
2646 }
2647 }
2648 row_info->width = final_width;
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002649 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
Guy Schalnat0d580581995-07-20 02:43:20 -05002650 }
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05002651#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002652 if (&transformations == NULL) /* silence compiler warning */
2653 return;
Glenn Randers-Pehrson104622b2000-05-29 08:58:03 -05002654#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002655}
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002656#endif /* !PNG_HAVE_MMX_READ_INTERLACE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002657#endif /* PNG_READ_INTERLACING_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -05002658
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002659#ifndef PNG_HAVE_MMX_READ_FILTER_ROW
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002660void /* PRIVATE */
Glenn Randers-Pehrson231e6872001-01-12 15:13:06 -06002661png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002662 png_bytep prev_row, int filter)
2663{
2664 png_debug(1, "in png_read_filter_row\n");
Glenn Randers-Pehrson4766a242000-07-17 06:17:09 -05002665 png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002666 switch (filter)
2667 {
2668 case PNG_FILTER_VALUE_NONE:
2669 break;
2670 case PNG_FILTER_VALUE_SUB:
2671 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002672 png_uint_32 i;
2673 png_uint_32 istop = row_info->rowbytes;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002674 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002675 png_bytep rp = row + bpp;
2676 png_bytep lp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002677
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002678 for (i = bpp; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002679 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002680 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2681 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002682 }
2683 break;
2684 }
2685 case PNG_FILTER_VALUE_UP:
2686 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002687 png_uint_32 i;
2688 png_uint_32 istop = row_info->rowbytes;
2689 png_bytep rp = row;
2690 png_bytep pp = prev_row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002691
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002692 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002693 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002694 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2695 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002696 }
2697 break;
2698 }
2699 case PNG_FILTER_VALUE_AVG:
2700 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002701 png_uint_32 i;
2702 png_bytep rp = row;
2703 png_bytep pp = prev_row;
2704 png_bytep lp = row;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002705 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002706 png_uint_32 istop = row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002707
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002708 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002709 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002710 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002711 ((int)(*pp++) / 2 )) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002712 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002713 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002714
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002715 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002716 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002717 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002718 (int)(*pp++ + *lp++) / 2 ) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002719 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002720 }
2721 break;
2722 }
2723 case PNG_FILTER_VALUE_PAETH:
2724 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002725 png_uint_32 i;
2726 png_bytep rp = row;
2727 png_bytep pp = prev_row;
2728 png_bytep lp = row;
2729 png_bytep cp = prev_row;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002730 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002731 png_uint_32 istop=row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002732
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002733 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002734 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002735 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2736 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002737 }
2738
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002739 for (i = 0; i < istop; i++) /* use leftover rp,pp */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002740 {
2741 int a, b, c, pa, pb, pc, p;
2742
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002743 a = *lp++;
2744 b = *pp++;
2745 c = *cp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002746
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002747 p = b - c;
2748 pc = a - c;
2749
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002750#ifdef PNG_USE_ABS
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002751 pa = abs(p);
2752 pb = abs(pc);
2753 pc = abs(p + pc);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002754#else
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002755 pa = p < 0 ? -p : p;
2756 pb = pc < 0 ? -pc : pc;
2757 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002758#endif
2759
2760 /*
2761 if (pa <= pb && pa <= pc)
2762 p = a;
2763 else if (pb <= pc)
2764 p = b;
2765 else
2766 p = c;
2767 */
2768
2769 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2770
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002771 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2772 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002773 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002774 break;
2775 }
2776 default:
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002777 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2778 *row=0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002779 break;
2780 }
2781}
Glenn Randers-Pehrson17218292006-04-20 07:20:46 -05002782#endif /* !PNG_HAVE_MMX_READ_FILTER_ROW */
Guy Schalnat0d580581995-07-20 02:43:20 -05002783
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002784void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002785png_read_finish_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002786{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002787#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002788 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002789
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002790 /* start of interlace block */
2791 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002792
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002793 /* offset to next interlace block */
2794 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002795
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002796 /* start of interlace block in the y direction */
2797 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002798
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002799 /* offset to next interlace block in the y direction */
2800 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002801#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002802
Andreas Dilger47a0c421997-05-16 02:46:07 -05002803 png_debug(1, "in png_read_finish_row\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05002804 png_ptr->row_number++;
2805 if (png_ptr->row_number < png_ptr->num_rows)
2806 return;
2807
2808 if (png_ptr->interlaced)
2809 {
2810 png_ptr->row_number = 0;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002811 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05002812 do
2813 {
2814 png_ptr->pass++;
2815 if (png_ptr->pass >= 7)
2816 break;
2817 png_ptr->iwidth = (png_ptr->width +
2818 png_pass_inc[png_ptr->pass] - 1 -
2819 png_pass_start[png_ptr->pass]) /
2820 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002821
2822 png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
2823 png_ptr->iwidth) + 1;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002824
Guy Schalnat0d580581995-07-20 02:43:20 -05002825 if (!(png_ptr->transformations & PNG_INTERLACE))
2826 {
2827 png_ptr->num_rows = (png_ptr->height +
2828 png_pass_yinc[png_ptr->pass] - 1 -
2829 png_pass_ystart[png_ptr->pass]) /
2830 png_pass_yinc[png_ptr->pass];
2831 if (!(png_ptr->num_rows))
2832 continue;
2833 }
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002834 else /* if (png_ptr->transformations & PNG_INTERLACE) */
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002835 break;
Guy Schalnat0d580581995-07-20 02:43:20 -05002836 } while (png_ptr->iwidth == 0);
2837
2838 if (png_ptr->pass < 7)
2839 return;
2840 }
2841
Guy Schalnate5a37791996-06-05 15:50:50 -05002842 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
Guy Schalnat0d580581995-07-20 02:43:20 -05002843 {
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002844#ifdef PNG_USE_LOCAL_ARRAYS
2845 PNG_IDAT;
2846#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002847 char extra;
2848 int ret;
2849
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002850 png_ptr->zstream.next_out = (Byte *)&extra;
2851 png_ptr->zstream.avail_out = (uInt)1;
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -06002852 for(;;)
Guy Schalnat0d580581995-07-20 02:43:20 -05002853 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002854 if (!(png_ptr->zstream.avail_in))
Guy Schalnat0d580581995-07-20 02:43:20 -05002855 {
2856 while (!png_ptr->idat_size)
2857 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002858 png_byte chunk_length[4];
Guy Schalnat0d580581995-07-20 02:43:20 -05002859
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002860 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -05002861
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002862 png_read_data(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05002863 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnat0d580581995-07-20 02:43:20 -05002864 png_reset_crc(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002865 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002866 if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
Guy Schalnat6d764711995-12-19 03:22:19 -06002867 png_error(png_ptr, "Not enough image data");
Guy Schalnat0d580581995-07-20 02:43:20 -05002868
2869 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002870 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2871 png_ptr->zstream.next_in = png_ptr->zbuf;
Guy Schalnat0d580581995-07-20 02:43:20 -05002872 if (png_ptr->zbuf_size > png_ptr->idat_size)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002873 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2874 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2875 png_ptr->idat_size -= png_ptr->zstream.avail_in;
Guy Schalnat0d580581995-07-20 02:43:20 -05002876 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002877 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnat0d580581995-07-20 02:43:20 -05002878 if (ret == Z_STREAM_END)
2879 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002880 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
Guy Schalnat0d580581995-07-20 02:43:20 -05002881 png_ptr->idat_size)
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05002882 png_warning(png_ptr, "Extra compressed data");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002883 png_ptr->mode |= PNG_AFTER_IDAT;
2884 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Guy Schalnat0d580581995-07-20 02:43:20 -05002885 break;
2886 }
2887 if (ret != Z_OK)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002888 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
Guy Schalnate5a37791996-06-05 15:50:50 -05002889 "Decompression Error");
Guy Schalnat0d580581995-07-20 02:43:20 -05002890
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002891 if (!(png_ptr->zstream.avail_out))
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05002892 {
2893 png_warning(png_ptr, "Extra compressed data.");
2894 png_ptr->mode |= PNG_AFTER_IDAT;
2895 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2896 break;
2897 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002898
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -06002899 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002900 png_ptr->zstream.avail_out = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002901 }
2902
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002903 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05002904 png_warning(png_ptr, "Extra compression data");
Guy Schalnat0d580581995-07-20 02:43:20 -05002905
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002906 inflateReset(&png_ptr->zstream);
Guy Schalnat0d580581995-07-20 02:43:20 -05002907
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002908 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnat0d580581995-07-20 02:43:20 -05002909}
2910
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002911void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002912png_read_start_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002913{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002914#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002915 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002916
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002917 /* start of interlace block */
2918 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002919
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002920 /* offset to next interlace block */
2921 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002922
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002923 /* start of interlace block in the y direction */
2924 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002925
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002926 /* offset to next interlace block in the y direction */
2927 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002928#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002929
Guy Schalnat0d580581995-07-20 02:43:20 -05002930 int max_pixel_depth;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002931 png_uint_32 row_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05002932
Andreas Dilger47a0c421997-05-16 02:46:07 -05002933 png_debug(1, "in png_read_start_row\n");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002934 png_ptr->zstream.avail_in = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002935 png_init_read_transformations(png_ptr);
2936 if (png_ptr->interlaced)
2937 {
2938 if (!(png_ptr->transformations & PNG_INTERLACE))
2939 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2940 png_pass_ystart[0]) / png_pass_yinc[0];
2941 else
2942 png_ptr->num_rows = png_ptr->height;
2943
2944 png_ptr->iwidth = (png_ptr->width +
2945 png_pass_inc[png_ptr->pass] - 1 -
2946 png_pass_start[png_ptr->pass]) /
2947 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002948
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05002949 row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;
2950
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002951 png_ptr->irowbytes = (png_size_t)row_bytes;
2952 if((png_uint_32)png_ptr->irowbytes != row_bytes)
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002953 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
Guy Schalnat0d580581995-07-20 02:43:20 -05002954 }
2955 else
2956 {
2957 png_ptr->num_rows = png_ptr->height;
2958 png_ptr->iwidth = png_ptr->width;
2959 png_ptr->irowbytes = png_ptr->rowbytes + 1;
2960 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002961 max_pixel_depth = png_ptr->pixel_depth;
2962
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002963#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05002964 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05002965 max_pixel_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002966#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002967
Guy Schalnate5a37791996-06-05 15:50:50 -05002968#if defined(PNG_READ_EXPAND_SUPPORTED)
2969 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05002970 {
2971 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2972 {
2973 if (png_ptr->num_trans)
2974 max_pixel_depth = 32;
2975 else
2976 max_pixel_depth = 24;
2977 }
2978 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2979 {
2980 if (max_pixel_depth < 8)
2981 max_pixel_depth = 8;
2982 if (png_ptr->num_trans)
2983 max_pixel_depth *= 2;
2984 }
2985 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2986 {
2987 if (png_ptr->num_trans)
2988 {
2989 max_pixel_depth *= 4;
2990 max_pixel_depth /= 3;
2991 }
2992 }
2993 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002994#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002995
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002996#if defined(PNG_READ_FILLER_SUPPORTED)
2997 if (png_ptr->transformations & (PNG_FILLER))
Guy Schalnat0d580581995-07-20 02:43:20 -05002998 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002999 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3000 max_pixel_depth = 32;
3001 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003002 {
3003 if (max_pixel_depth <= 8)
3004 max_pixel_depth = 16;
3005 else
3006 max_pixel_depth = 32;
3007 }
3008 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3009 {
3010 if (max_pixel_depth <= 32)
3011 max_pixel_depth = 32;
3012 else
3013 max_pixel_depth = 64;
3014 }
Guy Schalnat0d580581995-07-20 02:43:20 -05003015 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003016#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003017
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003018#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05003019 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3020 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003021 if (
3022#if defined(PNG_READ_EXPAND_SUPPORTED)
3023 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3024#endif
3025#if defined(PNG_READ_FILLER_SUPPORTED)
3026 (png_ptr->transformations & (PNG_FILLER)) ||
3027#endif
3028 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
Guy Schalnat0d580581995-07-20 02:43:20 -05003029 {
3030 if (max_pixel_depth <= 16)
3031 max_pixel_depth = 32;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003032 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003033 max_pixel_depth = 64;
3034 }
3035 else
3036 {
3037 if (max_pixel_depth <= 8)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06003038 {
3039 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3040 max_pixel_depth = 32;
3041 else
3042 max_pixel_depth = 24;
3043 }
3044 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3045 max_pixel_depth = 64;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06003046 else
Guy Schalnat0d580581995-07-20 02:43:20 -05003047 max_pixel_depth = 48;
3048 }
3049 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05003050#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003051
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05003052#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3053defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05003054 if(png_ptr->transformations & PNG_USER_TRANSFORM)
3055 {
3056 int user_pixel_depth=png_ptr->user_transform_depth*
3057 png_ptr->user_transform_channels;
3058 if(user_pixel_depth > max_pixel_depth)
3059 max_pixel_depth=user_pixel_depth;
3060 }
3061#endif
3062
Guy Schalnat0d580581995-07-20 02:43:20 -05003063 /* align the width on the next larger 8 pixels. Mainly used
3064 for interlacing */
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003065 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
Guy Schalnat0d580581995-07-20 02:43:20 -05003066 /* calculate the maximum bytes needed, adding a byte and a pixel
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05003067 for safety's sake */
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05003068 row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) +
Guy Schalnat0d580581995-07-20 02:43:20 -05003069 1 + ((max_pixel_depth + 7) >> 3);
3070#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05003071 if (row_bytes > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05003072 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05003073#endif
Glenn Randers-Pehrson1b8e5672001-08-25 06:46:06 -05003074 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
3075 png_ptr->row_buf = png_ptr->big_row_buf+32;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -05003076#if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05003077 png_ptr->row_buf_size = row_bytes;
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -05003078#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05003079
3080#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003081 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05003082 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05003083#endif
Glenn Randers-Pehrson78067772004-11-02 21:49:39 -06003084 if ((png_uint_32)png_ptr->rowbytes > PNG_SIZE_MAX - 1)
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05003085 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06003086 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3087 png_ptr->rowbytes + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05003088
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06003089 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05003090
Glenn Randers-Pehrson4766a242000-07-17 06:17:09 -05003091 png_debug1(3, "width = %lu,\n", png_ptr->width);
3092 png_debug1(3, "height = %lu,\n", png_ptr->height);
3093 png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
3094 png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
3095 png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
3096 png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05003097
Guy Schalnate5a37791996-06-05 15:50:50 -05003098 png_ptr->flags |= PNG_FLAG_ROW_INIT;
Guy Schalnat0d580581995-07-20 02:43:20 -05003099}
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06003100#endif /* PNG_READ_SUPPORTED */