blob: 3e9c7089baf546198cc5ec34aba8c462f3dc1503 [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-Pehrsonf8b008c1999-09-18 10:54:36 -05004 * libpng 1.0.4 - September 18, 1999
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-Pehrsonc9442291999-01-06 21:50:16 -06008 * Copyright (c) 1998, 1999 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
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -050017#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
18#include "pngasmrd.h"
19#endif
20
Andreas Dilger47a0c421997-05-16 02:46:07 -050021#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050022/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
Guy Schalnat0d580581995-07-20 02:43:20 -050023png_uint_32
Guy Schalnat6d764711995-12-19 03:22:19 -060024png_get_uint_32(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050025{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050026 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
Guy Schalnat0d580581995-07-20 02:43:20 -050027 ((png_uint_32)(*(buf + 1)) << 16) +
28 ((png_uint_32)(*(buf + 2)) << 8) +
29 (png_uint_32)(*(buf + 3));
30
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060031 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050032}
33
Andreas Dilger47a0c421997-05-16 02:46:07 -050034#if defined(PNG_READ_pCAL_SUPPORTED)
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050035/* Grab a signed 32-bit integer from a buffer in big-endian format. The
Andreas Dilger47a0c421997-05-16 02:46:07 -050036 * data is stored in the PNG file in two's complement format, and it is
37 * assumed that the machine format for signed integers is the same. */
38png_int_32
39png_get_int_32(png_bytep buf)
40{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050041 png_int_32 i = ((png_int_32)(*buf) << 24) +
Andreas Dilger47a0c421997-05-16 02:46:07 -050042 ((png_int_32)(*(buf + 1)) << 16) +
43 ((png_int_32)(*(buf + 2)) << 8) +
44 (png_int_32)(*(buf + 3));
45
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060046 return (i);
Andreas Dilger47a0c421997-05-16 02:46:07 -050047}
48#endif /* PNG_READ_pCAL_SUPPORTED */
49
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -050050/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
Guy Schalnat0d580581995-07-20 02:43:20 -050051png_uint_16
Guy Schalnat6d764711995-12-19 03:22:19 -060052png_get_uint_16(png_bytep buf)
Guy Schalnat0d580581995-07-20 02:43:20 -050053{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050054 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060055 (png_uint_16)(*(buf + 1)));
Guy Schalnat0d580581995-07-20 02:43:20 -050056
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -060057 return (i);
Guy Schalnat0d580581995-07-20 02:43:20 -050058}
Andreas Dilger47a0c421997-05-16 02:46:07 -050059#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -050060
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060061/* Read data, and (optionally) run it through the CRC. */
Guy Schalnat0d580581995-07-20 02:43:20 -050062void
Andreas Dilger47a0c421997-05-16 02:46:07 -050063png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
Guy Schalnat0d580581995-07-20 02:43:20 -050064{
Guy Schalnat6d764711995-12-19 03:22:19 -060065 png_read_data(png_ptr, buf, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -050066 png_calculate_crc(png_ptr, buf, length);
Guy Schalnat0d580581995-07-20 02:43:20 -050067}
68
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060069/* Optionally skip data and then check the CRC. Depending on whether we
70 are reading a ancillary or critical chunk, and how the program has set
Andreas Dilger47a0c421997-05-16 02:46:07 -050071 things up, we may calculate the CRC on the data and print a message.
72 Returns '1' if there was a CRC error, '0' otherwise. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060073int
74png_crc_finish(png_structp png_ptr, png_uint_32 skip)
Guy Schalnat0d580581995-07-20 02:43:20 -050075{
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050076 png_size_t i;
77 png_size_t istop = png_ptr->zbuf_size;
Guy Schalnat0d580581995-07-20 02:43:20 -050078
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -050079 for (i = (png_size_t)skip; i > istop; i -= istop)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060080 {
Andreas Dilger47a0c421997-05-16 02:46:07 -050081 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
Guy Schalnat0d580581995-07-20 02:43:20 -050082 }
83 if (i)
84 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -050085 png_crc_read(png_ptr, png_ptr->zbuf, i);
Guy Schalnat0d580581995-07-20 02:43:20 -050086 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060087
Andreas Dilger47a0c421997-05-16 02:46:07 -050088 if (png_crc_error(png_ptr))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060089 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060090 if ((png_ptr->chunk_name[0] & 0x20 && /* Ancillary */
91 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
92 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
93 png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))
94 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -060095 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060096 }
97 else
98 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -060099 png_chunk_error(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600100 }
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600101 return (1);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600102 }
103
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600104 return (0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500105}
106
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600107/* Compare the CRC stored in the PNG file with that calculated by libpng from
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600108 the data it has read thus far. */
109int
110png_crc_error(png_structp png_ptr)
111{
112 png_byte crc_bytes[4];
113 png_uint_32 crc;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500114 int need_crc = 1;
115
116 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
117 {
118 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
119 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
120 need_crc = 0;
121 }
122 else /* critical */
123 {
124 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
125 need_crc = 0;
126 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600127
128 png_read_data(png_ptr, crc_bytes, 4);
129
Andreas Dilger47a0c421997-05-16 02:46:07 -0500130 if (need_crc)
131 {
132 crc = png_get_uint_32(crc_bytes);
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600133 return ((int)(crc != png_ptr->crc));
Andreas Dilger47a0c421997-05-16 02:46:07 -0500134 }
135 else
Glenn Randers-Pehrsonb2120021998-01-31 20:07:59 -0600136 return (0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600137}
138
139
Guy Schalnat0d580581995-07-20 02:43:20 -0500140/* read and check the IDHR chunk */
141void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600142png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500143{
144 png_byte buf[13];
145 png_uint_32 width, height;
146 int bit_depth, color_type, compression_type, filter_type;
147 int interlace_type;
148
Andreas Dilger47a0c421997-05-16 02:46:07 -0500149 png_debug(1, "in png_handle_IHDR\n");
150
Guy Schalnate5a37791996-06-05 15:50:50 -0500151 if (png_ptr->mode != PNG_BEFORE_IHDR)
152 png_error(png_ptr, "Out of place IHDR");
153
Guy Schalnat0d580581995-07-20 02:43:20 -0500154 /* check the length */
155 if (length != 13)
Guy Schalnat6d764711995-12-19 03:22:19 -0600156 png_error(png_ptr, "Invalid IHDR chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -0500157
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600158 png_ptr->mode |= PNG_HAVE_IHDR;
159
Guy Schalnat0d580581995-07-20 02:43:20 -0500160 png_crc_read(png_ptr, buf, 13);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600161 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500162
163 width = png_get_uint_32(buf);
164 height = png_get_uint_32(buf + 4);
165 bit_depth = buf[8];
166 color_type = buf[9];
167 compression_type = buf[10];
168 filter_type = buf[11];
169 interlace_type = buf[12];
170
171 /* check for width and height valid values */
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500172 if (width == 0 || width > PNG_MAX_UINT || height == 0 ||
173 height > PNG_MAX_UINT)
Guy Schalnate5a37791996-06-05 15:50:50 -0500174 png_error(png_ptr, "Invalid image size in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500175
176 /* check other values */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500177 if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
178 bit_depth != 8 && bit_depth != 16)
Guy Schalnate5a37791996-06-05 15:50:50 -0500179 png_error(png_ptr, "Invalid bit depth in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500180
181 if (color_type < 0 || color_type == 1 ||
182 color_type == 5 || color_type > 6)
Guy Schalnate5a37791996-06-05 15:50:50 -0500183 png_error(png_ptr, "Invalid color type in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500184
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500185 if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) ||
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600186 ((color_type == PNG_COLOR_TYPE_RGB ||
187 color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
188 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
189 png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500190
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600191 if (interlace_type >= PNG_INTERLACE_LAST)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600192 png_error(png_ptr, "Unknown interlace method in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500193
Andreas Dilger47a0c421997-05-16 02:46:07 -0500194 if (compression_type != PNG_COMPRESSION_TYPE_BASE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600195 png_error(png_ptr, "Unknown compression method in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500196
Andreas Dilger47a0c421997-05-16 02:46:07 -0500197 if (filter_type != PNG_FILTER_TYPE_BASE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600198 png_error(png_ptr, "Unknown filter method in IHDR");
Guy Schalnat0d580581995-07-20 02:43:20 -0500199
200 /* set internal variables */
201 png_ptr->width = width;
202 png_ptr->height = height;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600203 png_ptr->bit_depth = (png_byte)bit_depth;
204 png_ptr->interlaced = (png_byte)interlace_type;
205 png_ptr->color_type = (png_byte)color_type;
Guy Schalnat0d580581995-07-20 02:43:20 -0500206
207 /* find number of channels */
208 switch (png_ptr->color_type)
209 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500210 case PNG_COLOR_TYPE_GRAY:
211 case PNG_COLOR_TYPE_PALETTE:
Guy Schalnat0d580581995-07-20 02:43:20 -0500212 png_ptr->channels = 1;
213 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500214 case PNG_COLOR_TYPE_RGB:
Guy Schalnat0d580581995-07-20 02:43:20 -0500215 png_ptr->channels = 3;
216 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500217 case PNG_COLOR_TYPE_GRAY_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500218 png_ptr->channels = 2;
219 break;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500220 case PNG_COLOR_TYPE_RGB_ALPHA:
Guy Schalnat0d580581995-07-20 02:43:20 -0500221 png_ptr->channels = 4;
222 break;
223 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600224
Guy Schalnat0d580581995-07-20 02:43:20 -0500225 /* set up other useful info */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600226 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600227 png_ptr->channels);
Guy Schalnat0d580581995-07-20 02:43:20 -0500228 png_ptr->rowbytes = ((png_ptr->width *
229 (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500230 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
231 png_debug1(3,"channels = %d\n", png_ptr->channels);
232 png_debug1(3,"rowbytes = %d\n", png_ptr->rowbytes);
233 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
234 color_type, interlace_type, compression_type, filter_type);
Guy Schalnat0d580581995-07-20 02:43:20 -0500235}
236
237/* read and check the palette */
238void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600239png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500240{
Guy Schalnat6d764711995-12-19 03:22:19 -0600241 png_colorp palette;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600242 int num, i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500243
Andreas Dilger47a0c421997-05-16 02:46:07 -0500244 png_debug(1, "in png_handle_PLTE\n");
245
Guy Schalnate5a37791996-06-05 15:50:50 -0500246 if (!(png_ptr->mode & PNG_HAVE_IHDR))
247 png_error(png_ptr, "Missing IHDR before PLTE");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600248 else if (png_ptr->mode & PNG_HAVE_IDAT)
249 {
250 png_warning(png_ptr, "Invalid PLTE after IDAT");
251 png_crc_finish(png_ptr, length);
252 return;
253 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500254 else if (png_ptr->mode & PNG_HAVE_PLTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600255 png_error(png_ptr, "Duplicate PLTE chunk");
256
257 png_ptr->mode |= PNG_HAVE_PLTE;
Guy Schalnate5a37791996-06-05 15:50:50 -0500258
259#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
260 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
261 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600262 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500263 return;
264 }
265#endif
266
Guy Schalnat0d580581995-07-20 02:43:20 -0500267 if (length % 3)
Guy Schalnate5a37791996-06-05 15:50:50 -0500268 {
269 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
270 {
271 png_warning(png_ptr, "Invalid palette chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600272 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500273 return;
274 }
275 else
276 {
277 png_error(png_ptr, "Invalid palette chunk");
278 }
279 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500280
281 num = (int)length / 3;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600282 palette = (png_colorp)png_zalloc(png_ptr, (uInt)num, sizeof (png_color));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600283 png_ptr->flags |= PNG_FLAG_FREE_PALETTE;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600284 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500285 {
286 png_byte buf[3];
287
288 png_crc_read(png_ptr, buf, 3);
289 /* don't depend upon png_color being any order */
290 palette[i].red = buf[0];
291 palette[i].green = buf[1];
292 palette[i].blue = buf[2];
293 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600294
295 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
296 whatever the normal CRC configuration tells us. However, if we
297 have an RGB image, the PLTE can be considered ancillary, so
298 we will act as though it is. */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600299#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600300 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600301#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600302 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500303 png_crc_finish(png_ptr, 0);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600304 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600305#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600306 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
307 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600308 /* If we don't want to use the data from an ancillary chunk,
309 we have two options: an error abort, or a warning and we
310 ignore the data in this chunk (which should be OK, since
311 it's considered ancillary for a RGB or RGBA image). */
312 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
313 {
314 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
315 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600316 png_chunk_error(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600317 }
318 else
319 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600320 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger47a0c421997-05-16 02:46:07 -0500321 png_ptr->flags &= ~PNG_FLAG_FREE_PALETTE;
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600322 png_zfree(png_ptr, palette);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600323 return;
324 }
325 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500326 /* Otherwise, we (optionally) emit a warning and use the chunk. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600327 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
328 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600329 png_chunk_warning(png_ptr, "CRC error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600330 }
331 }
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600332#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500333 png_ptr->palette = palette;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600334 png_ptr->num_palette = (png_uint_16)num;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500335 png_set_PLTE(png_ptr, info_ptr, palette, num);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500336
337#if defined (PNG_READ_tRNS_SUPPORTED)
338 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
339 {
340 if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tRNS)
341 {
342 if (png_ptr->num_trans > png_ptr->num_palette)
343 {
344 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
345 png_ptr->num_trans = png_ptr->num_palette;
346 }
347 }
348 }
349#endif
350
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600351}
Guy Schalnate5a37791996-06-05 15:50:50 -0500352
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600353void
354png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
355{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500356 png_debug(1, "in png_handle_IEND\n");
357
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600358 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
359 {
360 png_error(png_ptr, "No image in file");
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600361
362 /* to quiet compiler warnings about unused info_ptr */
363 if (info_ptr == NULL)
364 return;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600365 }
366
367 png_ptr->mode |= PNG_AFTER_IDAT | PNG_HAVE_IEND;
368
369 if (length != 0)
370 {
371 png_warning(png_ptr, "Incorrect IEND chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600372 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500373 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500374}
375
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500376#if defined(PNG_READ_gAMA_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500377void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600378png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500379{
380 png_uint_32 igamma;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500381 float file_gamma;
Guy Schalnat0d580581995-07-20 02:43:20 -0500382 png_byte buf[4];
383
Andreas Dilger47a0c421997-05-16 02:46:07 -0500384 png_debug(1, "in png_handle_gAMA\n");
385
Guy Schalnate5a37791996-06-05 15:50:50 -0500386 if (!(png_ptr->mode & PNG_HAVE_IHDR))
387 png_error(png_ptr, "Missing IHDR before gAMA");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600388 else if (png_ptr->mode & PNG_HAVE_IDAT)
389 {
390 png_warning(png_ptr, "Invalid gAMA after IDAT");
391 png_crc_finish(png_ptr, length);
392 return;
393 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500394 else if (png_ptr->mode & PNG_HAVE_PLTE)
395 /* Should be an error, but we can cope with it */
396 png_warning(png_ptr, "Out of place gAMA chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600397
398 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_gAMA
399#if defined(PNG_READ_sRGB_SUPPORTED)
400 && !(info_ptr->valid & PNG_INFO_sRGB)
401#endif
402 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600403 {
404 png_warning(png_ptr, "Duplicate gAMA chunk");
405 png_crc_finish(png_ptr, length);
406 return;
407 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500408
Guy Schalnat0d580581995-07-20 02:43:20 -0500409 if (length != 4)
410 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600411 png_warning(png_ptr, "Incorrect gAMA chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600412 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500413 return;
414 }
415
416 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600417 if (png_crc_finish(png_ptr, 0))
418 return;
419
Guy Schalnat0d580581995-07-20 02:43:20 -0500420 igamma = png_get_uint_32(buf);
421 /* check for zero gamma */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500422 if (igamma == 0)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600423 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500424
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600425#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600426 if (info_ptr->valid & PNG_INFO_sRGB)
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500427 if(fabs((float)igamma - 45455.)>500.)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600428 {
429 png_warning(png_ptr,
430 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600431#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600432 fprintf(stderr, "igamma = %lu\n", igamma);
433#endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600434 return;
435 }
436#endif /* PNG_READ_sRGB_SUPPORTED */
437
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600438 file_gamma = (float)igamma / (float)100000.0;
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600439#ifdef PNG_READ_GAMMA_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500440 png_ptr->gamma = file_gamma;
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600441#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500442 png_set_gAMA(png_ptr, info_ptr, file_gamma);
Guy Schalnat0d580581995-07-20 02:43:20 -0500443}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500444#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500445
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500446#if defined(PNG_READ_sBIT_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500447void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600448png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500449{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500450 png_size_t truelen;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600451 png_byte buf[4];
Guy Schalnat69b14481996-01-10 02:56:49 -0600452
Andreas Dilger47a0c421997-05-16 02:46:07 -0500453 png_debug(1, "in png_handle_sBIT\n");
454
Guy Schalnat69b14481996-01-10 02:56:49 -0600455 buf[0] = buf[1] = buf[2] = buf[3] = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500456
Guy Schalnate5a37791996-06-05 15:50:50 -0500457 if (!(png_ptr->mode & PNG_HAVE_IHDR))
458 png_error(png_ptr, "Missing IHDR before sBIT");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600459 else if (png_ptr->mode & PNG_HAVE_IDAT)
460 {
461 png_warning(png_ptr, "Invalid sBIT after IDAT");
462 png_crc_finish(png_ptr, length);
463 return;
464 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500465 else if (png_ptr->mode & PNG_HAVE_PLTE)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600466 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500467 /* Should be an error, but we can cope with it */
468 png_warning(png_ptr, "Out of place sBIT chunk");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600469 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500470 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_sBIT)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600471 {
472 png_warning(png_ptr, "Duplicate sBIT chunk");
473 png_crc_finish(png_ptr, length);
474 return;
475 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500476
Guy Schalnat0d580581995-07-20 02:43:20 -0500477 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600478 truelen = 3;
Guy Schalnat0d580581995-07-20 02:43:20 -0500479 else
Andreas Dilger47a0c421997-05-16 02:46:07 -0500480 truelen = (png_size_t)png_ptr->channels;
Guy Schalnat0d580581995-07-20 02:43:20 -0500481
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600482 if (length != truelen)
Guy Schalnat0d580581995-07-20 02:43:20 -0500483 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600484 png_warning(png_ptr, "Incorrect sBIT chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600485 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600486 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500487 }
488
Andreas Dilger47a0c421997-05-16 02:46:07 -0500489 png_crc_read(png_ptr, buf, truelen);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600490 if (png_crc_finish(png_ptr, 0))
491 return;
492
Guy Schalnat0d580581995-07-20 02:43:20 -0500493 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
494 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600495 png_ptr->sig_bit.red = buf[0];
496 png_ptr->sig_bit.green = buf[1];
497 png_ptr->sig_bit.blue = buf[2];
498 png_ptr->sig_bit.alpha = buf[3];
Guy Schalnat0d580581995-07-20 02:43:20 -0500499 }
500 else
501 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600502 png_ptr->sig_bit.gray = buf[0];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600503 png_ptr->sig_bit.red = buf[0];
504 png_ptr->sig_bit.green = buf[0];
505 png_ptr->sig_bit.blue = buf[0];
Guy Schalnat6d764711995-12-19 03:22:19 -0600506 png_ptr->sig_bit.alpha = buf[1];
Guy Schalnat0d580581995-07-20 02:43:20 -0500507 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500508 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
Guy Schalnat0d580581995-07-20 02:43:20 -0500509}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500510#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500511
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500512#if defined(PNG_READ_cHRM_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500513void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600514png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500515{
516 png_byte buf[4];
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600517 png_uint_32 val;
Guy Schalnat0d580581995-07-20 02:43:20 -0500518 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
519
Andreas Dilger47a0c421997-05-16 02:46:07 -0500520 png_debug(1, "in png_handle_cHRM\n");
521
Guy Schalnate5a37791996-06-05 15:50:50 -0500522 if (!(png_ptr->mode & PNG_HAVE_IHDR))
523 png_error(png_ptr, "Missing IHDR before sBIT");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600524 else if (png_ptr->mode & PNG_HAVE_IDAT)
525 {
526 png_warning(png_ptr, "Invalid cHRM after IDAT");
527 png_crc_finish(png_ptr, length);
528 return;
529 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500530 else if (png_ptr->mode & PNG_HAVE_PLTE)
531 /* Should be an error, but we can cope with it */
532 png_warning(png_ptr, "Missing PLTE before cHRM");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600533
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600534 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_cHRM
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600535#if defined(PNG_READ_sRGB_SUPPORTED)
536 && !(info_ptr->valid & PNG_INFO_sRGB)
537#endif
538 )
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600539 {
540 png_warning(png_ptr, "Duplicate cHRM chunk");
541 png_crc_finish(png_ptr, length);
542 return;
543 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500544
Guy Schalnat0d580581995-07-20 02:43:20 -0500545 if (length != 32)
546 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600547 png_warning(png_ptr, "Incorrect cHRM chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600548 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600549 return;
Guy Schalnat0d580581995-07-20 02:43:20 -0500550 }
551
552 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600553 val = png_get_uint_32(buf);
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600554 white_x = (float)val / (float)100000.0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500555
556 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600557 val = png_get_uint_32(buf);
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600558 white_y = (float)val / (float)100000.0;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600559
560 if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
561 white_x + white_y > 1.0)
562 {
563 png_warning(png_ptr, "Invalid cHRM white point");
564 png_crc_finish(png_ptr, 24);
565 return;
566 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500567
568 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600569 val = png_get_uint_32(buf);
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600570 red_x = (float)val / (float)100000.0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500571
572 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600573 val = png_get_uint_32(buf);
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600574 red_y = (float)val / (float)100000.0;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600575
576 if (red_x < 0 || red_x > 0.8 || red_y < 0 || red_y > 0.8 ||
577 red_x + red_y > 1.0)
578 {
579 png_warning(png_ptr, "Invalid cHRM red point");
580 png_crc_finish(png_ptr, 16);
581 return;
582 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500583
584 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600585 val = png_get_uint_32(buf);
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600586 green_x = (float)val / (float)100000.0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500587
588 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600589 val = png_get_uint_32(buf);
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600590 green_y = (float)val / (float)100000.0;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600591
592 if (green_x < 0 || green_x > 0.8 || green_y < 0 || green_y > 0.8 ||
593 green_x + green_y > 1.0)
594 {
595 png_warning(png_ptr, "Invalid cHRM green point");
596 png_crc_finish(png_ptr, 8);
597 return;
598 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500599
600 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600601 val = png_get_uint_32(buf);
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600602 blue_x = (float)val / (float)100000.0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500603
604 png_crc_read(png_ptr, buf, 4);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600605 val = png_get_uint_32(buf);
Glenn Randers-Pehrson397100e1998-03-07 19:45:37 -0600606 blue_y = (float)val / (float)100000.0;
Guy Schalnat0d580581995-07-20 02:43:20 -0500607
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600608 if (blue_x < (float)0 || blue_x > (float)0.8 || blue_y < (float)0 ||
609 blue_y > (float)0.8 || blue_x + blue_y > (float)1.0)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600610 {
611 png_warning(png_ptr, "Invalid cHRM blue point");
612 png_crc_finish(png_ptr, 0);
613 return;
614 }
615
616 if (png_crc_finish(png_ptr, 0))
617 return;
618
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600619#if defined(PNG_READ_sRGB_SUPPORTED)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600620 if (info_ptr->valid & PNG_INFO_sRGB)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600621 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600622 if (fabs(white_x - (float).3127) > (float).001 ||
623 fabs(white_y - (float).3290) > (float).001 ||
624 fabs( red_x - (float).6400) > (float).001 ||
625 fabs( red_y - (float).3300) > (float).001 ||
626 fabs(green_x - (float).3000) > (float).001 ||
627 fabs(green_y - (float).6000) > (float).001 ||
628 fabs( blue_x - (float).1500) > (float).001 ||
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600629 fabs( blue_y - (float).0600) > (float).001)
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600630 {
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600631
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600632 png_warning(png_ptr,
633 "Ignoring incorrect cHRM value when sRGB is also present");
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600634#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600635 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
636 white_x, white_y, red_x, red_y);
637 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
638 green_x, green_y, blue_x, blue_y);
639#endif
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -0600640 }
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600641 return;
642 }
643#endif /* PNG_READ_sRGB_SUPPORTED */
644
Andreas Dilger47a0c421997-05-16 02:46:07 -0500645 png_set_cHRM(png_ptr, info_ptr,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600646 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
Guy Schalnat0d580581995-07-20 02:43:20 -0500647}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500648#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500649
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600650#if defined(PNG_READ_sRGB_SUPPORTED)
651void
652png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
653{
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600654 int intent;
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600655 png_byte buf[1];
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600656
657 png_debug(1, "in png_handle_sRGB\n");
658
659 if (!(png_ptr->mode & PNG_HAVE_IHDR))
660 png_error(png_ptr, "Missing IHDR before sRGB");
661 else if (png_ptr->mode & PNG_HAVE_IDAT)
662 {
663 png_warning(png_ptr, "Invalid sRGB after IDAT");
664 png_crc_finish(png_ptr, length);
665 return;
666 }
667 else if (png_ptr->mode & PNG_HAVE_PLTE)
668 /* Should be an error, but we can cope with it */
669 png_warning(png_ptr, "Out of place sRGB chunk");
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600670
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600671 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_sRGB)
672 {
673 png_warning(png_ptr, "Duplicate sRGB chunk");
674 png_crc_finish(png_ptr, length);
675 return;
676 }
677
678 if (length != 1)
679 {
680 png_warning(png_ptr, "Incorrect sRGB chunk length");
681 png_crc_finish(png_ptr, length);
682 return;
683 }
684
685 png_crc_read(png_ptr, buf, 1);
686 if (png_crc_finish(png_ptr, 0))
687 return;
688
689 intent = buf[0];
690 /* check for bad intent */
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600691 if (intent >= PNG_sRGB_INTENT_LAST)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600692 {
693 png_warning(png_ptr, "Unknown sRGB intent");
694 return;
695 }
696
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -0600697#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600698 if ((info_ptr->valid & PNG_INFO_gAMA))
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500699 if(fabs((png_ptr->gamma*(float)100000.+.5)-45455.) > 500.)
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600700 {
701 png_warning(png_ptr,
702 "Ignoring incorrect gAMA value when sRGB is also present");
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600703#ifndef PNG_NO_CONSOLE_IO
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600704 fprintf(stderr,"gamma=%f\n",png_ptr->gamma);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600705#endif
Glenn Randers-Pehrson2687fcc1998-01-07 20:54:20 -0600706 }
707#endif /* PNG_READ_gAMA_SUPPORTED */
708
709#ifdef PNG_READ_cHRM_SUPPORTED
710 if (info_ptr->valid & PNG_INFO_cHRM)
711 if (fabs(info_ptr->x_white - (float).3127) > (float).001 ||
712 fabs(info_ptr->y_white - (float).3290) > (float).001 ||
713 fabs( info_ptr->x_red - (float).6400) > (float).001 ||
714 fabs( info_ptr->y_red - (float).3300) > (float).001 ||
715 fabs(info_ptr->x_green - (float).3000) > (float).001 ||
716 fabs(info_ptr->y_green - (float).6000) > (float).001 ||
717 fabs( info_ptr->x_blue - (float).1500) > (float).001 ||
718 fabs( info_ptr->y_blue - (float).0600) > (float).001)
719 {
720 png_warning(png_ptr,
721 "Ignoring incorrect cHRM value when sRGB is also present");
722 }
723#endif /* PNG_READ_cHRM_SUPPORTED */
724
725 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
726}
727#endif /* PNG_READ_sRGB_SUPPORTED */
728
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500729#if defined(PNG_READ_tRNS_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500730void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600731png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500732{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500733 png_debug(1, "in png_handle_tRNS\n");
734
Guy Schalnate5a37791996-06-05 15:50:50 -0500735 if (!(png_ptr->mode & PNG_HAVE_IHDR))
736 png_error(png_ptr, "Missing IHDR before tRNS");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600737 else if (png_ptr->mode & PNG_HAVE_IDAT)
738 {
739 png_warning(png_ptr, "Invalid tRNS after IDAT");
740 png_crc_finish(png_ptr, length);
741 return;
742 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500743 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tRNS)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600744 {
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600745 png_warning(png_ptr, "Duplicate tRNS chunk");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600746 png_crc_finish(png_ptr, length);
747 return;
748 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500749
Guy Schalnat0d580581995-07-20 02:43:20 -0500750 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
751 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500752 if (!(png_ptr->mode & PNG_HAVE_PLTE))
753 {
754 /* Should be an error, but we can cope with it */
755 png_warning(png_ptr, "Missing PLTE before tRNS");
756 }
757 else if (length > png_ptr->num_palette)
Guy Schalnat0d580581995-07-20 02:43:20 -0500758 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600759 png_warning(png_ptr, "Incorrect tRNS chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600760 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500761 return;
762 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500763 if (length == 0)
764 {
765 png_warning(png_ptr, "Zero length tRNS chunk");
766 png_crc_finish(png_ptr, length);
767 return;
768 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500769
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600770 png_ptr->trans = (png_bytep)png_malloc(png_ptr, length);
771 png_ptr->flags |= PNG_FLAG_FREE_TRANS;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500772 png_crc_read(png_ptr, png_ptr->trans, (png_size_t)length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600773 png_ptr->num_trans = (png_uint_16)length;
Guy Schalnat0d580581995-07-20 02:43:20 -0500774 }
775 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
776 {
777 png_byte buf[6];
778
779 if (length != 6)
780 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600781 png_warning(png_ptr, "Incorrect tRNS chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600782 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500783 return;
784 }
785
Andreas Dilger47a0c421997-05-16 02:46:07 -0500786 png_crc_read(png_ptr, buf, (png_size_t)length);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600787 png_ptr->num_trans = 1;
Guy Schalnat0d580581995-07-20 02:43:20 -0500788 png_ptr->trans_values.red = png_get_uint_16(buf);
789 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
790 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
791 }
792 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
793 {
794 png_byte buf[6];
795
796 if (length != 2)
797 {
Guy Schalnat69b14481996-01-10 02:56:49 -0600798 png_warning(png_ptr, "Incorrect tRNS chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600799 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600800 return;
801 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500802
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600803 png_crc_read(png_ptr, buf, 2);
804 png_ptr->num_trans = 1;
805 png_ptr->trans_values.gray = png_get_uint_16(buf);
806 }
807 else
Guy Schalnate5a37791996-06-05 15:50:50 -0500808 {
809 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600810 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500811 return;
812 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500813
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600814 if (png_crc_finish(png_ptr, 0))
815 return;
816
Andreas Dilger47a0c421997-05-16 02:46:07 -0500817 png_set_tRNS(png_ptr, info_ptr, png_ptr->trans, png_ptr->num_trans,
Guy Schalnat0d580581995-07-20 02:43:20 -0500818 &(png_ptr->trans_values));
819}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500820#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500821
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500822#if defined(PNG_READ_bKGD_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500823void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600824png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500825{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500826 png_size_t truelen;
Guy Schalnat0d580581995-07-20 02:43:20 -0500827 png_byte buf[6];
828
Andreas Dilger47a0c421997-05-16 02:46:07 -0500829 png_debug(1, "in png_handle_bKGD\n");
830
Guy Schalnate5a37791996-06-05 15:50:50 -0500831 if (!(png_ptr->mode & PNG_HAVE_IHDR))
832 png_error(png_ptr, "Missing IHDR before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600833 else if (png_ptr->mode & PNG_HAVE_IDAT)
834 {
835 png_warning(png_ptr, "Invalid bKGD after IDAT");
836 png_crc_finish(png_ptr, length);
837 return;
838 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500839 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
840 !(png_ptr->mode & PNG_HAVE_PLTE))
841 {
842 png_warning(png_ptr, "Missing PLTE before bKGD");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600843 png_crc_finish(png_ptr, length);
844 return;
845 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500846 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_bKGD)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600847 {
848 png_warning(png_ptr, "Duplicate bKGD chunk");
849 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500850 return;
851 }
852
Guy Schalnat0d580581995-07-20 02:43:20 -0500853 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
854 truelen = 1;
855 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
856 truelen = 6;
857 else
858 truelen = 2;
859
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600860 if (length != truelen)
Guy Schalnat0d580581995-07-20 02:43:20 -0500861 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600862 png_warning(png_ptr, "Incorrect bKGD chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600863 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500864 return;
865 }
866
Andreas Dilger47a0c421997-05-16 02:46:07 -0500867 png_crc_read(png_ptr, buf, truelen);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600868 if (png_crc_finish(png_ptr, 0))
869 return;
870
Guy Schalnate5a37791996-06-05 15:50:50 -0500871 /* We convert the index value into RGB components so that we can allow
872 * arbitrary RGB values for background when we have transparency, and
873 * so it is easy to determine the RGB values of the background color
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600874 * from the info_ptr struct. */
Guy Schalnat0d580581995-07-20 02:43:20 -0500875 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
Guy Schalnate5a37791996-06-05 15:50:50 -0500876 {
Guy Schalnat0d580581995-07-20 02:43:20 -0500877 png_ptr->background.index = buf[0];
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500878 if(info_ptr->num_palette)
879 {
880 if(buf[0] > info_ptr->num_palette)
881 {
882 png_warning(png_ptr, "Incorrect bKGD chunk index value");
883 png_crc_finish(png_ptr, length);
884 return;
885 }
886 png_ptr->background.red =
887 (png_uint_16)png_ptr->palette[buf[0]].red;
888 png_ptr->background.green =
889 (png_uint_16)png_ptr->palette[buf[0]].green;
890 png_ptr->background.blue =
891 (png_uint_16)png_ptr->palette[buf[0]].blue;
892 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500893 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500894 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
Guy Schalnate5a37791996-06-05 15:50:50 -0500895 {
896 png_ptr->background.red =
897 png_ptr->background.green =
898 png_ptr->background.blue =
Guy Schalnat0d580581995-07-20 02:43:20 -0500899 png_ptr->background.gray = png_get_uint_16(buf);
Guy Schalnate5a37791996-06-05 15:50:50 -0500900 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500901 else
902 {
903 png_ptr->background.red = png_get_uint_16(buf);
904 png_ptr->background.green = png_get_uint_16(buf + 2);
905 png_ptr->background.blue = png_get_uint_16(buf + 4);
906 }
907
Andreas Dilger47a0c421997-05-16 02:46:07 -0500908 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
Guy Schalnat0d580581995-07-20 02:43:20 -0500909}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500910#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500911
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500912#if defined(PNG_READ_hIST_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500913void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600914png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500915{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600916 int num, i;
Guy Schalnat0d580581995-07-20 02:43:20 -0500917
Andreas Dilger47a0c421997-05-16 02:46:07 -0500918 png_debug(1, "in png_handle_hIST\n");
919
Guy Schalnate5a37791996-06-05 15:50:50 -0500920 if (!(png_ptr->mode & PNG_HAVE_IHDR))
921 png_error(png_ptr, "Missing IHDR before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600922 else if (png_ptr->mode & PNG_HAVE_IDAT)
923 {
924 png_warning(png_ptr, "Invalid hIST after IDAT");
925 png_crc_finish(png_ptr, length);
926 return;
927 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500928 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
929 {
930 png_warning(png_ptr, "Missing PLTE before hIST");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600931 png_crc_finish(png_ptr, length);
932 return;
933 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500934 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_hIST)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600935 {
936 png_warning(png_ptr, "Duplicate hIST chunk");
937 png_crc_finish(png_ptr, length);
Guy Schalnate5a37791996-06-05 15:50:50 -0500938 return;
939 }
940
Andreas Dilger47a0c421997-05-16 02:46:07 -0500941 if (length != (png_uint_32)(2 * png_ptr->num_palette))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600942 {
943 png_warning(png_ptr, "Incorrect hIST chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600944 png_crc_finish(png_ptr, length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600945 return;
946 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500947
948 num = (int)length / 2;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600949 png_ptr->hist = (png_uint_16p)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600950 (png_uint_32)(num * sizeof (png_uint_16)));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600951 png_ptr->flags |= PNG_FLAG_FREE_HIST;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600952 for (i = 0; i < num; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500953 {
954 png_byte buf[2];
955
956 png_crc_read(png_ptr, buf, 2);
957 png_ptr->hist[i] = png_get_uint_16(buf);
958 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600959
960 if (png_crc_finish(png_ptr, 0))
961 return;
962
Andreas Dilger47a0c421997-05-16 02:46:07 -0500963 png_set_hIST(png_ptr, info_ptr, png_ptr->hist);
Guy Schalnat0d580581995-07-20 02:43:20 -0500964}
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500965#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500966
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500967#if defined(PNG_READ_pHYs_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500968void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600969png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -0500970{
971 png_byte buf[9];
972 png_uint_32 res_x, res_y;
973 int unit_type;
974
Andreas Dilger47a0c421997-05-16 02:46:07 -0500975 png_debug(1, "in png_handle_pHYs\n");
976
Guy Schalnate5a37791996-06-05 15:50:50 -0500977 if (!(png_ptr->mode & PNG_HAVE_IHDR))
978 png_error(png_ptr, "Missing IHDR before pHYS");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600979 else if (png_ptr->mode & PNG_HAVE_IDAT)
980 {
981 png_warning(png_ptr, "Invalid pHYS after IDAT");
982 png_crc_finish(png_ptr, length);
983 return;
984 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500985 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_pHYs)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600986 {
987 png_warning(png_ptr, "Duplicate pHYS chunk");
988 png_crc_finish(png_ptr, length);
989 return;
990 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500991
Guy Schalnat0d580581995-07-20 02:43:20 -0500992 if (length != 9)
993 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600994 png_warning(png_ptr, "Incorrect pHYs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600995 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500996 return;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600997 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500998
999 png_crc_read(png_ptr, buf, 9);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001000 if (png_crc_finish(png_ptr, 0))
1001 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001002
1003 res_x = png_get_uint_32(buf);
1004 res_y = png_get_uint_32(buf + 4);
1005 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001006 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
Guy Schalnat0d580581995-07-20 02:43:20 -05001007}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001008#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001009
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001010#if defined(PNG_READ_oFFs_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001011void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001012png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001013{
1014 png_byte buf[9];
1015 png_uint_32 offset_x, offset_y;
1016 int unit_type;
1017
Andreas Dilger47a0c421997-05-16 02:46:07 -05001018 png_debug(1, "in png_handle_oFFs\n");
1019
Guy Schalnate5a37791996-06-05 15:50:50 -05001020 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1021 png_error(png_ptr, "Missing IHDR before oFFs");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001022 else if (png_ptr->mode & PNG_HAVE_IDAT)
1023 {
1024 png_warning(png_ptr, "Invalid oFFs after IDAT");
1025 png_crc_finish(png_ptr, length);
1026 return;
1027 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001028 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_oFFs)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001029 {
1030 png_warning(png_ptr, "Duplicate oFFs chunk");
1031 png_crc_finish(png_ptr, length);
1032 return;
1033 }
Guy Schalnate5a37791996-06-05 15:50:50 -05001034
Guy Schalnat0d580581995-07-20 02:43:20 -05001035 if (length != 9)
1036 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001037 png_warning(png_ptr, "Incorrect oFFs chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001038 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001039 return;
1040 }
1041
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001042 png_crc_read(png_ptr, buf, 9);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001043 if (png_crc_finish(png_ptr, 0))
1044 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001045
1046 offset_x = png_get_uint_32(buf);
1047 offset_y = png_get_uint_32(buf + 4);
1048 unit_type = buf[8];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001049 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1050}
1051#endif
1052
1053#if defined(PNG_READ_pCAL_SUPPORTED)
1054/* read the pCAL chunk (png-scivis-19970203) */
1055void
1056png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1057{
1058 png_charp purpose;
1059 png_int_32 X0, X1;
1060 png_byte type, nparams;
1061 png_charp buf, units, endptr;
1062 png_charpp params;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001063 png_size_t slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001064 int i;
1065
1066 png_debug(1, "in png_handle_pCAL\n");
1067
1068 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1069 png_error(png_ptr, "Missing IHDR before pCAL");
1070 else if (png_ptr->mode & PNG_HAVE_IDAT)
1071 {
1072 png_warning(png_ptr, "Invalid pCAL after IDAT");
1073 png_crc_finish(png_ptr, length);
1074 return;
1075 }
1076 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_pCAL)
1077 {
1078 png_warning(png_ptr, "Duplicate pCAL chunk");
1079 png_crc_finish(png_ptr, length);
1080 return;
1081 }
1082
1083 png_debug1(2, "Allocating and reading pCAL chunk data (%d bytes)\n",
1084 length + 1);
1085 purpose = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001086 slength = (png_size_t)length;
1087 png_crc_read(png_ptr, (png_bytep)purpose, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001088
1089 if (png_crc_finish(png_ptr, 0))
1090 {
1091 png_free(png_ptr, purpose);
1092 return;
1093 }
1094
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001095 purpose[slength] = 0x00; /* null terminate the last string */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001096
1097 png_debug(3, "Finding end of pCAL purpose string\n");
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001098 for (buf = purpose; *buf; buf++)
Glenn Randers-Pehrsond12aa501998-03-13 07:39:39 -06001099 /* empty loop */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001100
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001101 endptr = purpose + slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001102
1103 /* We need to have at least 12 bytes after the purpose string
1104 in order to get the parameter information. */
1105 if (endptr <= buf + 12)
1106 {
1107 png_warning(png_ptr, "Invalid pCAL data");
1108 png_free(png_ptr, purpose);
1109 return;
1110 }
1111
1112 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1113 X0 = png_get_int_32((png_bytep)buf+1);
1114 X1 = png_get_int_32((png_bytep)buf+5);
1115 type = buf[9];
1116 nparams = buf[10];
1117 units = buf + 11;
1118
1119 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1120 /* Check that we have the right number of parameters for known
1121 equation types. */
1122 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1123 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1124 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1125 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1126 {
1127 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1128 png_free(png_ptr, purpose);
1129 return;
1130 }
1131 else if (type >= PNG_EQUATION_LAST)
1132 {
1133 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1134 }
1135
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001136 for (buf = units; *buf; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001137 /* Empty loop to move past the units string. */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001138
1139 png_debug(3, "Allocating pCAL parameters array\n");
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001140 params = (png_charpp)png_malloc(png_ptr, (png_uint_32)(nparams
1141 *sizeof(png_charp))) ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001142
1143 /* Get pointers to the start of each parameter string. */
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001144 for (i = 0; i < (int)nparams; i++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001145 {
1146 buf++; /* Skip the null string terminator from previous parameter. */
1147
1148 png_debug1(3, "Reading pCAL parameter %d\n", i);
Glenn Randers-Pehrsond12aa501998-03-13 07:39:39 -06001149 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -06001150 /* Empty loop to move past each parameter string */ ;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001151
1152 /* Make sure we haven't run out of data yet */
1153 if (buf > endptr)
1154 {
1155 png_warning(png_ptr, "Invalid pCAL data");
1156 png_free(png_ptr, purpose);
1157 png_free(png_ptr, params);
1158 return;
1159 }
1160 }
1161
1162 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1163 units, params);
1164
1165 png_free(png_ptr, purpose);
1166 png_free(png_ptr, params);
Guy Schalnat0d580581995-07-20 02:43:20 -05001167}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001168#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001169
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001170#if defined(PNG_READ_tIME_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001171void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001172png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001173{
1174 png_byte buf[7];
1175 png_time mod_time;
1176
Andreas Dilger47a0c421997-05-16 02:46:07 -05001177 png_debug(1, "in png_handle_tIME\n");
1178
Guy Schalnate5a37791996-06-05 15:50:50 -05001179 if (!(png_ptr->mode & PNG_HAVE_IHDR))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001180 png_error(png_ptr, "Out of place tIME chunk");
Andreas Dilger47a0c421997-05-16 02:46:07 -05001181 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tIME)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001182 {
1183 png_warning(png_ptr, "Duplicate tIME chunk");
1184 png_crc_finish(png_ptr, length);
1185 return;
1186 }
1187
1188 if (png_ptr->mode & PNG_HAVE_IDAT)
1189 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnate5a37791996-06-05 15:50:50 -05001190
Guy Schalnat0d580581995-07-20 02:43:20 -05001191 if (length != 7)
1192 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001193 png_warning(png_ptr, "Incorrect tIME chunk length");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001194 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -05001195 return;
1196 }
1197
1198 png_crc_read(png_ptr, buf, 7);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001199 if (png_crc_finish(png_ptr, 0))
1200 return;
Guy Schalnat0d580581995-07-20 02:43:20 -05001201
1202 mod_time.second = buf[6];
1203 mod_time.minute = buf[5];
1204 mod_time.hour = buf[4];
1205 mod_time.day = buf[3];
1206 mod_time.month = buf[2];
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001207 mod_time.year = png_get_uint_16(buf);
Guy Schalnat0d580581995-07-20 02:43:20 -05001208
Andreas Dilger47a0c421997-05-16 02:46:07 -05001209 png_set_tIME(png_ptr, info_ptr, &mod_time);
Guy Schalnat0d580581995-07-20 02:43:20 -05001210}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001211#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001212
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001213#if defined(PNG_READ_tEXt_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001214/* Note: this does not properly handle chunks that are > 64K under DOS */
Guy Schalnat0d580581995-07-20 02:43:20 -05001215void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001216png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001217{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001218 png_textp text_ptr;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001219 png_charp key;
Guy Schalnat6d764711995-12-19 03:22:19 -06001220 png_charp text;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001221 png_uint_32 skip = 0;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001222 png_size_t slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001223
1224 png_debug(1, "in png_handle_tEXt\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05001225
Guy Schalnate5a37791996-06-05 15:50:50 -05001226 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1227 png_error(png_ptr, "Missing IHDR before tEXt");
1228
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001229 if (png_ptr->mode & PNG_HAVE_IDAT)
1230 png_ptr->mode |= PNG_AFTER_IDAT;
1231
Andreas Dilger47a0c421997-05-16 02:46:07 -05001232#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001233 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001234 {
1235 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001236 skip = length - (png_uint_32)65535L;
1237 length = (png_uint_32)65535L;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001238 }
1239#endif
1240
1241 key = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001242 slength = (png_size_t)length;
1243 png_crc_read(png_ptr, (png_bytep)key, slength);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001244
1245 if (png_crc_finish(png_ptr, skip))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001246 {
1247 png_free(png_ptr, key);
1248 return;
1249 }
1250
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001251 key[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05001252
1253 for (text = key; *text; text++)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001254 /* empty loop to find end of key */ ;
Guy Schalnat0d580581995-07-20 02:43:20 -05001255
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001256 if (text != key + slength)
Guy Schalnat0d580581995-07-20 02:43:20 -05001257 text++;
1258
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001259 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
Andreas Dilger47a0c421997-05-16 02:46:07 -05001260 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1261 text_ptr->key = key;
1262 text_ptr->text = text;
1263
1264 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1265
1266 png_free(png_ptr, text_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -05001267}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001268#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001269
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001270#if defined(PNG_READ_zTXt_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001271/* note: this does not correctly handle chunks that are > 64K under DOS */
Guy Schalnat0d580581995-07-20 02:43:20 -05001272void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001273png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat0d580581995-07-20 02:43:20 -05001274{
Guy Schalnate5a37791996-06-05 15:50:50 -05001275 static char msg[] = "Error decoding zTXt chunk";
Andreas Dilger47a0c421997-05-16 02:46:07 -05001276 png_textp text_ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -06001277 png_charp key;
1278 png_charp text;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001279 int comp_type = PNG_TEXT_COMPRESSION_NONE;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001280 png_size_t slength;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001281
1282 png_debug(1, "in png_handle_zTXt\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05001283
Guy Schalnate5a37791996-06-05 15:50:50 -05001284 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1285 png_error(png_ptr, "Missing IHDR before zTXt");
1286
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001287 if (png_ptr->mode & PNG_HAVE_IDAT)
1288 png_ptr->mode |= PNG_AFTER_IDAT;
1289
Andreas Dilger47a0c421997-05-16 02:46:07 -05001290#ifdef PNG_MAX_MALLOC_64K
1291 /* We will no doubt have problems with chunks even half this size, but
1292 there is no hard and fast rule to tell us where to stop. */
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06001293 if (length > (png_uint_32)65535L)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001294 {
1295 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1296 png_crc_finish(png_ptr, length);
1297 return;
1298 }
1299#endif
1300
1301 key = (png_charp)png_malloc(png_ptr, length + 1);
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001302 slength = (png_size_t)length;
1303 png_crc_read(png_ptr, (png_bytep)key, slength);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001304 if (png_crc_finish(png_ptr, 0))
1305 {
1306 png_free(png_ptr, key);
1307 return;
1308 }
1309
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001310 key[slength] = 0x00;
Guy Schalnat0d580581995-07-20 02:43:20 -05001311
1312 for (text = key; *text; text++)
1313 /* empty loop */ ;
1314
Andreas Dilger47a0c421997-05-16 02:46:07 -05001315 /* zTXt must have some text after the keyword */
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001316 if (text == key + slength)
Guy Schalnat0d580581995-07-20 02:43:20 -05001317 {
Guy Schalnat69b14481996-01-10 02:56:49 -06001318 png_warning(png_ptr, "Zero length zTXt chunk");
Guy Schalnat0d580581995-07-20 02:43:20 -05001319 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001320 else if ((comp_type = *(++text)) == PNG_TEXT_COMPRESSION_zTXt)
Guy Schalnat0d580581995-07-20 02:43:20 -05001321 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001322 png_size_t text_size, key_size;
Guy Schalnate5a37791996-06-05 15:50:50 -05001323 text++;
Guy Schalnat0d580581995-07-20 02:43:20 -05001324
Andreas Dilger47a0c421997-05-16 02:46:07 -05001325 png_ptr->zstream.next_in = (png_bytep)text;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001326 png_ptr->zstream.avail_in = (uInt)(length - (text - key));
1327 png_ptr->zstream.next_out = png_ptr->zbuf;
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001328 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
Guy Schalnate5a37791996-06-05 15:50:50 -05001329
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001330 key_size = (png_size_t)(text - key);
Guy Schalnate5a37791996-06-05 15:50:50 -05001331 text_size = 0;
1332 text = NULL;
1333
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001334 while (png_ptr->zstream.avail_in)
Guy Schalnate5a37791996-06-05 15:50:50 -05001335 {
1336 int ret;
1337
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001338 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnate5a37791996-06-05 15:50:50 -05001339 if (ret != Z_OK && ret != Z_STREAM_END)
Guy Schalnat0d580581995-07-20 02:43:20 -05001340 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001341 if (png_ptr->zstream.msg != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001342 png_warning(png_ptr, png_ptr->zstream.msg);
Guy Schalnate5a37791996-06-05 15:50:50 -05001343 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001344 png_warning(png_ptr, msg);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001345 inflateReset(&png_ptr->zstream);
1346 png_ptr->zstream.avail_in = 0;
Guy Schalnate5a37791996-06-05 15:50:50 -05001347
Andreas Dilger47a0c421997-05-16 02:46:07 -05001348 if (text == NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -05001349 {
1350 text_size = key_size + sizeof(msg) + 1;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001351 text = (png_charp)png_malloc(png_ptr, (png_uint_32)text_size);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001352 png_memcpy(text, key, key_size);
Guy Schalnate5a37791996-06-05 15:50:50 -05001353 }
1354
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001355 text[text_size - 1] = 0x00;
Guy Schalnate5a37791996-06-05 15:50:50 -05001356
1357 /* Copy what we can of the error message into the text chunk */
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001358 text_size = (png_size_t)(slength - (text - key) - 1);
Guy Schalnate5a37791996-06-05 15:50:50 -05001359 text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001360 png_memcpy(text + key_size, msg, text_size + 1);
Guy Schalnate5a37791996-06-05 15:50:50 -05001361 break;
1362 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001363 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
Guy Schalnate5a37791996-06-05 15:50:50 -05001364 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001365 if (text == NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -05001366 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001367 text = (png_charp)png_malloc(png_ptr,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001368 (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out
1369 + key_size + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -05001370 png_memcpy(text + key_size, png_ptr->zbuf,
1371 png_ptr->zbuf_size - png_ptr->zstream.avail_out);
1372 png_memcpy(text, key, key_size);
1373 text_size = key_size + png_ptr->zbuf_size -
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001374 png_ptr->zstream.avail_out;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001375 *(text + text_size) = 0x00;
Guy Schalnate5a37791996-06-05 15:50:50 -05001376 }
1377 else
1378 {
1379 png_charp tmp;
1380
1381 tmp = text;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001382 text = (png_charp)png_malloc(png_ptr, (png_uint_32)(text_size +
1383 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
Andreas Dilger47a0c421997-05-16 02:46:07 -05001384 png_memcpy(text, tmp, text_size);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001385 png_free(png_ptr, tmp);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001386 png_memcpy(text + text_size, png_ptr->zbuf,
1387 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001388 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001389 *(text + text_size) = 0x00;
Guy Schalnate5a37791996-06-05 15:50:50 -05001390 }
1391 if (ret != Z_STREAM_END)
1392 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001393 png_ptr->zstream.next_out = png_ptr->zbuf;
1394 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
Guy Schalnate5a37791996-06-05 15:50:50 -05001395 }
1396 else
1397 {
1398 break;
1399 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001400 }
1401 }
Guy Schalnat0d580581995-07-20 02:43:20 -05001402
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001403 inflateReset(&png_ptr->zstream);
1404 png_ptr->zstream.avail_in = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05001405
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001406 png_free(png_ptr, key);
Guy Schalnate5a37791996-06-05 15:50:50 -05001407 key = text;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001408 text += key_size;
Guy Schalnat0d580581995-07-20 02:43:20 -05001409 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001410 else /* if (comp_type >= PNG_TEXT_COMPRESSION_LAST) */
1411 {
1412 png_size_t text_size;
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001413#if !defined(PNG_NO_STDIO)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001414 char umsg[50];
Guy Schalnat0d580581995-07-20 02:43:20 -05001415
Andreas Dilger47a0c421997-05-16 02:46:07 -05001416 sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
1417 png_warning(png_ptr, umsg);
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001418#else
1419 png_warning(png_ptr, "Unknown zTXt compression type");
1420#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -05001421
1422 /* Copy what we can of the error message into the text chunk */
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001423 text_size = (png_size_t)(slength - (text - key) - 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001424 text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
1425 png_memcpy(text, msg, text_size + 1);
1426 }
1427
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06001428 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
Andreas Dilger47a0c421997-05-16 02:46:07 -05001429 text_ptr->compression = comp_type;
1430 text_ptr->key = key;
1431 text_ptr->text = text;
1432
1433 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1434
1435 png_free(png_ptr, text_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -05001436}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001437#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001438
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001439/* This function is called when we haven't found a handler for a
1440 chunk. If there isn't a problem with the chunk itself (ie bad
Andreas Dilger47a0c421997-05-16 02:46:07 -05001441 chunk name, CRC, or a critical chunk), the chunk is silently ignored. */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001442void
1443png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1444{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001445 png_debug(1, "in png_handle_unknown\n");
1446
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001447 /* In the future we can have code here that calls user-supplied
1448 * callback functions for unknown chunks before they are ignored or
1449 * cause an error.
1450 */
1451 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
1452
1453 if (!(png_ptr->chunk_name[0] & 0x20))
1454 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001455 png_chunk_error(png_ptr, "unknown critical chunk");
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001456
Glenn Randers-Pehrsoncbe52d81998-02-28 07:00:24 -06001457 /* to quiet compiler warnings about unused info_ptr */
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001458 if (info_ptr == NULL)
1459 return;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001460 }
1461
1462 if (png_ptr->mode & PNG_HAVE_IDAT)
1463 png_ptr->mode |= PNG_AFTER_IDAT;
1464
1465 png_crc_finish(png_ptr, length);
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06001466
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001467}
1468
1469/* This function is called to verify that a chunk name is valid.
1470 This function can't have the "critical chunk check" incorporated
Andreas Dilger47a0c421997-05-16 02:46:07 -05001471 into it, since in the future we will need to be able to call user
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001472 functions to handle unknown critical chunks after we check that
1473 the chunk name itself is valid. */
Andreas Dilger47a0c421997-05-16 02:46:07 -05001474
1475#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
1476
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001477void
1478png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
1479{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001480 png_debug(1, "in png_check_chunk_name\n");
1481 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
1482 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001483 {
Glenn Randers-Pehrson70e3f541998-01-03 22:40:55 -06001484 png_chunk_error(png_ptr, "invalid chunk type");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001485 }
1486}
1487
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05001488/* Combines the row recently read in with the existing pixels in the
1489 row. This routine takes care of alpha and transparency if requested.
Guy Schalnat0d580581995-07-20 02:43:20 -05001490 This routine also handles the two methods of progressive display
1491 of interlaced images, depending on the mask value.
1492 The mask value describes which pixels are to be combined with
1493 the row. The pattern always repeats every 8 pixels, so just 8
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05001494 bits are needed. A one indicates the pixel is to be combined,
Guy Schalnat0d580581995-07-20 02:43:20 -05001495 a zero indicates the pixel is to be skipped. This is in addition
1496 to any alpha or transparency value associated with the pixel. If
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001497 you want all pixels to be combined, pass 0xff (255) in mask. */
Guy Schalnat0d580581995-07-20 02:43:20 -05001498void
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001499#ifdef PNG_HAVE_ASSEMBLER_COMBINE_ROW
1500png_combine_row_c
1501#else
1502png_combine_row
1503#endif /* PNG_HAVE_ASSEMBLER_COMBINE_ROW */
1504 (png_structp png_ptr, png_bytep row, int mask)
Guy Schalnat0d580581995-07-20 02:43:20 -05001505{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001506 png_debug(1,"in png_combine_row\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05001507 if (mask == 0xff)
1508 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001509 png_memcpy(row, png_ptr->row_buf + 1,
Guy Schalnat0d580581995-07-20 02:43:20 -05001510 (png_size_t)((png_ptr->width *
1511 png_ptr->row_info.pixel_depth + 7) >> 3));
1512 }
1513 else
1514 {
1515 switch (png_ptr->row_info.pixel_depth)
1516 {
1517 case 1:
1518 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001519 png_bytep sp = png_ptr->row_buf + 1;
1520 png_bytep dp = row;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001521 int s_inc, s_start, s_end;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001522 int m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05001523 int shift;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001524 png_uint_32 i;
1525 png_uint_32 row_width = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001526
Andreas Dilger47a0c421997-05-16 02:46:07 -05001527#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1528 if (png_ptr->transformations & PNG_PACKSWAP)
1529 {
1530 s_start = 0;
1531 s_end = 7;
1532 s_inc = 1;
1533 }
1534 else
1535#endif
1536 {
1537 s_start = 7;
1538 s_end = 0;
1539 s_inc = -1;
1540 }
1541
1542 shift = s_start;
1543
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001544 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001545 {
1546 if (m & mask)
1547 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001548 int value;
1549
Guy Schalnat0d580581995-07-20 02:43:20 -05001550 value = (*sp >> shift) & 0x1;
1551 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001552 *dp |= (png_byte)(value << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05001553 }
1554
Andreas Dilger47a0c421997-05-16 02:46:07 -05001555 if (shift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05001556 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001557 shift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05001558 sp++;
1559 dp++;
1560 }
1561 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001562 shift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05001563
1564 if (m == 1)
1565 m = 0x80;
1566 else
1567 m >>= 1;
1568 }
1569 break;
1570 }
1571 case 2:
1572 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001573 png_bytep sp = png_ptr->row_buf + 1;
1574 png_bytep dp = row;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001575 int s_start, s_end, s_inc;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001576 int m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05001577 int shift;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001578 png_uint_32 i;
1579 png_uint_32 row_width = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001580 int value;
1581
Andreas Dilger47a0c421997-05-16 02:46:07 -05001582#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1583 if (png_ptr->transformations & PNG_PACKSWAP)
1584 {
1585 s_start = 0;
1586 s_end = 6;
1587 s_inc = 2;
1588 }
1589 else
1590#endif
1591 {
1592 s_start = 6;
1593 s_end = 0;
1594 s_inc = -2;
1595 }
1596
1597 shift = s_start;
1598
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001599 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001600 {
1601 if (m & mask)
1602 {
1603 value = (*sp >> shift) & 0x3;
1604 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001605 *dp |= (png_byte)(value << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05001606 }
1607
Andreas Dilger47a0c421997-05-16 02:46:07 -05001608 if (shift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05001609 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001610 shift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05001611 sp++;
1612 dp++;
1613 }
1614 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001615 shift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05001616 if (m == 1)
1617 m = 0x80;
1618 else
1619 m >>= 1;
1620 }
1621 break;
1622 }
1623 case 4:
1624 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001625 png_bytep sp = png_ptr->row_buf + 1;
1626 png_bytep dp = row;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001627 int s_start, s_end, s_inc;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001628 int m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05001629 int shift;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001630 png_uint_32 i;
1631 png_uint_32 row_width = png_ptr->width;
Guy Schalnat0d580581995-07-20 02:43:20 -05001632 int value;
1633
Andreas Dilger47a0c421997-05-16 02:46:07 -05001634#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1635 if (png_ptr->transformations & PNG_PACKSWAP)
1636 {
1637 s_start = 0;
1638 s_end = 4;
1639 s_inc = 4;
1640 }
1641 else
1642#endif
1643 {
1644 s_start = 4;
1645 s_end = 0;
1646 s_inc = -4;
1647 }
1648 shift = s_start;
1649
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001650 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001651 {
1652 if (m & mask)
1653 {
1654 value = (*sp >> shift) & 0xf;
1655 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001656 *dp |= (png_byte)(value << shift);
Guy Schalnat0d580581995-07-20 02:43:20 -05001657 }
1658
Andreas Dilger47a0c421997-05-16 02:46:07 -05001659 if (shift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05001660 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001661 shift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05001662 sp++;
1663 dp++;
1664 }
1665 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001666 shift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05001667 if (m == 1)
1668 m = 0x80;
1669 else
1670 m >>= 1;
1671 }
1672 break;
1673 }
1674 default:
1675 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001676 png_bytep sp = png_ptr->row_buf + 1;
1677 png_bytep dp = row;
1678 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
1679 png_uint_32 i;
1680 png_uint_32 row_width = png_ptr->width;
1681 png_byte m = 0x80;
Guy Schalnat0d580581995-07-20 02:43:20 -05001682
Guy Schalnat0d580581995-07-20 02:43:20 -05001683
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001684 for (i = 0; i < row_width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001685 {
1686 if (m & mask)
1687 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001688 png_memcpy(dp, sp, pixel_bytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05001689 }
1690
1691 sp += pixel_bytes;
1692 dp += pixel_bytes;
1693
1694 if (m == 1)
1695 m = 0x80;
1696 else
1697 m >>= 1;
1698 }
1699 break;
1700 }
1701 }
1702 }
1703}
1704
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001705#if defined(PNG_READ_INTERLACING_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05001706void
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001707#ifdef PNG_HAVE_ASSEMBLER_READ_INTERLACE
1708png_do_read_interlace_c
1709#else
1710png_do_read_interlace
1711#endif /* PNG_HAVE_ASSEMBLER_READ_INTERLACE */
1712 (png_row_infop row_info, png_bytep row, int pass,
Andreas Dilger47a0c421997-05-16 02:46:07 -05001713 png_uint_32 transformations)
Guy Schalnat0d580581995-07-20 02:43:20 -05001714{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001715 png_debug(1,"in png_do_read_interlace\n");
1716 if (row != NULL && row_info != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05001717 {
1718 png_uint_32 final_width;
1719
1720 final_width = row_info->width * png_pass_inc[pass];
1721
1722 switch (row_info->pixel_depth)
1723 {
1724 case 1:
1725 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001726 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
1727 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06001728 int sshift, dshift;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001729 int s_start, s_end, s_inc;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001730 int jstop = png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05001731 png_byte v;
1732 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001733 int j;
Guy Schalnat0d580581995-07-20 02:43:20 -05001734
Andreas Dilger47a0c421997-05-16 02:46:07 -05001735#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1736 if (transformations & PNG_PACKSWAP)
1737 {
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06001738 sshift = (int)((row_info->width + 7) & 7);
1739 dshift = (int)((final_width + 7) & 7);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001740 s_start = 7;
1741 s_end = 0;
1742 s_inc = -1;
1743 }
1744 else
1745#endif
1746 {
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06001747 sshift = 7 - (int)((row_info->width + 7) & 7);
1748 dshift = 7 - (int)((final_width + 7) & 7);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001749 s_start = 0;
1750 s_end = 7;
1751 s_inc = 1;
1752 }
1753
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001754 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001755 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001756 v = (png_byte)((*sp >> sshift) & 0x1);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001757 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001758 {
1759 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
1760 *dp |= (png_byte)(v << dshift);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001761 if (dshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05001762 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001763 dshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05001764 dp--;
1765 }
1766 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001767 dshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05001768 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001769 if (sshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05001770 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001771 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05001772 sp--;
1773 }
1774 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001775 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05001776 }
1777 break;
1778 }
1779 case 2:
1780 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001781 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
1782 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06001783 int sshift, dshift;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001784 int s_start, s_end, s_inc;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001785 int jstop = png_pass_inc[pass];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001786 png_uint_32 i;
Guy Schalnat0d580581995-07-20 02:43:20 -05001787
Andreas Dilger47a0c421997-05-16 02:46:07 -05001788#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1789 if (transformations & PNG_PACKSWAP)
1790 {
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06001791 sshift = (int)(((row_info->width + 3) & 3) << 1);
1792 dshift = (int)(((final_width + 3) & 3) << 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001793 s_start = 6;
1794 s_end = 0;
1795 s_inc = -2;
1796 }
1797 else
1798#endif
1799 {
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06001800 sshift = (int)((3 - ((row_info->width + 3) & 3)) << 1);
1801 dshift = (int)((3 - ((final_width + 3) & 3)) << 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001802 s_start = 0;
1803 s_end = 6;
1804 s_inc = 2;
1805 }
1806
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001807 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001808 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001809 png_byte v;
1810 int j;
1811
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001812 v = (png_byte)((*sp >> sshift) & 0x3);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001813 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001814 {
1815 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001816 *dp |= (png_byte)(v << dshift);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001817 if (dshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05001818 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001819 dshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05001820 dp--;
1821 }
1822 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001823 dshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05001824 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001825 if (sshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05001826 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001827 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05001828 sp--;
1829 }
1830 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001831 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05001832 }
1833 break;
1834 }
1835 case 4:
1836 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001837 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
1838 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06001839 int sshift, dshift;
Andreas Dilger47a0c421997-05-16 02:46:07 -05001840 int s_start, s_end, s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05001841 png_uint_32 i;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001842 int jstop = png_pass_inc[pass];
Guy Schalnat0d580581995-07-20 02:43:20 -05001843
Andreas Dilger47a0c421997-05-16 02:46:07 -05001844#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1845 if (transformations & PNG_PACKSWAP)
1846 {
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06001847 sshift = (int)(((row_info->width + 1) & 1) << 2);
1848 dshift = (int)(((final_width + 1) & 1) << 2);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001849 s_start = 4;
1850 s_end = 0;
1851 s_inc = -4;
1852 }
1853 else
1854#endif
1855 {
Glenn Randers-Pehrson983ec161998-03-07 11:24:03 -06001856 sshift = (int)((1 - ((row_info->width + 1) & 1)) << 2);
1857 dshift = (int)((1 - ((final_width + 1) & 1)) << 2);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001858 s_start = 0;
1859 s_end = 4;
1860 s_inc = 4;
1861 }
1862
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001863 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001864 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001865 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001866 int j;
1867
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001868 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001869 {
1870 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001871 *dp |= (png_byte)(v << dshift);
Andreas Dilger47a0c421997-05-16 02:46:07 -05001872 if (dshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05001873 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001874 dshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05001875 dp--;
1876 }
1877 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001878 dshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05001879 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001880 if (sshift == s_end)
Guy Schalnat0d580581995-07-20 02:43:20 -05001881 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001882 sshift = s_start;
Guy Schalnat0d580581995-07-20 02:43:20 -05001883 sp--;
1884 }
1885 else
Andreas Dilger47a0c421997-05-16 02:46:07 -05001886 sshift += s_inc;
Guy Schalnat0d580581995-07-20 02:43:20 -05001887 }
1888 break;
1889 }
1890 default:
1891 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001892 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
1893 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
1894 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
1895 int jstop = png_pass_inc[pass];
Andreas Dilger47a0c421997-05-16 02:46:07 -05001896 png_uint_32 i;
Guy Schalnat0d580581995-07-20 02:43:20 -05001897
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001898 for (i = 0; i < row_info->width; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001899 {
Andreas Dilger47a0c421997-05-16 02:46:07 -05001900 png_byte v[8];
1901 int j;
1902
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001903 png_memcpy(v, sp, pixel_bytes);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001904 for (j = 0; j < jstop; j++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001905 {
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001906 png_memcpy(dp, v, pixel_bytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05001907 dp -= pixel_bytes;
1908 }
1909 sp -= pixel_bytes;
1910 }
1911 break;
1912 }
1913 }
1914 row_info->width = final_width;
1915 row_info->rowbytes = ((final_width *
1916 (png_uint_32)row_info->pixel_depth + 7) >> 3);
1917 }
1918}
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001919#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001920
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001921void
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001922#ifdef PNG_HAVE_ASSEMBLER_READ_FILTER_ROW
1923png_read_filter_row_c
1924#else
1925png_read_filter_row
1926#endif /* PNG_HAVE_ASSEMBLER_READ_FILTER_ROW */
1927 (png_structp png_ptr, png_row_infop row_info, png_bytep row,
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001928 png_bytep prev_row, int filter)
1929{
1930 png_debug(1, "in png_read_filter_row\n");
1931 png_debug2(2,"row = %d, filter = %d\n", png_ptr->row_number, filter);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001932 switch (filter)
1933 {
1934 case PNG_FILTER_VALUE_NONE:
1935 break;
1936 case PNG_FILTER_VALUE_SUB:
1937 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001938 png_uint_32 i;
1939 png_uint_32 istop = row_info->rowbytes;
1940 png_uint_32 bpp = (row_info->pixel_depth + 7) / 8;
1941 png_bytep rp = row + bpp;
1942 png_bytep lp = row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001943
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001944 for (i = bpp; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001945 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001946 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
1947 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001948 }
1949 break;
1950 }
1951 case PNG_FILTER_VALUE_UP:
1952 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001953 png_uint_32 i;
1954 png_uint_32 istop = row_info->rowbytes;
1955 png_bytep rp = row;
1956 png_bytep pp = prev_row;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001957
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001958 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001959 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001960 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
1961 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001962 }
1963 break;
1964 }
1965 case PNG_FILTER_VALUE_AVG:
1966 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001967 png_uint_32 i;
1968 png_bytep rp = row;
1969 png_bytep pp = prev_row;
1970 png_bytep lp = row;
1971 png_uint_32 bpp = (row_info->pixel_depth + 7) / 8;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001972 png_uint_32 istop = row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001973
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001974 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001975 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001976 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001977 ((int)(*pp++) / 2)) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001978 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001979 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001980
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001981 for (i = 0; i < istop; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001982 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001983 *rp = (png_byte)(((int)(*rp) +
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001984 (int)(*pp++ + *lp++) / 2) & 0xff);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001985 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001986 }
1987 break;
1988 }
1989 case PNG_FILTER_VALUE_PAETH:
1990 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001991 png_uint_32 i;
1992 png_bytep rp = row;
1993 png_bytep pp = prev_row;
1994 png_bytep lp = row;
1995 png_bytep cp = prev_row;
1996 png_uint_32 bpp = (row_info->pixel_depth + 7) / 8;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05001997 png_uint_32 istop=row_info->rowbytes - bpp;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001998
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001999 for (i = 0; i < bpp; i++)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002000 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002001 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2002 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002003 }
2004
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002005 for (i = 0; i < istop; i++) /* use leftover rp,pp */
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002006 {
2007 int a, b, c, pa, pb, pc, p;
2008
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002009 a = *lp++;
2010 b = *pp++;
2011 c = *cp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002012
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002013 p = b - c;
2014 pc = a - c;
2015
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002016#ifdef PNG_USE_ABS
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002017 pa = abs(p);
2018 pb = abs(pc);
2019 pc = abs(p + pc);
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002020#else
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05002021 pa = p < 0 ? -p : p;
2022 pb = pc < 0 ? -pc : pc;
2023 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002024#endif
2025
2026 /*
2027 if (pa <= pb && pa <= pc)
2028 p = a;
2029 else if (pb <= pc)
2030 p = b;
2031 else
2032 p = c;
2033 */
2034
2035 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
2036
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -05002037 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2038 rp++;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002039 }
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002040 break;
2041 }
2042 default:
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002043 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2044 *row=0;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002045 break;
2046 }
2047}
Guy Schalnat0d580581995-07-20 02:43:20 -05002048
2049void
Guy Schalnat6d764711995-12-19 03:22:19 -06002050png_read_finish_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002051{
Andreas Dilger47a0c421997-05-16 02:46:07 -05002052 png_debug(1, "in png_read_finish_row\n");
Guy Schalnat0d580581995-07-20 02:43:20 -05002053 png_ptr->row_number++;
2054 if (png_ptr->row_number < png_ptr->num_rows)
2055 return;
2056
2057 if (png_ptr->interlaced)
2058 {
2059 png_ptr->row_number = 0;
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002060 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Guy Schalnat0d580581995-07-20 02:43:20 -05002061 do
2062 {
2063 png_ptr->pass++;
2064 if (png_ptr->pass >= 7)
2065 break;
2066 png_ptr->iwidth = (png_ptr->width +
2067 png_pass_inc[png_ptr->pass] - 1 -
2068 png_pass_start[png_ptr->pass]) /
2069 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002070 png_ptr->irowbytes = ((png_ptr->iwidth *
2071 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2072
Guy Schalnat0d580581995-07-20 02:43:20 -05002073 if (!(png_ptr->transformations & PNG_INTERLACE))
2074 {
2075 png_ptr->num_rows = (png_ptr->height +
2076 png_pass_yinc[png_ptr->pass] - 1 -
2077 png_pass_ystart[png_ptr->pass]) /
2078 png_pass_yinc[png_ptr->pass];
2079 if (!(png_ptr->num_rows))
2080 continue;
2081 }
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -05002082 else /* if (png_ptr->transformations & PNG_INTERLACE) */
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002083 break;
Guy Schalnat0d580581995-07-20 02:43:20 -05002084 } while (png_ptr->iwidth == 0);
2085
2086 if (png_ptr->pass < 7)
2087 return;
2088 }
2089
Guy Schalnate5a37791996-06-05 15:50:50 -05002090 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
Guy Schalnat0d580581995-07-20 02:43:20 -05002091 {
2092 char extra;
2093 int ret;
2094
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002095 png_ptr->zstream.next_out = (Byte *)&extra;
2096 png_ptr->zstream.avail_out = (uInt)1;
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -06002097 for(;;)
Guy Schalnat0d580581995-07-20 02:43:20 -05002098 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002099 if (!(png_ptr->zstream.avail_in))
Guy Schalnat0d580581995-07-20 02:43:20 -05002100 {
2101 while (!png_ptr->idat_size)
2102 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002103 png_byte chunk_length[4];
Guy Schalnat0d580581995-07-20 02:43:20 -05002104
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002105 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -05002106
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002107 png_read_data(png_ptr, chunk_length, 4);
2108 png_ptr->idat_size = png_get_uint_32(chunk_length);
2109
Guy Schalnat0d580581995-07-20 02:43:20 -05002110 png_reset_crc(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002111 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2112 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Guy Schalnat6d764711995-12-19 03:22:19 -06002113 png_error(png_ptr, "Not enough image data");
Guy Schalnat0d580581995-07-20 02:43:20 -05002114
2115 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002116 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2117 png_ptr->zstream.next_in = png_ptr->zbuf;
Guy Schalnat0d580581995-07-20 02:43:20 -05002118 if (png_ptr->zbuf_size > png_ptr->idat_size)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002119 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2120 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2121 png_ptr->idat_size -= png_ptr->zstream.avail_in;
Guy Schalnat0d580581995-07-20 02:43:20 -05002122 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002123 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnat0d580581995-07-20 02:43:20 -05002124 if (ret == Z_STREAM_END)
2125 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002126 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
Guy Schalnat0d580581995-07-20 02:43:20 -05002127 png_ptr->idat_size)
Guy Schalnat6d764711995-12-19 03:22:19 -06002128 png_error(png_ptr, "Extra compressed data");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002129 png_ptr->mode |= PNG_AFTER_IDAT;
2130 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Guy Schalnat0d580581995-07-20 02:43:20 -05002131 break;
2132 }
2133 if (ret != Z_OK)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002134 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
Guy Schalnate5a37791996-06-05 15:50:50 -05002135 "Decompression Error");
Guy Schalnat0d580581995-07-20 02:43:20 -05002136
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002137 if (!(png_ptr->zstream.avail_out))
Guy Schalnat6d764711995-12-19 03:22:19 -06002138 png_error(png_ptr, "Extra compressed data");
Guy Schalnat0d580581995-07-20 02:43:20 -05002139
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -06002140 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002141 png_ptr->zstream.avail_out = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002142 }
2143
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002144 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
Guy Schalnat6d764711995-12-19 03:22:19 -06002145 png_error(png_ptr, "Extra compression data");
Guy Schalnat0d580581995-07-20 02:43:20 -05002146
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002147 inflateReset(&png_ptr->zstream);
Guy Schalnat0d580581995-07-20 02:43:20 -05002148
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002149 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnat0d580581995-07-20 02:43:20 -05002150}
2151
2152void
Guy Schalnat6d764711995-12-19 03:22:19 -06002153png_read_start_row(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05002154{
2155 int max_pixel_depth;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002156 png_uint_32 row_bytes;
Guy Schalnat0d580581995-07-20 02:43:20 -05002157
Andreas Dilger47a0c421997-05-16 02:46:07 -05002158 png_debug(1, "in png_read_start_row\n");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06002159 png_ptr->zstream.avail_in = 0;
Guy Schalnat0d580581995-07-20 02:43:20 -05002160 png_init_read_transformations(png_ptr);
2161 if (png_ptr->interlaced)
2162 {
2163 if (!(png_ptr->transformations & PNG_INTERLACE))
2164 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2165 png_pass_ystart[0]) / png_pass_yinc[0];
2166 else
2167 png_ptr->num_rows = png_ptr->height;
2168
2169 png_ptr->iwidth = (png_ptr->width +
2170 png_pass_inc[png_ptr->pass] - 1 -
2171 png_pass_start[png_ptr->pass]) /
2172 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002173
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002174 row_bytes = ((png_ptr->iwidth *
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002175 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002176 png_ptr->irowbytes = (png_size_t)row_bytes;
2177 if((png_uint_32)png_ptr->irowbytes != row_bytes)
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002178 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
Guy Schalnat0d580581995-07-20 02:43:20 -05002179 }
2180 else
2181 {
2182 png_ptr->num_rows = png_ptr->height;
2183 png_ptr->iwidth = png_ptr->width;
2184 png_ptr->irowbytes = png_ptr->rowbytes + 1;
2185 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002186 max_pixel_depth = png_ptr->pixel_depth;
2187
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002188#if defined(PNG_READ_PACK_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05002189 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
Guy Schalnat0d580581995-07-20 02:43:20 -05002190 max_pixel_depth = 8;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002191#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002192
Guy Schalnate5a37791996-06-05 15:50:50 -05002193#if defined(PNG_READ_EXPAND_SUPPORTED)
2194 if (png_ptr->transformations & PNG_EXPAND)
Guy Schalnat0d580581995-07-20 02:43:20 -05002195 {
2196 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2197 {
2198 if (png_ptr->num_trans)
2199 max_pixel_depth = 32;
2200 else
2201 max_pixel_depth = 24;
2202 }
2203 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2204 {
2205 if (max_pixel_depth < 8)
2206 max_pixel_depth = 8;
2207 if (png_ptr->num_trans)
2208 max_pixel_depth *= 2;
2209 }
2210 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2211 {
2212 if (png_ptr->num_trans)
2213 {
2214 max_pixel_depth *= 4;
2215 max_pixel_depth /= 3;
2216 }
2217 }
2218 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002219#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002220
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002221#if defined(PNG_READ_FILLER_SUPPORTED)
2222 if (png_ptr->transformations & (PNG_FILLER))
Guy Schalnat0d580581995-07-20 02:43:20 -05002223 {
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002224 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2225 max_pixel_depth = 32;
2226 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002227 {
2228 if (max_pixel_depth <= 8)
2229 max_pixel_depth = 16;
2230 else
2231 max_pixel_depth = 32;
2232 }
2233 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2234 {
2235 if (max_pixel_depth <= 32)
2236 max_pixel_depth = 32;
2237 else
2238 max_pixel_depth = 64;
2239 }
Guy Schalnat0d580581995-07-20 02:43:20 -05002240 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002241#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002242
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002243#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -05002244 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
2245 {
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002246 if (
2247#if defined(PNG_READ_EXPAND_SUPPORTED)
2248 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
2249#endif
2250#if defined(PNG_READ_FILLER_SUPPORTED)
2251 (png_ptr->transformations & (PNG_FILLER)) ||
2252#endif
2253 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
Guy Schalnat0d580581995-07-20 02:43:20 -05002254 {
2255 if (max_pixel_depth <= 16)
2256 max_pixel_depth = 32;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002257 else
Guy Schalnat0d580581995-07-20 02:43:20 -05002258 max_pixel_depth = 64;
2259 }
2260 else
2261 {
2262 if (max_pixel_depth <= 8)
2263 max_pixel_depth = 24;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06002264 else
Guy Schalnat0d580581995-07-20 02:43:20 -05002265 max_pixel_depth = 48;
2266 }
2267 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05002268#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05002269
2270 /* align the width on the next larger 8 pixels. Mainly used
2271 for interlacing */
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002272 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
Guy Schalnat0d580581995-07-20 02:43:20 -05002273 /* calculate the maximum bytes needed, adding a byte and a pixel
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05002274 for safety's sake */
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002275 row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
Guy Schalnat0d580581995-07-20 02:43:20 -05002276 1 + ((max_pixel_depth + 7) >> 3);
2277#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002278 if (row_bytes > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05002279 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05002280#endif
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -05002281 png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, row_bytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05002282
2283#ifdef PNG_MAX_MALLOC_64K
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06002284 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
Guy Schalnate5a37791996-06-05 15:50:50 -05002285 png_error(png_ptr, "This image requires a row greater than 64KB");
Guy Schalnat0d580581995-07-20 02:43:20 -05002286#endif
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -06002287 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
2288 png_ptr->rowbytes + 1));
Guy Schalnat0d580581995-07-20 02:43:20 -05002289
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -06002290 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Andreas Dilger47a0c421997-05-16 02:46:07 -05002291
2292 png_debug1(3, "width = %d,\n", png_ptr->width);
2293 png_debug1(3, "height = %d,\n", png_ptr->height);
2294 png_debug1(3, "iwidth = %d,\n", png_ptr->iwidth);
2295 png_debug1(3, "num_rows = %d\n", png_ptr->num_rows);
2296 png_debug1(3, "rowbytes = %d,\n", png_ptr->rowbytes);
2297 png_debug1(3, "irowbytes = %d,\n", png_ptr->irowbytes);
Guy Schalnat0d580581995-07-20 02:43:20 -05002298
Guy Schalnate5a37791996-06-05 15:50:50 -05002299 png_ptr->flags |= PNG_FLAG_ROW_INIT;
Guy Schalnat0d580581995-07-20 02:43:20 -05002300}