blob: e05c52ed6b5e188267af37e5667d89f397ef3013 [file] [log] [blame]
Guy Schalnat0d580581995-07-20 02:43:20 -05001
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-Pehrsonec61c232000-05-16 06:17:36 -05004 * libpng 1.0.7beta13 - May 16, 2000
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
7 * Copyright (c) 1996, 1997 Andreas Dilger
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06008 * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
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
14#define PNG_INTERNAL
15#include "png.h"
16
Andreas Dilger47a0c421997-05-16 02:46:07 -050017#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050018/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050019png_uint_32 /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -060020png_get_uint_32(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050021{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050022 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
Guy Schalnat0d580581995-07-20 02:43:20 -050023 ((png_uint_32)(*(buf + 1)) << 16) +
24 ((png_uint_32)(*(buf + 2)) << 8) +
25 (png_uint_32)(*(buf + 3));
26
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060027 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050028}
29
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -060030#if defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_oFFs_SUPPORTED)
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050031/* Grab a signed 32-bit integer from a buffer in big-endian format. The
Andreas Dilger47a0c421997-05-16 02:46:07 -050032 * data is stored in the PNG file in two's complement format, and it is
33 * assumed that the machine format for signed integers is the same. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050034png_int_32 /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -050035png_get_int_32(png_bytep buf)
36{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050037 png_int_32 i = ((png_int_32)(*buf) << 24) +
Andreas Dilger47a0c421997-05-16 02:46:07 -050038 ((png_int_32)(*(buf + 1)) << 16) +
39 ((png_int_32)(*(buf + 2)) << 8) +
40 (png_int_32)(*(buf + 3));
41
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060042 return (i);
Andreas Dilger47a0c421997-05-16 02:46:07 -050043}
44#endif /* PNG_READ_pCAL_SUPPORTED */
45
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050046/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050047png_uint_16 /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -060048png_get_uint_16(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050049{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050050 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060051 (png_uint_16)(*(buf + 1)));
Guy Schalnat0d580581995-07-20 02:43:20 -050052
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060053 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050054}
Andreas Dilger47a0c421997-05-16 02:46:07 -050055#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -050056
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060057/* Read data, and (optionally) run it through the CRC. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050058void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -050059png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
Guy Schalnat0d580581995-07-20 02:43:20 -050060{
Guy Schalnat6d764711995-12-19 03:22:19 -060061 png_read_data(png_ptr, buf, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -050062 png_calculate_crc(png_ptr, buf, length);
Guy Schalnat0d580581995-07-20 02:43:20 -050063}
64
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060065/* Optionally skip data and then check the CRC. Depending on whether we
66 are reading a ancillary or critical chunk, and how the program has set
Andreas Dilger47a0c421997-05-16 02:46:07 -050067 things up, we may calculate the CRC on the data and print a message.
68 Returns '1' if there was a CRC error, '0' otherwise. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050069int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060070png_crc_finish(png_structp png_ptr, png_uint_32 skip)
Guy Schalnat0d580581995-07-20 02:43:20 -050071{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050072 png_size_t i;
73 png_size_t istop = png_ptr->zbuf_size;
Guy Schalnat0d580581995-07-20 02:43:20 -050074
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -050075 for (i = (png_size_t)skip; i > istop; i -= istop)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060076 {
Andreas Dilger47a0c421997-05-16 02:46:07 -050077 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
Guy Schalnat0d580581995-07-20 02:43:20 -050078 }
79 if (i)
80 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050081 png_crc_read(png_ptr, png_ptr->zbuf, i);
Guy Schalnat0d580581995-07-20 02:43:20 -050082 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060083
Andreas Dilger47a0c421997-05-16 02:46:07 -050084 if (png_crc_error(png_ptr))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060085 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -060086 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060087 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
88 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -060089 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060090 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -060091 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060092 }
93 else
94 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -060095 png_chunk_error(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060096 }
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060097 return (1);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060098 }
99
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600100 return (0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500101}
102
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600103/* Compare the CRC stored in the PNG file with that calculated by libpng from
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600104 the data it has read thus far. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500105int /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600106png_crc_error(png_structp png_ptr)
107{
108 png_byte crc_bytes[4];
109 png_uint_32 crc;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500110 int need_crc = 1;
111
112 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
113 {
114 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
115 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
116 need_crc = 0;
117 }
118 else /* critical */
119 {
120 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
121 need_crc = 0;
122 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600123
124 png_read_data(png_ptr, crc_bytes, 4);
125
Andreas Dilger47a0c421997-05-16 02:46:07 -0500126 if (need_crc)
127 {
128 crc = png_get_uint_32(crc_bytes);
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600129 return ((int)(crc != png_ptr->crc));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500130 }
131 else
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600132 return (0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600133}
134
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600135#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500136 defined(PNG_READ_iCCP_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600137/*
138 * Decompress trailing data in a chunk. The assumption is that chunkdata
139 * points at an allocated area holding the contents of a chunk with a
140 * trailing compressed part. What we get back is an allocated area
141 * holding the original prefix part and an uncompressed version of the
142 * trailing part (the malloc area passed in is freed).
143 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500144png_charp /* PRIVATE */
145png_decompress_chunk(png_structp png_ptr, int comp_type,
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600146 png_charp chunkdata, png_size_t chunklength,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600147 png_size_t prefix_size, png_size_t *newlength)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600148{
149 static char msg[] = "Error decoding compressed text";
150 png_charp text = NULL;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600151 png_size_t text_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600152
153 if (comp_type == PNG_TEXT_COMPRESSION_zTXt)
154 {
155 png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
156 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
157 png_ptr->zstream.next_out = png_ptr->zbuf;
158 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
159
160 text_size = 0;
161 text = NULL;
162
163 while (png_ptr->zstream.avail_in)
164 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600165 int ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600166 if (ret != Z_OK && ret != Z_STREAM_END)
167 {
168 if (png_ptr->zstream.msg != NULL)
169 png_warning(png_ptr, png_ptr->zstream.msg);
170 else
171 png_warning(png_ptr, msg);
172 inflateReset(&png_ptr->zstream);
173 png_ptr->zstream.avail_in = 0;
174
175 if (text == NULL)
176 {
177 text_size = prefix_size + sizeof(msg) + 1;
178 text = (png_charp)png_malloc(png_ptr, text_size);
179 png_memcpy(text, chunkdata, prefix_size);
180 }
181
182 text[text_size - 1] = 0x00;
183
184 /* Copy what we can of the error message into the text chunk */
185 text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
186 text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
187 png_memcpy(text + prefix_size, msg, text_size + 1);
188 break;
189 }
190 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
191 {
192 if (text == NULL)
193 {
194 text_size = prefix_size +
195 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
196 text = (png_charp)png_malloc(png_ptr, text_size + 1);
197 png_memcpy(text + prefix_size, png_ptr->zbuf,
198 text_size - prefix_size);
199 png_memcpy(text, chunkdata, prefix_size);
200 *(text + text_size) = 0x00;
201 }
202 else
203 {
204 png_charp tmp;
205
206 tmp = text;
207 text = (png_charp)png_malloc(png_ptr, (png_uint_32)(text_size +
208 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
209 png_memcpy(text, tmp, text_size);
210 png_free(png_ptr, tmp);
211 png_memcpy(text + text_size, png_ptr->zbuf,
212 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
213 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
214 *(text + text_size) = 0x00;
215 }
216 if (ret == Z_STREAM_END)
217 break;
218 else
219 {
220 png_ptr->zstream.next_out = png_ptr->zbuf;
221 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
222 }
223 }
224 }
225
226 inflateReset(&png_ptr->zstream);
227 png_ptr->zstream.avail_in = 0;
228
229 png_free(png_ptr, chunkdata);
230 chunkdata = text;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600231 *newlength=text_size;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600232 }
233 else /* if (comp_type >= PNG_TEXT_COMPRESSION_LAST) */
234 {
235#if !defined(PNG_NO_STDIO)
236 char umsg[50];
237
238 sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
239 png_warning(png_ptr, umsg);
240#else
241 png_warning(png_ptr, "Unknown zTXt compression type");
242#endif
243
244 /* Copy what we can of the error message into the text chunk */
245 text_size = (png_size_t)(chunklength - (text - chunkdata));
246 text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
247 png_memcpy(text, msg, text_size);
248 }
249
250 return chunkdata;
251}
252#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600253
Guy Schalnat0d580581995-07-20 02:43:20 -0500254/* read and check the IDHR chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500255void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600256png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500257{
258 png_byte buf[13];
259 png_uint_32 width, height;
260 int bit_depth, color_type, compression_type, filter_type;
261 int interlace_type;
262
Andreas Dilger47a0c421997-05-16 02:46:07 -0500263 png_debug(1, "in png_handle_IHDR\n");
264
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600265 if (png_ptr->mode & PNG_HAVE_IHDR)
Guy Schalnate5a37791996-06-05 15:50:50 -0500266 png_error(png_ptr, "Out of place IHDR");
267
Guy Schalnat0d580581995-07-20 02:43:20 -0500268 /* check the length */
269 if (length != 13)
Guy Schalnat6d764711995-12-19 03:22:19 -0600270 png_error(png_ptr, "Invalid IHDR chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -0500271
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600272 png_ptr->mode |= PNG_HAVE_IHDR;
273
Guy Schalnat0d580581995-07-20 02:43:20 -0500274 png_crc_read(png_ptr, buf, 13);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600275 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500276
277 width = png_get_uint_32(buf);
278 height = png_get_uint_32(buf + 4);
279 bit_depth = buf[8];
280 color_type = buf[9];
281 compression_type = buf[10];
282 filter_type = buf[11];
283 interlace_type = buf[12];
284
285 /* check for width and height valid values */
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500286 if (width == 0 || width > PNG_MAX_UINT || height == 0 ||
287 height > PNG_MAX_UINT)
Guy Schalnate5a37791996-06-05 15:50:50 -0500288 png_error(png_ptr, "Invalid image size in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500289
290 /* check other values */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500291 if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
292 bit_depth != 8 && bit_depth != 16)
Guy Schalnate5a37791996-06-05 15:50:50 -0500293 png_error(png_ptr, "Invalid bit depth in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500294
295 if (color_type < 0 || color_type == 1 ||
296 color_type == 5 || color_type > 6)
Guy Schalnate5a37791996-06-05 15:50:50 -0500297 png_error(png_ptr, "Invalid color type in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500298
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500299 if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600300 ((color_type == PNG_COLOR_TYPE_RGB ||
301 color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
302 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
303 png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500304
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600305 if (interlace_type >= PNG_INTERLACE_LAST)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600306 png_error(png_ptr, "Unknown interlace method in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500307
Andreas Dilger47a0c421997-05-16 02:46:07 -0500308 if (compression_type != PNG_COMPRESSION_TYPE_BASE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600309 png_error(png_ptr, "Unknown compression method in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500310
Andreas Dilger47a0c421997-05-16 02:46:07 -0500311 if (filter_type != PNG_FILTER_TYPE_BASE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600312 png_error(png_ptr, "Unknown filter method in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500313
314 /* set internal variables */
315 png_ptr->width = width;
316 png_ptr->height = height;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600317 png_ptr->bit_depth = (png_byte)bit_depth;
318 png_ptr->interlaced = (png_byte)interlace_type;
319 png_ptr->color_type = (png_byte)color_type;
Guy Schalnat0d580581995-07-20 02:43:20 -0500320
321 /* find number of channels */
322 switch (png_ptr->color_type)
323 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500324 case PNG_COLOR_TYPE_GRAY:
325 case PNG_COLOR_TYPE_PALETTE:
Guy Schalnat0d580581995-07-20 02:43:20 -0500326 png_ptr->channels = 1;
327 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500328 case PNG_COLOR_TYPE_RGB:
Guy Schalnat0d580581995-07-20 02:43:20 -0500329 png_ptr->channels = 3;
330 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500331 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500332 png_ptr->channels = 2;
333 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500334 case PNG_COLOR_TYPE_RGB_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500335 png_ptr->channels = 4;
336 break;
337 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600338
Guy Schalnat0d580581995-07-20 02:43:20 -0500339 /* set up other useful info */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600340 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600341 png_ptr->channels);
Guy Schalnat0d580581995-07-20 02:43:20 -0500342 png_ptr->rowbytes = ((png_ptr->width *
343 (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500344 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
345 png_debug1(3,"channels = %d\n", png_ptr->channels);
346 png_debug1(3,"rowbytes = %d\n", png_ptr->rowbytes);
347 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
348 color_type, interlace_type, compression_type, filter_type);
Guy Schalnat0d580581995-07-20 02:43:20 -0500349}
350
351/* read and check the palette */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500352void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600353png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500354{
Guy Schalnat6d764711995-12-19 03:22:19 -0600355 png_colorp palette;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600356 int num, i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500357
Andreas Dilger47a0c421997-05-16 02:46:07 -0500358 png_debug(1, "in png_handle_PLTE\n");
359
Guy Schalnate5a37791996-06-05 15:50:50 -0500360 if (!(png_ptr->mode & PNG_HAVE_IHDR))
361 png_error(png_ptr, "Missing IHDR before PLTE");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600362 else if (png_ptr->mode & PNG_HAVE_IDAT)
363 {
364 png_warning(png_ptr, "Invalid PLTE after IDAT");
365 png_crc_finish(png_ptr, length);
366 return;
367 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500368 else if (png_ptr->mode & PNG_HAVE_PLTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600369 png_error(png_ptr, "Duplicate PLTE chunk");
370
371 png_ptr->mode |= PNG_HAVE_PLTE;
Guy Schalnate5a37791996-06-05 15:50:50 -0500372
373#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
374 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
375 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600376 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500377 return;
378 }
379#endif
380
Guy Schalnat0d580581995-07-20 02:43:20 -0500381 if (length % 3)
Guy Schalnate5a37791996-06-05 15:50:50 -0500382 {
383 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
384 {
385 png_warning(png_ptr, "Invalid palette chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600386 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500387 return;
388 }
389 else
390 {
391 png_error(png_ptr, "Invalid palette chunk");
392 }
393 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500394
395 num = (int)length / 3;
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500396
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600397 palette = (png_colorp)png_zalloc(png_ptr, (uInt)num, sizeof (png_color));
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500398
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600399 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500400 {
401 png_byte buf[3];
402
403 png_crc_read(png_ptr, buf, 3);
404 /* don't depend upon png_color being any order */
405 palette[i].red = buf[0];
406 palette[i].green = buf[1];
407 palette[i].blue = buf[2];
408 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600409
410 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
411 whatever the normal CRC configuration tells us. However, if we
412 have an RGB image, the PLTE can be considered ancillary, so
413 we will act as though it is. */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600414#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600415 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600416#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600417 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500418 png_crc_finish(png_ptr, 0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600419 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600420#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600421 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
422 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600423 /* If we don't want to use the data from an ancillary chunk,
424 we have two options: an error abort, or a warning and we
425 ignore the data in this chunk (which should be OK, since
426 it's considered ancillary for a RGB or RGBA image). */
427 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
428 {
429 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
430 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600431 png_chunk_error(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600432 }
433 else
434 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600435 png_chunk_warning(png_ptr, "CRC error");
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600436 png_zfree(png_ptr, palette);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600437 return;
438 }
439 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500440 /* Otherwise, we (optionally) emit a warning and use the chunk. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600441 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
442 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600443 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600444 }
445 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600446#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500447 png_ptr->palette = palette;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600448 png_ptr->num_palette = (png_uint_16)num;
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500449
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500450#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500451 png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
452 png_ptr->free_me |= PNG_FREE_PLTE;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500453#else
454 png_ptr->flags |= PNG_FLAG_FREE_PLTE;
455#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500456 png_set_PLTE(png_ptr, info_ptr, palette, num);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500457
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500458#if defined(PNG_READ_tRNS_SUPPORTED)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500459 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
460 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600461 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500462 {
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500463 if (png_ptr->num_trans > (png_uint_16)num)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500464 {
465 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500466 png_ptr->num_trans = (png_uint_16)num;
467 }
468 if (info_ptr->num_trans > (png_uint_16)num)
469 {
470 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
471 info_ptr->num_trans = (png_uint_16)num;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500472 }
473 }
474 }
475#endif
476
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600477}
Guy Schalnate5a37791996-06-05 15:50:50 -0500478
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500479void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600480png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
481{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500482 png_debug(1, "in png_handle_IEND\n");
483
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600484 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
485 {
486 png_error(png_ptr, "No image in file");
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600487
488 /* to quiet compiler warnings about unused info_ptr */
489 if (info_ptr == NULL)
490 return;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600491 }
492
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600493 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600494
495 if (length != 0)
496 {
497 png_warning(png_ptr, "Incorrect IEND chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600498 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500499 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500500}
501
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500502#if defined(PNG_READ_gAMA_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500503void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600504png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500505{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600506 png_fixed_point igamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600507#ifdef PNG_FLOATING_POINT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500508 float file_gamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600509#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500510 png_byte buf[4];
511
Andreas Dilger47a0c421997-05-16 02:46:07 -0500512 png_debug(1, "in png_handle_gAMA\n");
513
Guy Schalnate5a37791996-06-05 15:50:50 -0500514 if (!(png_ptr->mode & PNG_HAVE_IHDR))
515 png_error(png_ptr, "Missing IHDR before gAMA");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600516 else if (png_ptr->mode & PNG_HAVE_IDAT)
517 {
518 png_warning(png_ptr, "Invalid gAMA after IDAT");
519 png_crc_finish(png_ptr, length);
520 return;
521 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500522 else if (png_ptr->mode & PNG_HAVE_PLTE)
523 /* Should be an error, but we can cope with it */
524 png_warning(png_ptr, "Out of place gAMA chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600525
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600526 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600527#if defined(PNG_READ_sRGB_SUPPORTED)
528 && !(info_ptr->valid & PNG_INFO_sRGB)
529#endif
530 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600531 {
532 png_warning(png_ptr, "Duplicate gAMA chunk");
533 png_crc_finish(png_ptr, length);
534 return;
535 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500536
Guy Schalnat0d580581995-07-20 02:43:20 -0500537 if (length != 4)
538 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600539 png_warning(png_ptr, "Incorrect gAMA chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600540 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500541 return;
542 }
543
544 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600545 if (png_crc_finish(png_ptr, 0))
546 return;
547
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600548 igamma = (png_fixed_point)png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500549 /* check for zero gamma */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500550 if (igamma == 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600551 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500552
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600553#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600554 if (info_ptr->valid & PNG_INFO_sRGB)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600555 if(igamma < 45000L || igamma > 46000L)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600556 {
557 png_warning(png_ptr,
558 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500559#ifndef PNG_NO_STDIO
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600560 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600561#endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600562 return;
563 }
564#endif /* PNG_READ_sRGB_SUPPORTED */
565
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600566#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600567 file_gamma = (float)igamma / (float)100000.0;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600568# ifdef PNG_READ_GAMMA_SUPPORTED
569 png_ptr->gamma = file_gamma;
570# endif
571 png_set_gAMA(png_ptr, info_ptr, file_gamma);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600572#endif
573#ifdef PNG_FIXED_POINT_SUPPORTED
574 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
575#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500576}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500577#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500578
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500579#if defined(PNG_READ_sBIT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500580void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600581png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500582{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500583 png_size_t truelen;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600584 png_byte buf[4];
Guy Schalnat69b14481996-01-10 02:56:49 -0600585
Andreas Dilger47a0c421997-05-16 02:46:07 -0500586 png_debug(1, "in png_handle_sBIT\n");
587
Guy Schalnat69b14481996-01-10 02:56:49 -0600588 buf[0] = buf[1] = buf[2] = buf[3] = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500589
Guy Schalnate5a37791996-06-05 15:50:50 -0500590 if (!(png_ptr->mode & PNG_HAVE_IHDR))
591 png_error(png_ptr, "Missing IHDR before sBIT");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600592 else if (png_ptr->mode & PNG_HAVE_IDAT)
593 {
594 png_warning(png_ptr, "Invalid sBIT after IDAT");
595 png_crc_finish(png_ptr, length);
596 return;
597 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500598 else if (png_ptr->mode & PNG_HAVE_PLTE)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600599 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500600 /* Should be an error, but we can cope with it */
601 png_warning(png_ptr, "Out of place sBIT chunk");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600602 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600603 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600604 {
605 png_warning(png_ptr, "Duplicate sBIT chunk");
606 png_crc_finish(png_ptr, length);
607 return;
608 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500609
Guy Schalnat0d580581995-07-20 02:43:20 -0500610 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600611 truelen = 3;
Guy Schalnat0d580581995-07-20 02:43:20 -0500612 else
Andreas Dilger47a0c421997-05-16 02:46:07 -0500613 truelen = (png_size_t)png_ptr->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500614
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600615 if (length != truelen)
Guy Schalnat0d580581995-07-20 02:43:20 -0500616 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600617 png_warning(png_ptr, "Incorrect sBIT chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600618 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600619 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500620 }
621
Andreas Dilger47a0c421997-05-16 02:46:07 -0500622 png_crc_read(png_ptr, buf, truelen);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600623 if (png_crc_finish(png_ptr, 0))
624 return;
625
Guy Schalnat0d580581995-07-20 02:43:20 -0500626 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
627 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600628 png_ptr->sig_bit.red = buf[0];
629 png_ptr->sig_bit.green = buf[1];
630 png_ptr->sig_bit.blue = buf[2];
631 png_ptr->sig_bit.alpha = buf[3];
Guy Schalnat0d580581995-07-20 02:43:20 -0500632 }
633 else
634 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600635 png_ptr->sig_bit.gray = buf[0];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600636 png_ptr->sig_bit.red = buf[0];
637 png_ptr->sig_bit.green = buf[0];
638 png_ptr->sig_bit.blue = buf[0];
Guy Schalnat6d764711995-12-19 03:22:19 -0600639 png_ptr->sig_bit.alpha = buf[1];
Guy Schalnat0d580581995-07-20 02:43:20 -0500640 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500641 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
Guy Schalnat0d580581995-07-20 02:43:20 -0500642}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500643#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500644
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500645#if defined(PNG_READ_cHRM_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500646void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600647png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500648{
649 png_byte buf[4];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600650#ifdef PNG_FLOATING_POINT_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -0500651 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 -0600652#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600653 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 -0600654 int_y_green, int_x_blue, int_y_blue;
Guy Schalnat0d580581995-07-20 02:43:20 -0500655
Andreas Dilger47a0c421997-05-16 02:46:07 -0500656 png_debug(1, "in png_handle_cHRM\n");
657
Guy Schalnate5a37791996-06-05 15:50:50 -0500658 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600659 png_error(png_ptr, "Missing IHDR before cHRM");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600660 else if (png_ptr->mode & PNG_HAVE_IDAT)
661 {
662 png_warning(png_ptr, "Invalid cHRM after IDAT");
663 png_crc_finish(png_ptr, length);
664 return;
665 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500666 else if (png_ptr->mode & PNG_HAVE_PLTE)
667 /* Should be an error, but we can cope with it */
668 png_warning(png_ptr, "Missing PLTE before cHRM");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600669
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600670 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600671#if defined(PNG_READ_sRGB_SUPPORTED)
672 && !(info_ptr->valid & PNG_INFO_sRGB)
673#endif
674 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600675 {
676 png_warning(png_ptr, "Duplicate cHRM chunk");
677 png_crc_finish(png_ptr, length);
678 return;
679 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500680
Guy Schalnat0d580581995-07-20 02:43:20 -0500681 if (length != 32)
682 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600683 png_warning(png_ptr, "Incorrect cHRM chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600684 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600685 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500686 }
687
688 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600689 int_x_white = (png_fixed_point)png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500690
691 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600692 int_y_white = (png_fixed_point)png_get_uint_32(buf);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600693
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600694 if (int_x_white > 80000L || int_y_white > 80000L ||
695 int_x_white + int_y_white > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600696 {
697 png_warning(png_ptr, "Invalid cHRM white point");
698 png_crc_finish(png_ptr, 24);
699 return;
700 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500701
702 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600703 int_x_red = (png_fixed_point)png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500704
705 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600706 int_y_red = (png_fixed_point)png_get_uint_32(buf);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600707
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600708 if (int_x_red > 80000L || int_y_red > 80000L ||
709 int_x_red + int_y_red > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600710 {
711 png_warning(png_ptr, "Invalid cHRM red point");
712 png_crc_finish(png_ptr, 16);
713 return;
714 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500715
716 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600717 int_x_green = (png_fixed_point)png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500718
719 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600720 int_y_green = (png_fixed_point)png_get_uint_32(buf);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600721
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600722 if (int_x_green > 80000L || int_y_green > 80000L ||
723 int_x_green + int_y_green > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600724 {
725 png_warning(png_ptr, "Invalid cHRM green point");
726 png_crc_finish(png_ptr, 8);
727 return;
728 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500729
730 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600731 int_x_blue = (png_fixed_point)png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500732
733 png_crc_read(png_ptr, buf, 4);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600734 int_y_blue = (png_fixed_point)png_get_uint_32(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -0500735
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600736 if (int_x_blue > 80000L || int_y_blue > 80000L ||
737 int_x_blue + int_y_blue > 100000L)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600738 {
739 png_warning(png_ptr, "Invalid cHRM blue point");
740 png_crc_finish(png_ptr, 0);
741 return;
742 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600743#ifdef PNG_FLOATING_POINT_SUPPORTED
744 white_x = (float)int_x_white / (float)100000.0;
745 white_y = (float)int_y_white / (float)100000.0;
746 red_x = (float)int_x_red / (float)100000.0;
747 red_y = (float)int_y_red / (float)100000.0;
748 green_x = (float)int_x_green / (float)100000.0;
749 green_y = (float)int_y_green / (float)100000.0;
750 blue_x = (float)int_x_blue / (float)100000.0;
751 blue_y = (float)int_y_blue / (float)100000.0;
752#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600753
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600754#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600755 if (info_ptr->valid & PNG_INFO_sRGB)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600756 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600757 if (abs(int_x_white - 31270L) > 1000 ||
758 abs(int_y_white - 32900L) > 1000 ||
759 abs( int_x_red - 64000L) > 1000 ||
760 abs( int_y_red - 33000L) > 1000 ||
761 abs(int_x_green - 30000L) > 1000 ||
762 abs(int_y_green - 60000L) > 1000 ||
763 abs( int_x_blue - 15000L) > 1000 ||
764 abs( int_y_blue - 6000L) > 1000)
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600765 {
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600766
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600767 png_warning(png_ptr,
768 "Ignoring incorrect cHRM value when sRGB is also present");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500769#ifndef PNG_NO_STDIO
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600770#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600771 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
772 white_x, white_y, red_x, red_y);
773 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
774 green_x, green_y, blue_x, blue_y);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600775#else
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600776 fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600777 int_x_white, int_y_white, int_x_red, int_y_red);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600778 fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600779 int_x_green, int_y_green, int_x_blue, int_y_blue);
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600780#endif
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500781#endif /* PNG_NO_STDIO */
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600782 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600783 png_crc_finish(png_ptr, 0);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600784 return;
785 }
786#endif /* PNG_READ_sRGB_SUPPORTED */
787
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600788#ifdef PNG_FLOATING_POINT_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500789 png_set_cHRM(png_ptr, info_ptr,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600790 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600791#endif
792#ifdef PNG_FIXED_POINT_SUPPORTED
793 png_set_cHRM_fixed(png_ptr, info_ptr,
794 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
795 int_y_green, int_x_blue, int_y_blue);
796#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600797 if (png_crc_finish(png_ptr, 0))
798 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500799}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500800#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500801
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600802#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500803void /* PRIVATE */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600804png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
805{
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600806 int intent;
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600807 png_byte buf[1];
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600808
809 png_debug(1, "in png_handle_sRGB\n");
810
811 if (!(png_ptr->mode & PNG_HAVE_IHDR))
812 png_error(png_ptr, "Missing IHDR before sRGB");
813 else if (png_ptr->mode & PNG_HAVE_IDAT)
814 {
815 png_warning(png_ptr, "Invalid sRGB after IDAT");
816 png_crc_finish(png_ptr, length);
817 return;
818 }
819 else if (png_ptr->mode & PNG_HAVE_PLTE)
820 /* Should be an error, but we can cope with it */
821 png_warning(png_ptr, "Out of place sRGB chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600822
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600823 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600824 {
825 png_warning(png_ptr, "Duplicate sRGB chunk");
826 png_crc_finish(png_ptr, length);
827 return;
828 }
829
830 if (length != 1)
831 {
832 png_warning(png_ptr, "Incorrect sRGB chunk length");
833 png_crc_finish(png_ptr, length);
834 return;
835 }
836
837 png_crc_read(png_ptr, buf, 1);
838 if (png_crc_finish(png_ptr, 0))
839 return;
840
841 intent = buf[0];
842 /* check for bad intent */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600843 if (intent >= PNG_sRGB_INTENT_LAST)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600844 {
845 png_warning(png_ptr, "Unknown sRGB intent");
846 return;
847 }
848
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600849#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600850 if ((info_ptr->valid & PNG_INFO_gAMA))
851 {
852 int igamma;
853#ifdef PNG_FIXED_POINT_SUPPORTED
854 igamma=(int)info_ptr->int_gamma;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600855#else
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600856# ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500857 igamma=(int)(info_ptr->gamma * 100000.);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600858# endif
859#endif
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500860#if 0 && defined(PNG_cHRM_SUPPORTED) && !defined(PNG_FIXED_POINT_SUPPORTED)
861/* We need to define these here because they aren't in png.h */
862 png_fixed_point int_x_white;
863 png_fixed_point int_y_white;
864 png_fixed_point int_x_red;
865 png_fixed_point int_y_red;
866 png_fixed_point int_x_green;
867 png_fixed_point int_y_green;
868 png_fixed_point int_x_blue;
869 png_fixed_point int_y_blue;
870#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600871 if(igamma < 45000L || igamma > 46000L)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600872 {
873 png_warning(png_ptr,
874 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -0500875#ifndef PNG_NO_STDIO
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600876# ifdef PNG_FIXED_POINT_SUPPORTED
877 fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
878# else
879# ifdef PNG_FLOATING_POINT_SUPPORTED
880 fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
881# endif
882# endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600883#endif
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600884 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600885 }
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600886#endif /* PNG_READ_gAMA_SUPPORTED */
887
888#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500889#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600890 if (info_ptr->valid & PNG_INFO_cHRM)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600891 if (abs(info_ptr->int_x_white - 31270L) > 1000 ||
892 abs(info_ptr->int_y_white - 32900L) > 1000 ||
893 abs( info_ptr->int_x_red - 64000L) > 1000 ||
894 abs( info_ptr->int_y_red - 33000L) > 1000 ||
895 abs(info_ptr->int_x_green - 30000L) > 1000 ||
896 abs(info_ptr->int_y_green - 60000L) > 1000 ||
897 abs( info_ptr->int_x_blue - 15000L) > 1000 ||
898 abs( info_ptr->int_y_blue - 6000L) > 1000)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600899 {
900 png_warning(png_ptr,
901 "Ignoring incorrect cHRM value when sRGB is also present");
902 }
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -0500903#endif /* PNG_FIXED_POINT_SUPPORTED */
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600904#endif /* PNG_READ_cHRM_SUPPORTED */
905
906 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
907}
908#endif /* PNG_READ_sRGB_SUPPORTED */
909
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600910#if defined(PNG_READ_iCCP_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500911void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600912png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
913/* Note: this does not properly handle chunks that are > 64K under DOS */
914{
915 png_charp chunkdata;
916 png_byte compression_type;
917 png_charp profile;
918 png_uint_32 skip = 0;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600919 png_size_t slength, prefix_length, data_length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600920
921 png_debug(1, "in png_handle_iCCP\n");
922
923 if (!(png_ptr->mode & PNG_HAVE_IHDR))
924 png_error(png_ptr, "Missing IHDR before iCCP");
925 else if (png_ptr->mode & PNG_HAVE_IDAT)
926 {
927 png_warning(png_ptr, "Invalid iCCP after IDAT");
928 png_crc_finish(png_ptr, length);
929 return;
930 }
931 else if (png_ptr->mode & PNG_HAVE_PLTE)
932 /* Should be an error, but we can cope with it */
933 png_warning(png_ptr, "Out of place iCCP chunk");
934
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600935 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600936 {
937 png_warning(png_ptr, "Duplicate iCCP chunk");
938 png_crc_finish(png_ptr, length);
939 return;
940 }
941
942#ifdef PNG_MAX_MALLOC_64K
943 if (length > (png_uint_32)65535L)
944 {
945 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
946 skip = length - (png_uint_32)65535L;
947 length = (png_uint_32)65535L;
948 }
949#endif
950
951 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
952 slength = (png_size_t)length;
953 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
954
955 if (png_crc_finish(png_ptr, skip))
956 {
957 png_free(png_ptr, chunkdata);
958 return;
959 }
960
961 chunkdata[slength] = 0x00;
962
963 for (profile = chunkdata; *profile; profile++)
964 /* empty loop to find end of name */ ;
965 ++profile;
966
967 /* there should be at least one NUL (the compression type byte)
968 following the separator, and we should be on it */
969 if (profile >= chunkdata + slength)
970 {
971 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500972 png_warning(png_ptr, "malformed iCCP chunk");
973 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600974 }
975
976 /* compression should always be zero */
977 compression_type = *profile++;
978
979 prefix_length = profile - chunkdata;
980 chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600981 slength, prefix_length, &data_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600982
983 png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -0600984 chunkdata + prefix_length, data_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600985 png_free(png_ptr, chunkdata);
986}
987#endif /* PNG_READ_iCCP_SUPPORTED */
988
989#if defined(PNG_READ_sPLT_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500990void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600991png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
992/* Note: this does not properly handle chunks that are > 64K under DOS */
993{
994 png_bytep chunkdata;
995 png_bytep entry_start;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -0600996 png_sPLT_t new_palette;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600997 int data_length, entry_size, i;
998 png_uint_32 skip = 0;
999 png_size_t slength;
1000
1001 png_debug(1, "in png_handle_sPLT\n");
1002
1003 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1004 png_error(png_ptr, "Missing IHDR before sPLT");
1005 else if (png_ptr->mode & PNG_HAVE_IDAT)
1006 {
1007 png_warning(png_ptr, "Invalid sPLT after IDAT");
1008 png_crc_finish(png_ptr, length);
1009 return;
1010 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001011
1012#ifdef PNG_MAX_MALLOC_64K
1013 if (length > (png_uint_32)65535L)
1014 {
1015 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1016 skip = length - (png_uint_32)65535L;
1017 length = (png_uint_32)65535L;
1018 }
1019#endif
1020
1021 chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
1022 slength = (png_size_t)length;
1023 png_crc_read(png_ptr, chunkdata, slength);
1024
1025 if (png_crc_finish(png_ptr, skip))
1026 {
1027 png_free(png_ptr, chunkdata);
1028 return;
1029 }
1030
1031 chunkdata[slength] = 0x00;
1032
1033 for (entry_start = chunkdata; *entry_start; entry_start++)
1034 /* empty loop to find end of name */ ;
1035 ++entry_start;
1036
1037 /* a sample depth should follow the separator, and we should be on it */
1038 if (entry_start > chunkdata + slength)
1039 {
1040 png_free(png_ptr, chunkdata);
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001041 png_warning(png_ptr, "malformed sPLT chunk");
1042 return;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001043 }
1044
1045 new_palette.depth = *entry_start++;
1046 entry_size = (new_palette.depth == 8 ? 6 : 10);
1047 data_length = (slength - (entry_start - chunkdata));
1048
1049 /* integrity-check the data length */
1050 if (data_length % entry_size)
1051 {
1052 png_free(png_ptr, chunkdata);
1053 png_error(png_ptr, "sPLT chunk has bad length");
1054 }
1055
1056 new_palette.nentries = data_length / entry_size;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001057 new_palette.entries = (png_sPLT_entryp)png_malloc(
1058 png_ptr, new_palette.nentries * sizeof(png_sPLT_entry));
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001059
1060 for (i = 0; i < new_palette.nentries; i++)
1061 {
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001062 png_sPLT_entryp pp = new_palette.entries + i;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001063
1064 if (new_palette.depth == 8)
1065 {
1066 pp->red = *entry_start++;
1067 pp->green = *entry_start++;
1068 pp->blue = *entry_start++;
1069 pp->alpha = *entry_start++;
1070 }
1071 else
1072 {
1073 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1074 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1075 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1076 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1077 }
1078 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1079 }
1080
1081 /* discard all chunk data except the name and stash that */
1082 new_palette.name = (png_charp)chunkdata;
1083
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001084 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001085
1086 png_free(png_ptr, chunkdata);
1087 png_free(png_ptr, new_palette.entries);
1088}
1089#endif /* PNG_READ_sPLT_SUPPORTED */
1090
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001091#if defined(PNG_READ_tRNS_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001092void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001093png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001094{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001095 png_debug(1, "in png_handle_tRNS\n");
1096
Guy Schalnate5a37791996-06-05 15:50:50 -05001097 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1098 png_error(png_ptr, "Missing IHDR before tRNS");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001099 else if (png_ptr->mode & PNG_HAVE_IDAT)
1100 {
1101 png_warning(png_ptr, "Invalid tRNS after IDAT");
1102 png_crc_finish(png_ptr, length);
1103 return;
1104 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001105 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001106 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001107 png_warning(png_ptr, "Duplicate tRNS chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001108 png_crc_finish(png_ptr, length);
1109 return;
1110 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001111
Guy Schalnat0d580581995-07-20 02:43:20 -05001112 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1113 {
Guy Schalnate5a37791996-06-05 15:50:50 -05001114 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1115 {
1116 /* Should be an error, but we can cope with it */
1117 png_warning(png_ptr, "Missing PLTE before tRNS");
1118 }
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001119 else if (length > (png_uint_32)png_ptr->num_palette)
Guy Schalnat0d580581995-07-20 02:43:20 -05001120 {
Guy Schalnat69b14481996-01-10 02:56:49 -06001121 png_warning(png_ptr, "Incorrect tRNS chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001122 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001123 return;
1124 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001125 if (length == 0)
1126 {
1127 png_warning(png_ptr, "Zero length tRNS chunk");
1128 png_crc_finish(png_ptr, length);
1129 return;
1130 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001131
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001132 png_ptr->trans = (png_bytep)png_malloc(png_ptr, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001133 png_crc_read(png_ptr, png_ptr->trans, (png_size_t)length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001134 png_ptr->num_trans = (png_uint_16)length;
Guy Schalnat0d580581995-07-20 02:43:20 -05001135 }
1136 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1137 {
1138 png_byte buf[6];
1139
1140 if (length != 6)
1141 {
Guy Schalnat69b14481996-01-10 02:56:49 -06001142 png_warning(png_ptr, "Incorrect tRNS chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001143 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001144 return;
1145 }
1146
Andreas Dilger47a0c421997-05-16 02:46:07 -05001147 png_crc_read(png_ptr, buf, (png_size_t)length);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001148 png_ptr->num_trans = 1;
Guy Schalnat0d580581995-07-20 02:43:20 -05001149 png_ptr->trans_values.red = png_get_uint_16(buf);
1150 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1151 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
1152 }
1153 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1154 {
1155 png_byte buf[6];
1156
1157 if (length != 2)
1158 {
Guy Schalnat69b14481996-01-10 02:56:49 -06001159 png_warning(png_ptr, "Incorrect tRNS chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001160 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001161 return;
1162 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001163
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001164 png_crc_read(png_ptr, buf, 2);
1165 png_ptr->num_trans = 1;
1166 png_ptr->trans_values.gray = png_get_uint_16(buf);
1167 }
1168 else
Guy Schalnate5a37791996-06-05 15:50:50 -05001169 {
1170 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001171 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001172 return;
1173 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001174
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001175 if (png_crc_finish(png_ptr, 0))
1176 return;
1177
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001178#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -05001179 png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
1180 png_ptr->free_me |= PNG_FREE_TRNS;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001181#else
1182 png_ptr->flags |= PNG_FLAG_FREE_TRNS;
1183#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001184 png_set_tRNS(png_ptr, info_ptr, png_ptr->trans, png_ptr->num_trans,
Guy Schalnat0d580581995-07-20 02:43:20 -05001185 &(png_ptr->trans_values));
1186}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001187#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001188
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001189#if defined(PNG_READ_bKGD_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001190void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001191png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001192{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001193 png_size_t truelen;
Guy Schalnat0d580581995-07-20 02:43:20 -05001194 png_byte buf[6];
1195
Andreas Dilger47a0c421997-05-16 02:46:07 -05001196 png_debug(1, "in png_handle_bKGD\n");
1197
Guy Schalnate5a37791996-06-05 15:50:50 -05001198 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1199 png_error(png_ptr, "Missing IHDR before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001200 else if (png_ptr->mode & PNG_HAVE_IDAT)
1201 {
1202 png_warning(png_ptr, "Invalid bKGD after IDAT");
1203 png_crc_finish(png_ptr, length);
1204 return;
1205 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001206 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1207 !(png_ptr->mode & PNG_HAVE_PLTE))
1208 {
1209 png_warning(png_ptr, "Missing PLTE before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001210 png_crc_finish(png_ptr, length);
1211 return;
1212 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001213 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001214 {
1215 png_warning(png_ptr, "Duplicate bKGD chunk");
1216 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001217 return;
1218 }
1219
Guy Schalnat0d580581995-07-20 02:43:20 -05001220 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1221 truelen = 1;
1222 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1223 truelen = 6;
1224 else
1225 truelen = 2;
1226
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001227 if (length != truelen)
Guy Schalnat0d580581995-07-20 02:43:20 -05001228 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001229 png_warning(png_ptr, "Incorrect bKGD chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001230 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001231 return;
1232 }
1233
Andreas Dilger47a0c421997-05-16 02:46:07 -05001234 png_crc_read(png_ptr, buf, truelen);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001235 if (png_crc_finish(png_ptr, 0))
1236 return;
1237
Guy Schalnate5a37791996-06-05 15:50:50 -05001238 /* We convert the index value into RGB components so that we can allow
1239 * arbitrary RGB values for background when we have transparency, and
1240 * so it is easy to determine the RGB values of the background color
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001241 * from the info_ptr struct. */
Guy Schalnat0d580581995-07-20 02:43:20 -05001242 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnate5a37791996-06-05 15:50:50 -05001243 {
Guy Schalnat0d580581995-07-20 02:43:20 -05001244 png_ptr->background.index = buf[0];
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001245 if(info_ptr->num_palette)
1246 {
1247 if(buf[0] > info_ptr->num_palette)
1248 {
1249 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1250 png_crc_finish(png_ptr, length);
1251 return;
1252 }
1253 png_ptr->background.red =
1254 (png_uint_16)png_ptr->palette[buf[0]].red;
1255 png_ptr->background.green =
1256 (png_uint_16)png_ptr->palette[buf[0]].green;
1257 png_ptr->background.blue =
1258 (png_uint_16)png_ptr->palette[buf[0]].blue;
1259 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001260 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001261 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
Guy Schalnate5a37791996-06-05 15:50:50 -05001262 {
1263 png_ptr->background.red =
1264 png_ptr->background.green =
1265 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -05001266 png_ptr->background.gray = png_get_uint_16(buf);
Guy Schalnate5a37791996-06-05 15:50:50 -05001267 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001268 else
1269 {
1270 png_ptr->background.red = png_get_uint_16(buf);
1271 png_ptr->background.green = png_get_uint_16(buf + 2);
1272 png_ptr->background.blue = png_get_uint_16(buf + 4);
1273 }
1274
Andreas Dilger47a0c421997-05-16 02:46:07 -05001275 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
Guy Schalnat0d580581995-07-20 02:43:20 -05001276}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001277#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001278
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001279#if defined(PNG_READ_hIST_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001280void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001281png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001282{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001283 int num, i;
Guy Schalnat0d580581995-07-20 02:43:20 -05001284
Andreas Dilger47a0c421997-05-16 02:46:07 -05001285 png_debug(1, "in png_handle_hIST\n");
1286
Guy Schalnate5a37791996-06-05 15:50:50 -05001287 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1288 png_error(png_ptr, "Missing IHDR before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001289 else if (png_ptr->mode & PNG_HAVE_IDAT)
1290 {
1291 png_warning(png_ptr, "Invalid hIST after IDAT");
1292 png_crc_finish(png_ptr, length);
1293 return;
1294 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001295 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1296 {
1297 png_warning(png_ptr, "Missing PLTE before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001298 png_crc_finish(png_ptr, length);
1299 return;
1300 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001301 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001302 {
1303 png_warning(png_ptr, "Duplicate hIST chunk");
1304 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -05001305 return;
1306 }
1307
Andreas Dilger47a0c421997-05-16 02:46:07 -05001308 if (length != (png_uint_32)(2 * png_ptr->num_palette))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001309 {
1310 png_warning(png_ptr, "Incorrect hIST chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001311 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001312 return;
1313 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001314
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05001315 num = (int)length / 2 ;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001316 png_ptr->hist = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001317 (png_uint_32)(num * sizeof (png_uint_16)));
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001318 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001319 {
1320 png_byte buf[2];
1321
1322 png_crc_read(png_ptr, buf, 2);
1323 png_ptr->hist[i] = png_get_uint_16(buf);
1324 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001325
1326 if (png_crc_finish(png_ptr, 0))
1327 return;
1328
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001329#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrson38e6e772000-04-09 19:06:13 -05001330 png_free_data(png_ptr, info_ptr, PNG_FREE_HIST, 0);
1331 png_ptr->free_me |= PNG_FREE_HIST;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001332#else
1333 png_ptr->flags |= PNG_FLAG_FREE_HIST;
1334#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001335 png_set_hIST(png_ptr, info_ptr, png_ptr->hist);
Guy Schalnat0d580581995-07-20 02:43:20 -05001336}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001337#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001338
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001339#if defined(PNG_READ_pHYs_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001340void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001341png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001342{
1343 png_byte buf[9];
1344 png_uint_32 res_x, res_y;
1345 int unit_type;
1346
Andreas Dilger47a0c421997-05-16 02:46:07 -05001347 png_debug(1, "in png_handle_pHYs\n");
1348
Guy Schalnate5a37791996-06-05 15:50:50 -05001349 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1350 png_error(png_ptr, "Missing IHDR before pHYS");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001351 else if (png_ptr->mode & PNG_HAVE_IDAT)
1352 {
1353 png_warning(png_ptr, "Invalid pHYS after IDAT");
1354 png_crc_finish(png_ptr, length);
1355 return;
1356 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001357 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001358 {
1359 png_warning(png_ptr, "Duplicate pHYS chunk");
1360 png_crc_finish(png_ptr, length);
1361 return;
1362 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001363
Guy Schalnat0d580581995-07-20 02:43:20 -05001364 if (length != 9)
1365 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001366 png_warning(png_ptr, "Incorrect pHYs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001367 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001368 return;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001369 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001370
1371 png_crc_read(png_ptr, buf, 9);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001372 if (png_crc_finish(png_ptr, 0))
1373 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001374
1375 res_x = png_get_uint_32(buf);
1376 res_y = png_get_uint_32(buf + 4);
1377 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001378 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
Guy Schalnat0d580581995-07-20 02:43:20 -05001379}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001380#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001381
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001382#if defined(PNG_READ_oFFs_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001383void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001384png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001385{
1386 png_byte buf[9];
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001387 png_int_32 offset_x, offset_y;
Guy Schalnat0d580581995-07-20 02:43:20 -05001388 int unit_type;
1389
Andreas Dilger47a0c421997-05-16 02:46:07 -05001390 png_debug(1, "in png_handle_oFFs\n");
1391
Guy Schalnate5a37791996-06-05 15:50:50 -05001392 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1393 png_error(png_ptr, "Missing IHDR before oFFs");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001394 else if (png_ptr->mode & PNG_HAVE_IDAT)
1395 {
1396 png_warning(png_ptr, "Invalid oFFs after IDAT");
1397 png_crc_finish(png_ptr, length);
1398 return;
1399 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001400 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001401 {
1402 png_warning(png_ptr, "Duplicate oFFs chunk");
1403 png_crc_finish(png_ptr, length);
1404 return;
1405 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001406
Guy Schalnat0d580581995-07-20 02:43:20 -05001407 if (length != 9)
1408 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001409 png_warning(png_ptr, "Incorrect oFFs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001410 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001411 return;
1412 }
1413
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001414 png_crc_read(png_ptr, buf, 9);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001415 if (png_crc_finish(png_ptr, 0))
1416 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001417
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001418 offset_x = png_get_int_32(buf);
1419 offset_y = png_get_int_32(buf + 4);
Guy Schalnat0d580581995-07-20 02:43:20 -05001420 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001421 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1422}
1423#endif
1424
1425#if defined(PNG_READ_pCAL_SUPPORTED)
1426/* read the pCAL chunk (png-scivis-19970203) */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001427void /* PRIVATE */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001428png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1429{
1430 png_charp purpose;
1431 png_int_32 X0, X1;
1432 png_byte type, nparams;
1433 png_charp buf, units, endptr;
1434 png_charpp params;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001435 png_size_t slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001436 int i;
1437
1438 png_debug(1, "in png_handle_pCAL\n");
1439
1440 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1441 png_error(png_ptr, "Missing IHDR before pCAL");
1442 else if (png_ptr->mode & PNG_HAVE_IDAT)
1443 {
1444 png_warning(png_ptr, "Invalid pCAL after IDAT");
1445 png_crc_finish(png_ptr, length);
1446 return;
1447 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001448 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
Andreas Dilger47a0c421997-05-16 02:46:07 -05001449 {
1450 png_warning(png_ptr, "Duplicate pCAL chunk");
1451 png_crc_finish(png_ptr, length);
1452 return;
1453 }
1454
1455 png_debug1(2, "Allocating and reading pCAL chunk data (%d bytes)\n",
1456 length + 1);
1457 purpose = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001458 slength = (png_size_t)length;
1459 png_crc_read(png_ptr, (png_bytep)purpose, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001460
1461 if (png_crc_finish(png_ptr, 0))
1462 {
1463 png_free(png_ptr, purpose);
1464 return;
1465 }
1466
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001467 purpose[slength] = 0x00; /* null terminate the last string */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001468
1469 png_debug(3, "Finding end of pCAL purpose string\n");
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001470 for (buf = purpose; *buf; buf++)
Glenn Randers-Pehrsond12aa501998-03-13 07:39:39 -06001471 /* empty loop */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001472
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001473 endptr = purpose + slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001474
1475 /* We need to have at least 12 bytes after the purpose string
1476 in order to get the parameter information. */
1477 if (endptr <= buf + 12)
1478 {
1479 png_warning(png_ptr, "Invalid pCAL data");
1480 png_free(png_ptr, purpose);
1481 return;
1482 }
1483
1484 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1485 X0 = png_get_int_32((png_bytep)buf+1);
1486 X1 = png_get_int_32((png_bytep)buf+5);
1487 type = buf[9];
1488 nparams = buf[10];
1489 units = buf + 11;
1490
1491 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1492 /* Check that we have the right number of parameters for known
1493 equation types. */
1494 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1495 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1496 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1497 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1498 {
1499 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1500 png_free(png_ptr, purpose);
1501 return;
1502 }
1503 else if (type >= PNG_EQUATION_LAST)
1504 {
1505 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1506 }
1507
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001508 for (buf = units; *buf; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001509 /* Empty loop to move past the units string. */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001510
1511 png_debug(3, "Allocating pCAL parameters array\n");
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001512 params = (png_charpp)png_malloc(png_ptr, (png_uint_32)(nparams
1513 *sizeof(png_charp))) ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001514
1515 /* Get pointers to the start of each parameter string. */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001516 for (i = 0; i < (int)nparams; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001517 {
1518 buf++; /* Skip the null string terminator from previous parameter. */
1519
1520 png_debug1(3, "Reading pCAL parameter %d\n", i);
Glenn Randers-Pehrsond12aa501998-03-13 07:39:39 -06001521 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001522 /* Empty loop to move past each parameter string */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001523
1524 /* Make sure we haven't run out of data yet */
1525 if (buf > endptr)
1526 {
1527 png_warning(png_ptr, "Invalid pCAL data");
1528 png_free(png_ptr, purpose);
1529 png_free(png_ptr, params);
1530 return;
1531 }
1532 }
1533
1534 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1535 units, params);
1536
1537 png_free(png_ptr, purpose);
1538 png_free(png_ptr, params);
Guy Schalnat0d580581995-07-20 02:43:20 -05001539}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001540#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001541
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001542#if defined(PNG_READ_sCAL_SUPPORTED)
1543/* read the sCAL chunk */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001544void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001545png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1546{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001547 png_charp buffer, ep;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001548#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001549 double width, height;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001550 png_charp vp;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001551#else
1552#ifdef PNG_FIXED_POINT_SUPPORTED
1553 png_charp swidth, sheight;
1554#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001555#endif
1556 png_size_t slength;
1557
1558 png_debug(1, "in png_handle_sCAL\n");
1559
1560 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1561 png_error(png_ptr, "Missing IHDR before sCAL");
1562 else if (png_ptr->mode & PNG_HAVE_IDAT)
1563 {
1564 png_warning(png_ptr, "Invalid sCAL after IDAT");
1565 png_crc_finish(png_ptr, length);
1566 return;
1567 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001568 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001569 {
1570 png_warning(png_ptr, "Duplicate sCAL chunk");
1571 png_crc_finish(png_ptr, length);
1572 return;
1573 }
1574
1575 png_debug1(2, "Allocating and reading sCAL chunk data (%d bytes)\n",
1576 length + 1);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001577 buffer = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001578 slength = (png_size_t)length;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001579 png_crc_read(png_ptr, (png_bytep)buffer, slength);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001580
1581 if (png_crc_finish(png_ptr, 0))
1582 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001583 png_free(png_ptr, buffer);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001584 return;
1585 }
1586
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001587 buffer[slength] = 0x00; /* null terminate the last string */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001588
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001589 ep = buffer + 1; /* skip unit byte */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001590
1591#ifdef PNG_FLOATING_POINT_SUPPORTED
1592 width = strtod(ep, &vp);
1593 if (*vp)
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001594 {
1595 png_warning(png_ptr, "malformed width string in sCAL chunk");
1596 return;
1597 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001598#else
1599#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001600 swidth = (png_charp)png_malloc(png_ptr, strlen(ep) + 1);
1601 png_memcpy(swidth, ep, (png_size_t)strlen(ep));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001602#endif
1603#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001604
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001605 for (ep = buffer; *ep; ep++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001606 /* empty loop */ ;
1607 ep++;
1608
1609#ifdef PNG_FLOATING_POINT_SUPPORTED
1610 height = strtod(ep, &vp);
1611 if (*vp)
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -05001612 {
1613 png_warning(png_ptr, "malformed height string in sCAL chunk");
1614 return;
1615 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001616#else
1617#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001618 sheight = (png_charp)png_malloc(png_ptr, strlen(ep) + 1);
1619 png_memcpy(sheight, ep, (png_size_t)strlen(ep));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001620#endif
1621#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001622
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001623 if (buffer + slength < ep
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001624#ifdef PNG_FLOATING_POINT_SUPPORTED
1625 || width <= 0. || height <= 0.
1626#endif
1627 )
1628 {
1629 png_warning(png_ptr, "Invalid sCAL data");
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001630 png_free(png_ptr, buffer);
1631#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001632 png_free(png_ptr, swidth);
1633 png_free(png_ptr, sheight);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001634#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001635 return;
1636 }
1637
1638
1639#ifdef PNG_FLOATING_POINT_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001640 png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1641#else
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001642#ifdef PNG_FIXED_POINT_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001643 png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1644#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001645#endif
1646
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001647 png_free(png_ptr, buffer);
1648#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1649 png_free(png_ptr, swidth);
1650 png_free(png_ptr, sheight);
1651#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001652}
1653#endif
1654
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001655#if defined(PNG_READ_tIME_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001656void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001657png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001658{
1659 png_byte buf[7];
1660 png_time mod_time;
1661
Andreas Dilger47a0c421997-05-16 02:46:07 -05001662 png_debug(1, "in png_handle_tIME\n");
1663
Guy Schalnate5a37791996-06-05 15:50:50 -05001664 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001665 png_error(png_ptr, "Out of place tIME chunk");
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001666 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001667 {
1668 png_warning(png_ptr, "Duplicate tIME chunk");
1669 png_crc_finish(png_ptr, length);
1670 return;
1671 }
1672
1673 if (png_ptr->mode & PNG_HAVE_IDAT)
1674 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnate5a37791996-06-05 15:50:50 -05001675
Guy Schalnat0d580581995-07-20 02:43:20 -05001676 if (length != 7)
1677 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001678 png_warning(png_ptr, "Incorrect tIME chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001679 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001680 return;
1681 }
1682
1683 png_crc_read(png_ptr, buf, 7);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001684 if (png_crc_finish(png_ptr, 0))
1685 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001686
1687 mod_time.second = buf[6];
1688 mod_time.minute = buf[5];
1689 mod_time.hour = buf[4];
1690 mod_time.day = buf[3];
1691 mod_time.month = buf[2];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001692 mod_time.year = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001693
Andreas Dilger47a0c421997-05-16 02:46:07 -05001694 png_set_tIME(png_ptr, info_ptr, &mod_time);
Guy Schalnat0d580581995-07-20 02:43:20 -05001695}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001696#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001697
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001698#if defined(PNG_READ_tEXt_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001699/* Note: this does not properly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001700void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001701png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001702{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001703 png_textp text_ptr;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001704 png_charp key;
Guy Schalnat6d764711995-12-19 03:22:19 -06001705 png_charp text;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001706 png_uint_32 skip = 0;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001707 png_size_t slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001708
1709 png_debug(1, "in png_handle_tEXt\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05001710
Guy Schalnate5a37791996-06-05 15:50:50 -05001711 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1712 png_error(png_ptr, "Missing IHDR before tEXt");
1713
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001714 if (png_ptr->mode & PNG_HAVE_IDAT)
1715 png_ptr->mode |= PNG_AFTER_IDAT;
1716
Andreas Dilger47a0c421997-05-16 02:46:07 -05001717#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001718 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001719 {
1720 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001721 skip = length - (png_uint_32)65535L;
1722 length = (png_uint_32)65535L;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001723 }
1724#endif
1725
1726 key = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001727 slength = (png_size_t)length;
1728 png_crc_read(png_ptr, (png_bytep)key, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001729
1730 if (png_crc_finish(png_ptr, skip))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001731 {
1732 png_free(png_ptr, key);
1733 return;
1734 }
1735
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001736 key[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05001737
1738 for (text = key; *text; text++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001739 /* empty loop to find end of key */ ;
Guy Schalnat0d580581995-07-20 02:43:20 -05001740
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001741 if (text != key + slength)
Guy Schalnat0d580581995-07-20 02:43:20 -05001742 text++;
1743
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001744 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
Andreas Dilger47a0c421997-05-16 02:46:07 -05001745 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1746 text_ptr->key = key;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001747#ifdef PNG_iTXt_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001748 text_ptr->lang = NULL;
1749 text_ptr->lang_key = NULL;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001750 text_ptr->itxt_length = 0;
1751#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001752 text_ptr->text = text;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001753 text_ptr->text_length = png_strlen(text);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001754
1755 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1756
Glenn Randers-Pehrson6d8f3b01999-10-23 08:39:18 -05001757 png_free(png_ptr, key);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001758 png_free(png_ptr, text_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -05001759}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001760#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001761
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001762#if defined(PNG_READ_zTXt_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001763/* note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001764void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001765png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001766{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001767 png_textp text_ptr;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001768 png_charp chunkdata;
Guy Schalnat6d764711995-12-19 03:22:19 -06001769 png_charp text;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001770 int comp_type;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001771 png_size_t slength, prefix_len, data_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001772
1773 png_debug(1, "in png_handle_zTXt\n");
Guy Schalnate5a37791996-06-05 15:50:50 -05001774 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1775 png_error(png_ptr, "Missing IHDR before zTXt");
1776
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001777 if (png_ptr->mode & PNG_HAVE_IDAT)
1778 png_ptr->mode |= PNG_AFTER_IDAT;
1779
Andreas Dilger47a0c421997-05-16 02:46:07 -05001780#ifdef PNG_MAX_MALLOC_64K
1781 /* We will no doubt have problems with chunks even half this size, but
1782 there is no hard and fast rule to tell us where to stop. */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001783 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001784 {
1785 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1786 png_crc_finish(png_ptr, length);
1787 return;
1788 }
1789#endif
1790
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001791 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001792 slength = (png_size_t)length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001793 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001794 if (png_crc_finish(png_ptr, 0))
1795 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001796 png_free(png_ptr, chunkdata);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001797 return;
1798 }
1799
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001800 chunkdata[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05001801
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001802 for (text = chunkdata; *text; text++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001803 /* empty loop */ ;
1804
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001805 /* zTXt must have some text after the chunkdataword */
1806 if (text == chunkdata + slength)
Guy Schalnat0d580581995-07-20 02:43:20 -05001807 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001808 comp_type = PNG_TEXT_COMPRESSION_NONE;
Guy Schalnat69b14481996-01-10 02:56:49 -06001809 png_warning(png_ptr, "Zero length zTXt chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -05001810 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001811 else
Guy Schalnat0d580581995-07-20 02:43:20 -05001812 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001813 comp_type = *(++text);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001814 text++; /* skip the compression_method byte */
Guy Schalnat0d580581995-07-20 02:43:20 -05001815 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001816 prefix_len = text - chunkdata;
Guy Schalnat0d580581995-07-20 02:43:20 -05001817
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001818 chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001819 (png_size_t)length, prefix_len, &data_len);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001820
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001821 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
Andreas Dilger47a0c421997-05-16 02:46:07 -05001822 text_ptr->compression = comp_type;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001823 text_ptr->key = chunkdata;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001824#ifdef PNG_iTXt_SUPPORTED
1825 text_ptr->lang = NULL;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001826 text_ptr->lang_key = NULL;
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001827 text_ptr->itxt_length = 0;
1828#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001829 text_ptr->text = chunkdata + prefix_len;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001830 text_ptr->text_length = data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001831
1832 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1833
1834 png_free(png_ptr, text_ptr);
1835 png_free(png_ptr, chunkdata);
1836}
1837#endif
1838
1839#if defined(PNG_READ_iTXt_SUPPORTED)
1840/* note: this does not correctly handle chunks that are > 64K under DOS */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001841void /* PRIVATE */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001842png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1843{
1844 png_textp text_ptr;
1845 png_charp chunkdata;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001846 png_charp key, lang, text, lang_key;
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001847 int comp_flag;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001848 int comp_type = 0;
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001849 png_size_t slength, prefix_len, data_len;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001850
1851 png_debug(1, "in png_handle_iTXt\n");
1852
1853 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1854 png_error(png_ptr, "Missing IHDR before iTXt");
1855
1856 if (png_ptr->mode & PNG_HAVE_IDAT)
1857 png_ptr->mode |= PNG_AFTER_IDAT;
1858
1859#ifdef PNG_MAX_MALLOC_64K
1860 /* We will no doubt have problems with chunks even half this size, but
1861 there is no hard and fast rule to tell us where to stop. */
1862 if (length > (png_uint_32)65535L)
1863 {
1864 png_warning(png_ptr,"iTXt chunk too large to fit in memory");
1865 png_crc_finish(png_ptr, length);
1866 return;
1867 }
1868#endif
1869
1870 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1871 slength = (png_size_t)length;
1872 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1873 if (png_crc_finish(png_ptr, 0))
1874 {
1875 png_free(png_ptr, chunkdata);
1876 return;
1877 }
1878
1879 chunkdata[slength] = 0x00;
1880
1881 for (lang = chunkdata; *lang; lang++)
1882 /* empty loop */ ;
1883 lang++; /* skip NUL separator */
1884
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001885 /* iTXt must have a language tag (possibly empty), two compression bytes,
1886 translated keyword (possibly empty), and possibly some text after the
1887 keyword */
1888
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001889 if (lang >= chunkdata + slength)
1890 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001891 comp_flag = PNG_TEXT_COMPRESSION_NONE;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001892 png_warning(png_ptr, "Zero length iTXt chunk");
1893 }
1894 else
1895 {
1896 comp_flag = *lang++;
1897 comp_type = *lang++;
1898 }
1899
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001900 for (lang_key = lang; *lang_key; lang_key++)
1901 /* empty loop */ ;
1902 lang_key++; /* skip NUL separator */
1903
1904 for (text = lang_key; *text; text++)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001905 /* empty loop */ ;
1906 text++; /* skip NUL separator */
1907
1908 prefix_len = text - chunkdata;
1909
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001910 key=chunkdata;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001911 if (comp_flag)
1912 chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
Glenn Randers-Pehrson68ea2432000-04-01 21:10:05 -06001913 (size_t)length, prefix_len, &data_len);
1914 else
1915 data_len=png_strlen(chunkdata + prefix_len);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001916 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001917 text_ptr->compression = (int)comp_flag + 1;
1918 text_ptr->lang_key = chunkdata+(lang_key-key);
1919 text_ptr->lang = chunkdata+(lang-key);
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001920 text_ptr->itxt_length = data_len;
1921 text_ptr->text_length = 0;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001922 text_ptr->key = chunkdata;
1923 text_ptr->text = chunkdata + prefix_len;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001924
1925 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1926
1927 png_free(png_ptr, text_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001928 png_free(png_ptr, chunkdata);
1929}
1930#endif
1931
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001932/* This function is called when we haven't found a handler for a
1933 chunk. If there isn't a problem with the chunk itself (ie bad
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001934 chunk name, CRC, or a critical chunk), the chunk is silently ignored
1935 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
1936 case it will be saved away to be written out later. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001937void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001938png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1939{
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001940 png_uint_32 skip = 0;
1941
Andreas Dilger47a0c421997-05-16 02:46:07 -05001942 png_debug(1, "in png_handle_unknown\n");
1943
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001944 if (png_ptr->mode & PNG_HAVE_IDAT)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001945 {
1946#ifdef PNG_USE_LOCAL_ARRAYS
1947 PNG_IDAT;
1948#endif
1949 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
1950 png_ptr->mode |= PNG_AFTER_IDAT;
1951 }
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001952
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001953 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
1954
1955 if (!(png_ptr->chunk_name[0] & 0x20))
1956 {
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001957#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001958 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
1959 HANDLE_CHUNK_ALWAYS
1960#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1961 && png_ptr->read_user_chunk_fn == (png_user_chunk_ptr)NULL
1962#endif
1963 )
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001964#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001965 png_chunk_error(png_ptr, "unknown critical chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001966 }
1967
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001968#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
1969 if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
1970 {
1971 png_unknown_chunk chunk;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001972
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001973#ifdef PNG_MAX_MALLOC_64K
1974 if (length > (png_uint_32)65535L)
1975 {
1976 png_warning(png_ptr, "unknown chunk too large to fit in memory");
1977 skip = length - (png_uint_32)65535L;
1978 length = (png_uint_32)65535L;
1979 }
1980#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001981 strcpy((png_charp)chunk.name, (png_charp)png_ptr->chunk_name);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001982 chunk.data = (png_bytep)png_malloc(png_ptr, length);
1983 png_crc_read(png_ptr, chunk.data, length);
1984 chunk.size = length;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001985#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
1986 if(png_ptr->read_user_chunk_fn != (png_user_chunk_ptr)NULL)
1987 {
1988 /* callback to user unknown chunk handler */
1989 if ((*(png_ptr->read_user_chunk_fn)) (png_ptr, &chunk) <= 0)
1990 {
1991 if (!(png_ptr->chunk_name[0] & 0x20))
1992 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
1993 HANDLE_CHUNK_ALWAYS)
1994 png_chunk_error(png_ptr, "unknown critical chunk");
1995 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
1996 }
1997 }
1998 else
1999#endif
2000 png_set_unknown_chunks(png_ptr, info_ptr, &chunk, 1);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002001 png_free(png_ptr, chunk.data);
2002 }
2003 else
2004#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002005 skip = length;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002006
2007 png_crc_finish(png_ptr, skip);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002008
2009#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2010 if (info_ptr == NULL)
2011 /* quiet compiler warnings about unused info_ptr */ ;
2012#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002013}
2014
2015/* This function is called to verify that a chunk name is valid.
2016 This function can't have the "critical chunk check" incorporated
Andreas Dilger47a0c421997-05-16 02:46:07 -05002017 into it, since in the future we will need to be able to call user
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002018 functions to handle unknown critical chunks after we check that
2019 the chunk name itself is valid. */
Andreas Dilger47a0c421997-05-16 02:46:07 -05002020
2021#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
2022
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002023void /* PRIVATE */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002024png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2025{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002026 png_debug(1, "in png_check_chunk_name\n");
2027 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2028 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002029 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06002030 png_chunk_error(png_ptr, "invalid chunk type");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002031 }
2032}
2033
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002034/* Combines the row recently read in with the existing pixels in the
2035 row. This routine takes care of alpha and transparency if requested.
Guy Schalnat0d580581995-07-20 02:43:20 -05002036 This routine also handles the two methods of progressive display
2037 of interlaced images, depending on the mask value.
2038 The mask value describes which pixels are to be combined with
2039 the row. The pattern always repeats every 8 pixels, so just 8
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002040 bits are needed. A one indicates the pixel is to be combined,
Guy Schalnat0d580581995-07-20 02:43:20 -05002041 a zero indicates the pixel is to be skipped. This is in addition
2042 to any alpha or transparency value associated with the pixel. If
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002043 you want all pixels to be combined, pass 0xff (255) in mask. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002044void /* PRIVATE */
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002045#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -05002046png_combine_row_c
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002047#else
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -05002048png_combine_row
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002049#endif /* PNG_HAVE_ASSEMBLER_COMBINE_ROW */
2050 (png_structp png_ptr, png_bytep row, int mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05002051{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002052 png_debug(1,"in png_combine_row\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05002053 if (mask == 0xff)
2054 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002055 png_memcpy(row, png_ptr->row_buf + 1,
Guy Schalnat0d580581995-07-20 02:43:20 -05002056 (png_size_t)((png_ptr->width *
2057 png_ptr->row_info.pixel_depth + 7) >> 3));
2058 }
2059 else
2060 {
2061 switch (png_ptr->row_info.pixel_depth)
2062 {
2063 case 1:
2064 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002065 png_bytep sp = png_ptr->row_buf + 1;
2066 png_bytep dp = row;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002067 int s_inc, s_start, s_end;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002068 int m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05002069 int shift;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002070 png_uint_32 i;
2071 png_uint_32 row_width = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05002072
Andreas Dilger47a0c421997-05-16 02:46:07 -05002073#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2074 if (png_ptr->transformations & PNG_PACKSWAP)
2075 {
2076 s_start = 0;
2077 s_end = 7;
2078 s_inc = 1;
2079 }
2080 else
2081#endif
2082 {
2083 s_start = 7;
2084 s_end = 0;
2085 s_inc = -1;
2086 }
2087
2088 shift = s_start;
2089
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002090 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002091 {
2092 if (m & mask)
2093 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002094 int value;
2095
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002096 value = (*sp >> shift) & 0x01;
Guy Schalnat0d580581995-07-20 02:43:20 -05002097 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002098 *dp |= (png_byte)(value << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05002099 }
2100
Andreas Dilger47a0c421997-05-16 02:46:07 -05002101 if (shift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05002102 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002103 shift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002104 sp++;
2105 dp++;
2106 }
2107 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002108 shift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002109
2110 if (m == 1)
2111 m = 0x80;
2112 else
2113 m >>= 1;
2114 }
2115 break;
2116 }
2117 case 2:
2118 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002119 png_bytep sp = png_ptr->row_buf + 1;
2120 png_bytep dp = row;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002121 int s_start, s_end, s_inc;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002122 int m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05002123 int shift;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002124 png_uint_32 i;
2125 png_uint_32 row_width = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05002126 int value;
2127
Andreas Dilger47a0c421997-05-16 02:46:07 -05002128#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2129 if (png_ptr->transformations & PNG_PACKSWAP)
2130 {
2131 s_start = 0;
2132 s_end = 6;
2133 s_inc = 2;
2134 }
2135 else
2136#endif
2137 {
2138 s_start = 6;
2139 s_end = 0;
2140 s_inc = -2;
2141 }
2142
2143 shift = s_start;
2144
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002145 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002146 {
2147 if (m & mask)
2148 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002149 value = (*sp >> shift) & 0x03;
Guy Schalnat0d580581995-07-20 02:43:20 -05002150 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002151 *dp |= (png_byte)(value << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05002152 }
2153
Andreas Dilger47a0c421997-05-16 02:46:07 -05002154 if (shift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05002155 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002156 shift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002157 sp++;
2158 dp++;
2159 }
2160 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002161 shift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002162 if (m == 1)
2163 m = 0x80;
2164 else
2165 m >>= 1;
2166 }
2167 break;
2168 }
2169 case 4:
2170 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002171 png_bytep sp = png_ptr->row_buf + 1;
2172 png_bytep dp = row;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002173 int s_start, s_end, s_inc;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002174 int m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05002175 int shift;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002176 png_uint_32 i;
2177 png_uint_32 row_width = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05002178 int value;
2179
Andreas Dilger47a0c421997-05-16 02:46:07 -05002180#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2181 if (png_ptr->transformations & PNG_PACKSWAP)
2182 {
2183 s_start = 0;
2184 s_end = 4;
2185 s_inc = 4;
2186 }
2187 else
2188#endif
2189 {
2190 s_start = 4;
2191 s_end = 0;
2192 s_inc = -4;
2193 }
2194 shift = s_start;
2195
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002196 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002197 {
2198 if (m & mask)
2199 {
2200 value = (*sp >> shift) & 0xf;
2201 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002202 *dp |= (png_byte)(value << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05002203 }
2204
Andreas Dilger47a0c421997-05-16 02:46:07 -05002205 if (shift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05002206 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002207 shift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002208 sp++;
2209 dp++;
2210 }
2211 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002212 shift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002213 if (m == 1)
2214 m = 0x80;
2215 else
2216 m >>= 1;
2217 }
2218 break;
2219 }
2220 default:
2221 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002222 png_bytep sp = png_ptr->row_buf + 1;
2223 png_bytep dp = row;
2224 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2225 png_uint_32 i;
2226 png_uint_32 row_width = png_ptr->width;
2227 png_byte m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05002228
Guy Schalnat0d580581995-07-20 02:43:20 -05002229
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002230 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002231 {
2232 if (m & mask)
2233 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002234 png_memcpy(dp, sp, pixel_bytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05002235 }
2236
2237 sp += pixel_bytes;
2238 dp += pixel_bytes;
2239
2240 if (m == 1)
2241 m = 0x80;
2242 else
2243 m >>= 1;
2244 }
2245 break;
2246 }
2247 }
2248 }
2249}
2250
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002251#if defined(PNG_READ_INTERLACING_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002252void /* PRIVATE */
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002253#ifdef PNG_HAVE_ASSEMBLER_READ_INTERLACE
2254png_do_read_interlace_c
2255#else
2256png_do_read_interlace
2257#endif /* PNG_HAVE_ASSEMBLER_READ_INTERLACE */
2258 (png_row_infop row_info, png_bytep row, int pass,
Andreas Dilger47a0c421997-05-16 02:46:07 -05002259 png_uint_32 transformations)
Guy Schalnat0d580581995-07-20 02:43:20 -05002260{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002261#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002262 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002263
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002264 /* offset to next interlace block */
2265 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002266#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002267
Andreas Dilger47a0c421997-05-16 02:46:07 -05002268 png_debug(1,"in png_do_read_interlace\n");
2269 if (row != NULL && row_info != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05002270 {
2271 png_uint_32 final_width;
2272
2273 final_width = row_info->width * png_pass_inc[pass];
2274
2275 switch (row_info->pixel_depth)
2276 {
2277 case 1:
2278 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002279 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2280 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06002281 int sshift, dshift;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002282 int s_start, s_end, s_inc;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002283 int jstop = png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05002284 png_byte v;
2285 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002286 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -05002287
Andreas Dilger47a0c421997-05-16 02:46:07 -05002288#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2289 if (transformations & PNG_PACKSWAP)
2290 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002291 sshift = (int)((row_info->width + 7) & 0x07);
2292 dshift = (int)((final_width + 7) & 0x07);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002293 s_start = 7;
2294 s_end = 0;
2295 s_inc = -1;
2296 }
2297 else
2298#endif
2299 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002300 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2301 dshift = 7 - (int)((final_width + 7) & 0x07);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002302 s_start = 0;
2303 s_end = 7;
2304 s_inc = 1;
2305 }
2306
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002307 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002308 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002309 v = (png_byte)((*sp >> sshift) & 0x01);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002310 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002311 {
2312 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2313 *dp |= (png_byte)(v << dshift);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002314 if (dshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05002315 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002316 dshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002317 dp--;
2318 }
2319 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002320 dshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002321 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002322 if (sshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05002323 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002324 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002325 sp--;
2326 }
2327 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002328 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002329 }
2330 break;
2331 }
2332 case 2:
2333 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002334 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2335 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06002336 int sshift, dshift;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002337 int s_start, s_end, s_inc;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002338 int jstop = png_pass_inc[pass];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002339 png_uint_32 i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002340
Andreas Dilger47a0c421997-05-16 02:46:07 -05002341#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2342 if (transformations & PNG_PACKSWAP)
2343 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002344 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2345 dshift = (int)(((final_width + 3) & 0x03) << 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002346 s_start = 6;
2347 s_end = 0;
2348 s_inc = -2;
2349 }
2350 else
2351#endif
2352 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002353 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2354 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002355 s_start = 0;
2356 s_end = 6;
2357 s_inc = 2;
2358 }
2359
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002360 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002361 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002362 png_byte v;
2363 int j;
2364
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002365 v = (png_byte)((*sp >> sshift) & 0x03);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002366 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002367 {
2368 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06002369 *dp |= (png_byte)(v << dshift);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002370 if (dshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05002371 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002372 dshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002373 dp--;
2374 }
2375 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002376 dshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002377 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002378 if (sshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05002379 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002380 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002381 sp--;
2382 }
2383 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002384 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002385 }
2386 break;
2387 }
2388 case 4:
2389 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002390 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2391 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06002392 int sshift, dshift;
Andreas Dilger47a0c421997-05-16 02:46:07 -05002393 int s_start, s_end, s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002394 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002395 int jstop = png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05002396
Andreas Dilger47a0c421997-05-16 02:46:07 -05002397#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2398 if (transformations & PNG_PACKSWAP)
2399 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002400 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2401 dshift = (int)(((final_width + 1) & 0x01) << 2);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002402 s_start = 4;
2403 s_end = 0;
2404 s_inc = -4;
2405 }
2406 else
2407#endif
2408 {
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06002409 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2410 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002411 s_start = 0;
2412 s_end = 4;
2413 s_inc = 4;
2414 }
2415
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002416 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002417 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002418 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002419 int j;
2420
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002421 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002422 {
2423 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06002424 *dp |= (png_byte)(v << dshift);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002425 if (dshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05002426 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002427 dshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002428 dp--;
2429 }
2430 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002431 dshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002432 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05002433 if (sshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05002434 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002435 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05002436 sp--;
2437 }
2438 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05002439 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05002440 }
2441 break;
2442 }
2443 default:
2444 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002445 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2446 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2447 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002448
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002449 int jstop = png_pass_inc[pass];
Andreas Dilger47a0c421997-05-16 02:46:07 -05002450 png_uint_32 i;
Guy Schalnat0d580581995-07-20 02:43:20 -05002451
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002452 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002453 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05002454 png_byte v[8];
2455 int j;
2456
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002457 png_memcpy(v, sp, pixel_bytes);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002458 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05002459 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002460 png_memcpy(dp, v, pixel_bytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05002461 dp -= pixel_bytes;
2462 }
2463 sp -= pixel_bytes;
2464 }
2465 break;
2466 }
2467 }
2468 row_info->width = final_width;
2469 row_info->rowbytes = ((final_width *
2470 (png_uint_32)row_info->pixel_depth + 7) >> 3);
2471 }
2472}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002473#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002474
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002475void /* PRIVATE */
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05002476#ifdef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
2477png_read_filter_row_c
2478#else
2479png_read_filter_row
2480#endif /* PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
2481 (png_structp png_ptr, png_row_infop row_info, png_bytep row,
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002482 png_bytep prev_row, int filter)
2483{
2484 png_debug(1, "in png_read_filter_row\n");
2485 png_debug2(2,"row = %d, filter = %d\n", png_ptr->row_number, filter);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002486 switch (filter)
2487 {
2488 case PNG_FILTER_VALUE_NONE:
2489 break;
2490 case PNG_FILTER_VALUE_SUB:
2491 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002492 png_uint_32 i;
2493 png_uint_32 istop = row_info->rowbytes;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002494 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002495 png_bytep rp = row + bpp;
2496 png_bytep lp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002497
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002498 for (i = bpp; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002499 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002500 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2501 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002502 }
2503 break;
2504 }
2505 case PNG_FILTER_VALUE_UP:
2506 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002507 png_uint_32 i;
2508 png_uint_32 istop = row_info->rowbytes;
2509 png_bytep rp = row;
2510 png_bytep pp = prev_row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002511
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002512 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002513 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002514 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2515 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002516 }
2517 break;
2518 }
2519 case PNG_FILTER_VALUE_AVG:
2520 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002521 png_uint_32 i;
2522 png_bytep rp = row;
2523 png_bytep pp = prev_row;
2524 png_bytep lp = row;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002525 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002526 png_uint_32 istop = row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002527
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002528 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002529 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002530 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002531 ((int)(*pp++) / 2 )) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002532 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002533 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002534
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002535 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002536 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002537 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002538 (int)(*pp++ + *lp++) / 2 ) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002539 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002540 }
2541 break;
2542 }
2543 case PNG_FILTER_VALUE_PAETH:
2544 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002545 png_uint_32 i;
2546 png_bytep rp = row;
2547 png_bytep pp = prev_row;
2548 png_bytep lp = row;
2549 png_bytep cp = prev_row;
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002550 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002551 png_uint_32 istop=row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002552
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002553 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002554 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002555 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2556 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002557 }
2558
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002559 for (i = 0; i < istop; i++) /* use leftover rp,pp */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002560 {
2561 int a, b, c, pa, pb, pc, p;
2562
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002563 a = *lp++;
2564 b = *pp++;
2565 c = *cp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002566
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002567 p = b - c;
2568 pc = a - c;
2569
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002570#ifdef PNG_USE_ABS
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002571 pa = abs(p);
2572 pb = abs(pc);
2573 pc = abs(p + pc);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002574#else
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002575 pa = p < 0 ? -p : p;
2576 pb = pc < 0 ? -pc : pc;
2577 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002578#endif
2579
2580 /*
2581 if (pa <= pb && pa <= pc)
2582 p = a;
2583 else if (pb <= pc)
2584 p = b;
2585 else
2586 p = c;
2587 */
2588
2589 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2590
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002591 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2592 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002593 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002594 break;
2595 }
2596 default:
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002597 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2598 *row=0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002599 break;
2600 }
2601}
Guy Schalnat0d580581995-07-20 02:43:20 -05002602
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002603void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002604png_read_finish_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002605{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002606#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002607 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002608
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002609 /* start of interlace block */
2610 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002611
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002612 /* offset to next interlace block */
2613 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002614
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002615 /* start of interlace block in the y direction */
2616 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002617
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002618 /* offset to next interlace block in the y direction */
2619 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002620#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002621
Andreas Dilger47a0c421997-05-16 02:46:07 -05002622 png_debug(1, "in png_read_finish_row\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05002623 png_ptr->row_number++;
2624 if (png_ptr->row_number < png_ptr->num_rows)
2625 return;
2626
2627 if (png_ptr->interlaced)
2628 {
2629 png_ptr->row_number = 0;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002630 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05002631 do
2632 {
2633 png_ptr->pass++;
2634 if (png_ptr->pass >= 7)
2635 break;
2636 png_ptr->iwidth = (png_ptr->width +
2637 png_pass_inc[png_ptr->pass] - 1 -
2638 png_pass_start[png_ptr->pass]) /
2639 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002640 png_ptr->irowbytes = ((png_ptr->iwidth *
2641 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2642
Guy Schalnat0d580581995-07-20 02:43:20 -05002643 if (!(png_ptr->transformations & PNG_INTERLACE))
2644 {
2645 png_ptr->num_rows = (png_ptr->height +
2646 png_pass_yinc[png_ptr->pass] - 1 -
2647 png_pass_ystart[png_ptr->pass]) /
2648 png_pass_yinc[png_ptr->pass];
2649 if (!(png_ptr->num_rows))
2650 continue;
2651 }
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002652 else /* if (png_ptr->transformations & PNG_INTERLACE) */
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002653 break;
Guy Schalnat0d580581995-07-20 02:43:20 -05002654 } while (png_ptr->iwidth == 0);
2655
2656 if (png_ptr->pass < 7)
2657 return;
2658 }
2659
Guy Schalnate5a37791996-06-05 15:50:50 -05002660 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
Guy Schalnat0d580581995-07-20 02:43:20 -05002661 {
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002662#ifdef PNG_USE_LOCAL_ARRAYS
2663 PNG_IDAT;
2664#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002665 char extra;
2666 int ret;
2667
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002668 png_ptr->zstream.next_out = (Byte *)&extra;
2669 png_ptr->zstream.avail_out = (uInt)1;
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -06002670 for(;;)
Guy Schalnat0d580581995-07-20 02:43:20 -05002671 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002672 if (!(png_ptr->zstream.avail_in))
Guy Schalnat0d580581995-07-20 02:43:20 -05002673 {
2674 while (!png_ptr->idat_size)
2675 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002676 png_byte chunk_length[4];
Guy Schalnat0d580581995-07-20 02:43:20 -05002677
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002678 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -05002679
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002680 png_read_data(png_ptr, chunk_length, 4);
2681 png_ptr->idat_size = png_get_uint_32(chunk_length);
2682
Guy Schalnat0d580581995-07-20 02:43:20 -05002683 png_reset_crc(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002684 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002685 if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
Guy Schalnat6d764711995-12-19 03:22:19 -06002686 png_error(png_ptr, "Not enough image data");
Guy Schalnat0d580581995-07-20 02:43:20 -05002687
2688 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002689 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2690 png_ptr->zstream.next_in = png_ptr->zbuf;
Guy Schalnat0d580581995-07-20 02:43:20 -05002691 if (png_ptr->zbuf_size > png_ptr->idat_size)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002692 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2693 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2694 png_ptr->idat_size -= png_ptr->zstream.avail_in;
Guy Schalnat0d580581995-07-20 02:43:20 -05002695 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002696 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnat0d580581995-07-20 02:43:20 -05002697 if (ret == Z_STREAM_END)
2698 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002699 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
Guy Schalnat0d580581995-07-20 02:43:20 -05002700 png_ptr->idat_size)
Guy Schalnat6d764711995-12-19 03:22:19 -06002701 png_error(png_ptr, "Extra compressed data");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002702 png_ptr->mode |= PNG_AFTER_IDAT;
2703 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Guy Schalnat0d580581995-07-20 02:43:20 -05002704 break;
2705 }
2706 if (ret != Z_OK)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002707 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
Guy Schalnate5a37791996-06-05 15:50:50 -05002708 "Decompression Error");
Guy Schalnat0d580581995-07-20 02:43:20 -05002709
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002710 if (!(png_ptr->zstream.avail_out))
Guy Schalnat6d764711995-12-19 03:22:19 -06002711 png_error(png_ptr, "Extra compressed data");
Guy Schalnat0d580581995-07-20 02:43:20 -05002712
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -06002713 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002714 png_ptr->zstream.avail_out = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002715 }
2716
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002717 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
Guy Schalnat6d764711995-12-19 03:22:19 -06002718 png_error(png_ptr, "Extra compression data");
Guy Schalnat0d580581995-07-20 02:43:20 -05002719
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002720 inflateReset(&png_ptr->zstream);
Guy Schalnat0d580581995-07-20 02:43:20 -05002721
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002722 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnat0d580581995-07-20 02:43:20 -05002723}
2724
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05002725void /* PRIVATE */
Guy Schalnat6d764711995-12-19 03:22:19 -06002726png_read_start_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002727{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002728#ifdef PNG_USE_LOCAL_ARRAYS
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002729 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002730
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002731 /* start of interlace block */
2732 const int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002733
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002734 /* offset to next interlace block */
2735 const int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002736
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002737 /* start of interlace block in the y direction */
2738 const int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002739
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06002740 /* offset to next interlace block in the y direction */
2741 const int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -06002742#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06002743
Guy Schalnat0d580581995-07-20 02:43:20 -05002744 int max_pixel_depth;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002745 png_uint_32 row_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05002746
Andreas Dilger47a0c421997-05-16 02:46:07 -05002747 png_debug(1, "in png_read_start_row\n");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002748 png_ptr->zstream.avail_in = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002749 png_init_read_transformations(png_ptr);
2750 if (png_ptr->interlaced)
2751 {
2752 if (!(png_ptr->transformations & PNG_INTERLACE))
2753 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2754 png_pass_ystart[0]) / png_pass_yinc[0];
2755 else
2756 png_ptr->num_rows = png_ptr->height;
2757
2758 png_ptr->iwidth = (png_ptr->width +
2759 png_pass_inc[png_ptr->pass] - 1 -
2760 png_pass_start[png_ptr->pass]) /
2761 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002762
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002763 row_bytes = ((png_ptr->iwidth *
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002764 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002765 png_ptr->irowbytes = (png_size_t)row_bytes;
2766 if((png_uint_32)png_ptr->irowbytes != row_bytes)
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002767 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
Guy Schalnat0d580581995-07-20 02:43:20 -05002768 }
2769 else
2770 {
2771 png_ptr->num_rows = png_ptr->height;
2772 png_ptr->iwidth = png_ptr->width;
2773 png_ptr->irowbytes = png_ptr->rowbytes + 1;
2774 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002775 max_pixel_depth = png_ptr->pixel_depth;
2776
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002777#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05002778 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05002779 max_pixel_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002780#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002781
Guy Schalnate5a37791996-06-05 15:50:50 -05002782#if defined(PNG_READ_EXPAND_SUPPORTED)
2783 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05002784 {
2785 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2786 {
2787 if (png_ptr->num_trans)
2788 max_pixel_depth = 32;
2789 else
2790 max_pixel_depth = 24;
2791 }
2792 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2793 {
2794 if (max_pixel_depth < 8)
2795 max_pixel_depth = 8;
2796 if (png_ptr->num_trans)
2797 max_pixel_depth *= 2;
2798 }
2799 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2800 {
2801 if (png_ptr->num_trans)
2802 {
2803 max_pixel_depth *= 4;
2804 max_pixel_depth /= 3;
2805 }
2806 }
2807 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002808#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002809
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002810#if defined(PNG_READ_FILLER_SUPPORTED)
2811 if (png_ptr->transformations & (PNG_FILLER))
Guy Schalnat0d580581995-07-20 02:43:20 -05002812 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002813 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2814 max_pixel_depth = 32;
2815 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002816 {
2817 if (max_pixel_depth <= 8)
2818 max_pixel_depth = 16;
2819 else
2820 max_pixel_depth = 32;
2821 }
2822 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2823 {
2824 if (max_pixel_depth <= 32)
2825 max_pixel_depth = 32;
2826 else
2827 max_pixel_depth = 64;
2828 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002829 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002830#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002831
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002832#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05002833 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
2834 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002835 if (
2836#if defined(PNG_READ_EXPAND_SUPPORTED)
2837 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
2838#endif
2839#if defined(PNG_READ_FILLER_SUPPORTED)
2840 (png_ptr->transformations & (PNG_FILLER)) ||
2841#endif
2842 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
Guy Schalnat0d580581995-07-20 02:43:20 -05002843 {
2844 if (max_pixel_depth <= 16)
2845 max_pixel_depth = 32;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002846 else
Guy Schalnat0d580581995-07-20 02:43:20 -05002847 max_pixel_depth = 64;
2848 }
2849 else
2850 {
2851 if (max_pixel_depth <= 8)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06002852 {
2853 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2854 max_pixel_depth = 32;
2855 else
2856 max_pixel_depth = 24;
2857 }
2858 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
2859 max_pixel_depth = 64;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002860 else
Guy Schalnat0d580581995-07-20 02:43:20 -05002861 max_pixel_depth = 48;
2862 }
2863 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002864#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002865
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05002866#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
2867defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
Glenn Randers-Pehrsonbcfd15d1999-10-01 14:22:25 -05002868 if(png_ptr->transformations & PNG_USER_TRANSFORM)
2869 {
2870 int user_pixel_depth=png_ptr->user_transform_depth*
2871 png_ptr->user_transform_channels;
2872 if(user_pixel_depth > max_pixel_depth)
2873 max_pixel_depth=user_pixel_depth;
2874 }
2875#endif
2876
Guy Schalnat0d580581995-07-20 02:43:20 -05002877 /* align the width on the next larger 8 pixels. Mainly used
2878 for interlacing */
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002879 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
Guy Schalnat0d580581995-07-20 02:43:20 -05002880 /* calculate the maximum bytes needed, adding a byte and a pixel
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002881 for safety's sake */
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002882 row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
Guy Schalnat0d580581995-07-20 02:43:20 -05002883 1 + ((max_pixel_depth + 7) >> 3);
2884#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002885 if (row_bytes > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05002886 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05002887#endif
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002888 png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, row_bytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05002889
2890#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002891 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05002892 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05002893#endif
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002894 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
2895 png_ptr->rowbytes + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05002896
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002897 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002898
2899 png_debug1(3, "width = %d,\n", png_ptr->width);
2900 png_debug1(3, "height = %d,\n", png_ptr->height);
2901 png_debug1(3, "iwidth = %d,\n", png_ptr->iwidth);
2902 png_debug1(3, "num_rows = %d\n", png_ptr->num_rows);
2903 png_debug1(3, "rowbytes = %d,\n", png_ptr->rowbytes);
2904 png_debug1(3, "irowbytes = %d,\n", png_ptr->irowbytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05002905
Guy Schalnate5a37791996-06-05 15:50:50 -05002906 png_ptr->flags |= PNG_FLAG_ROW_INIT;
Guy Schalnat0d580581995-07-20 02:43:20 -05002907}