]> git.saurik.com Git - wxWidgets.git/blame - src/png/pngrutil.c
add src/gtk1/mnemonics.cpp to files.bkl and rebake
[wxWidgets.git] / src / png / pngrutil.c
CommitLineData
0272a10d
VZ
1
2/* pngrutil.c - utilities to read a PNG file
3 *
970f6abe 4 * Last changed in libpng 1.2.34 [December 18, 2008]
0272a10d 5 * For conditions of distribution and use, see copyright notice in png.h
970f6abe 6 * Copyright (c) 1998-2008 Glenn Randers-Pehrson
0272a10d
VZ
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9 *
10 * This file contains routines that are only called from within
11 * libpng itself during the course of reading an image.
12 */
13
14#define PNG_INTERNAL
15#include "png.h"
0272a10d
VZ
16#if defined(PNG_READ_SUPPORTED)
17
18#if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
19# define WIN32_WCE_OLD
20#endif
21
22#ifdef PNG_FLOATING_POINT_SUPPORTED
23# if defined(WIN32_WCE_OLD)
24/* strtod() function is not supported on WindowsCE */
25__inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr)
26{
27 double result = 0;
28 int len;
29 wchar_t *str, *end;
30
31 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
970f6abe 32 str = (wchar_t *)png_malloc(png_ptr, len * png_sizeof(wchar_t));
0272a10d
VZ
33 if ( NULL != str )
34 {
35 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
36 result = wcstod(str, &end);
37 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
38 *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
39 png_free(png_ptr, str);
40 }
41 return result;
42}
43# else
44# define png_strtod(p,a,b) strtod(a,b)
45# endif
46#endif
47
48png_uint_32 PNGAPI
49png_get_uint_31(png_structp png_ptr, png_bytep buf)
50{
970f6abe 51#ifdef PNG_READ_BIG_ENDIAN_SUPPORTED
0272a10d 52 png_uint_32 i = png_get_uint_32(buf);
970f6abe
VZ
53#else
54 /* Avoid an extra function call by inlining the result. */
55 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
56 ((png_uint_32)(*(buf + 1)) << 16) +
57 ((png_uint_32)(*(buf + 2)) << 8) +
58 (png_uint_32)(*(buf + 3));
59#endif
0272a10d
VZ
60 if (i > PNG_UINT_31_MAX)
61 png_error(png_ptr, "PNG unsigned integer out of range.");
62 return (i);
63}
64#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
65/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
66png_uint_32 PNGAPI
67png_get_uint_32(png_bytep buf)
68{
69 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
70 ((png_uint_32)(*(buf + 1)) << 16) +
71 ((png_uint_32)(*(buf + 2)) << 8) +
72 (png_uint_32)(*(buf + 3));
73
74 return (i);
75}
76
77/* Grab a signed 32-bit integer from a buffer in big-endian format. The
78 * data is stored in the PNG file in two's complement format, and it is
79 * assumed that the machine format for signed integers is the same. */
80png_int_32 PNGAPI
81png_get_int_32(png_bytep buf)
82{
83 png_int_32 i = ((png_int_32)(*buf) << 24) +
84 ((png_int_32)(*(buf + 1)) << 16) +
85 ((png_int_32)(*(buf + 2)) << 8) +
86 (png_int_32)(*(buf + 3));
87
88 return (i);
89}
90
91/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
92png_uint_16 PNGAPI
93png_get_uint_16(png_bytep buf)
94{
95 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
96 (png_uint_16)(*(buf + 1)));
97
98 return (i);
99}
100#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
101
970f6abe
VZ
102/* Read the chunk header (length + type name).
103 * Put the type name into png_ptr->chunk_name, and return the length.
104 */
105png_uint_32 /* PRIVATE */
106png_read_chunk_header(png_structp png_ptr)
107{
108 png_byte buf[8];
109 png_uint_32 length;
110
111 /* read the length and the chunk name */
112 png_read_data(png_ptr, buf, 8);
113 length = png_get_uint_31(png_ptr, buf);
114
115 /* put the chunk name into png_ptr->chunk_name */
116 png_memcpy(png_ptr->chunk_name, buf + 4, 4);
117
118 png_debug2(0, "Reading %s chunk, length = %lu",
119 png_ptr->chunk_name, length);
120
121 /* reset the crc and run it over the chunk name */
122 png_reset_crc(png_ptr);
123 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
124
125 /* check to see if chunk name is valid */
126 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
127
128 return length;
129}
130
0272a10d
VZ
131/* Read data, and (optionally) run it through the CRC. */
132void /* PRIVATE */
133png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
134{
970f6abe 135 if (png_ptr == NULL) return;
0272a10d
VZ
136 png_read_data(png_ptr, buf, length);
137 png_calculate_crc(png_ptr, buf, length);
138}
139
140/* Optionally skip data and then check the CRC. Depending on whether we
141 are reading a ancillary or critical chunk, and how the program has set
142 things up, we may calculate the CRC on the data and print a message.
143 Returns '1' if there was a CRC error, '0' otherwise. */
144int /* PRIVATE */
145png_crc_finish(png_structp png_ptr, png_uint_32 skip)
146{
147 png_size_t i;
148 png_size_t istop = png_ptr->zbuf_size;
149
150 for (i = (png_size_t)skip; i > istop; i -= istop)
151 {
152 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
153 }
154 if (i)
155 {
156 png_crc_read(png_ptr, png_ptr->zbuf, i);
157 }
158
159 if (png_crc_error(png_ptr))
160 {
161 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
162 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
163 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
164 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
165 {
166 png_chunk_warning(png_ptr, "CRC error");
167 }
168 else
169 {
170 png_chunk_error(png_ptr, "CRC error");
171 }
172 return (1);
173 }
174
175 return (0);
176}
177
178/* Compare the CRC stored in the PNG file with that calculated by libpng from
179 the data it has read thus far. */
180int /* PRIVATE */
181png_crc_error(png_structp png_ptr)
182{
183 png_byte crc_bytes[4];
184 png_uint_32 crc;
185 int need_crc = 1;
186
187 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
188 {
189 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
190 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
191 need_crc = 0;
192 }
193 else /* critical */
194 {
195 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
196 need_crc = 0;
197 }
198
199 png_read_data(png_ptr, crc_bytes, 4);
200
201 if (need_crc)
202 {
203 crc = png_get_uint_32(crc_bytes);
204 return ((int)(crc != png_ptr->crc));
205 }
206 else
207 return (0);
208}
209
210#if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
211 defined(PNG_READ_iCCP_SUPPORTED)
212/*
213 * Decompress trailing data in a chunk. The assumption is that chunkdata
214 * points at an allocated area holding the contents of a chunk with a
215 * trailing compressed part. What we get back is an allocated area
216 * holding the original prefix part and an uncompressed version of the
217 * trailing part (the malloc area passed in is freed).
218 */
970f6abe 219void /* PRIVATE */
0272a10d 220png_decompress_chunk(png_structp png_ptr, int comp_type,
970f6abe 221 png_size_t chunklength,
0272a10d
VZ
222 png_size_t prefix_size, png_size_t *newlength)
223{
224 static PNG_CONST char msg[] = "Error decoding compressed text";
225 png_charp text;
226 png_size_t text_size;
227
228 if (comp_type == PNG_COMPRESSION_TYPE_BASE)
229 {
230 int ret = Z_OK;
970f6abe 231 png_ptr->zstream.next_in = (png_bytep)(png_ptr->chunkdata + prefix_size);
0272a10d
VZ
232 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
233 png_ptr->zstream.next_out = png_ptr->zbuf;
234 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
235
236 text_size = 0;
237 text = NULL;
238
239 while (png_ptr->zstream.avail_in)
240 {
241 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
242 if (ret != Z_OK && ret != Z_STREAM_END)
243 {
244 if (png_ptr->zstream.msg != NULL)
245 png_warning(png_ptr, png_ptr->zstream.msg);
246 else
247 png_warning(png_ptr, msg);
248 inflateReset(&png_ptr->zstream);
249 png_ptr->zstream.avail_in = 0;
250
251 if (text == NULL)
252 {
253 text_size = prefix_size + png_sizeof(msg) + 1;
254 text = (png_charp)png_malloc_warn(png_ptr, text_size);
255 if (text == NULL)
256 {
970f6abe
VZ
257 png_free(png_ptr, png_ptr->chunkdata);
258 png_ptr->chunkdata = NULL;
259 png_error(png_ptr, "Not enough memory to decompress chunk");
0272a10d 260 }
970f6abe 261 png_memcpy(text, png_ptr->chunkdata, prefix_size);
0272a10d
VZ
262 }
263
264 text[text_size - 1] = 0x00;
265
266 /* Copy what we can of the error message into the text chunk */
970f6abe
VZ
267 text_size = (png_size_t)(chunklength -
268 (text - png_ptr->chunkdata) - 1);
269 if (text_size > png_sizeof(msg))
270 text_size = png_sizeof(msg);
271 png_memcpy(text + prefix_size, msg, text_size);
0272a10d
VZ
272 break;
273 }
274 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
275 {
276 if (text == NULL)
277 {
278 text_size = prefix_size +
279 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
280 text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
281 if (text == NULL)
970f6abe
VZ
282 {
283 png_free(png_ptr, png_ptr->chunkdata);
284 png_ptr->chunkdata = NULL;
285 png_error(png_ptr,
286 "Not enough memory to decompress chunk.");
287 }
0272a10d
VZ
288 png_memcpy(text + prefix_size, png_ptr->zbuf,
289 text_size - prefix_size);
970f6abe 290 png_memcpy(text, png_ptr->chunkdata, prefix_size);
0272a10d
VZ
291 *(text + text_size) = 0x00;
292 }
293 else
294 {
295 png_charp tmp;
296
297 tmp = text;
298 text = (png_charp)png_malloc_warn(png_ptr,
299 (png_uint_32)(text_size +
300 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
301 if (text == NULL)
302 {
303 png_free(png_ptr, tmp);
970f6abe
VZ
304 png_free(png_ptr, png_ptr->chunkdata);
305 png_ptr->chunkdata = NULL;
306 png_error(png_ptr,
307 "Not enough memory to decompress chunk..");
0272a10d
VZ
308 }
309 png_memcpy(text, tmp, text_size);
310 png_free(png_ptr, tmp);
311 png_memcpy(text + text_size, png_ptr->zbuf,
312 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
313 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
314 *(text + text_size) = 0x00;
315 }
316 if (ret == Z_STREAM_END)
317 break;
318 else
319 {
320 png_ptr->zstream.next_out = png_ptr->zbuf;
321 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
322 }
323 }
324 }
325 if (ret != Z_STREAM_END)
326 {
327#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
328 char umsg[52];
329
330 if (ret == Z_BUF_ERROR)
331 png_snprintf(umsg, 52,
332 "Buffer error in compressed datastream in %s chunk",
333 png_ptr->chunk_name);
334 else if (ret == Z_DATA_ERROR)
335 png_snprintf(umsg, 52,
336 "Data error in compressed datastream in %s chunk",
337 png_ptr->chunk_name);
338 else
339 png_snprintf(umsg, 52,
340 "Incomplete compressed datastream in %s chunk",
341 png_ptr->chunk_name);
342 png_warning(png_ptr, umsg);
343#else
344 png_warning(png_ptr,
345 "Incomplete compressed datastream in chunk other than IDAT");
346#endif
970f6abe 347 text_size = prefix_size;
0272a10d
VZ
348 if (text == NULL)
349 {
350 text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
351 if (text == NULL)
352 {
970f6abe
VZ
353 png_free(png_ptr, png_ptr->chunkdata);
354 png_ptr->chunkdata = NULL;
355 png_error(png_ptr, "Not enough memory for text.");
0272a10d 356 }
970f6abe 357 png_memcpy(text, png_ptr->chunkdata, prefix_size);
0272a10d
VZ
358 }
359 *(text + text_size) = 0x00;
360 }
361
362 inflateReset(&png_ptr->zstream);
363 png_ptr->zstream.avail_in = 0;
364
970f6abe
VZ
365 png_free(png_ptr, png_ptr->chunkdata);
366 png_ptr->chunkdata = text;
0272a10d
VZ
367 *newlength=text_size;
368 }
369 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
370 {
371#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
372 char umsg[50];
373
970f6abe 374 png_snprintf(umsg, 50, "Unknown zTXt compression type %d", comp_type);
0272a10d
VZ
375 png_warning(png_ptr, umsg);
376#else
377 png_warning(png_ptr, "Unknown zTXt compression type");
378#endif
379
970f6abe
VZ
380 *(png_ptr->chunkdata + prefix_size) = 0x00;
381 *newlength = prefix_size;
0272a10d 382 }
0272a10d
VZ
383}
384#endif
385
386/* read and check the IDHR chunk */
387void /* PRIVATE */
388png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
389{
390 png_byte buf[13];
391 png_uint_32 width, height;
392 int bit_depth, color_type, compression_type, filter_type;
393 int interlace_type;
394
970f6abe 395 png_debug(1, "in png_handle_IHDR");
0272a10d
VZ
396
397 if (png_ptr->mode & PNG_HAVE_IHDR)
398 png_error(png_ptr, "Out of place IHDR");
399
400 /* check the length */
401 if (length != 13)
402 png_error(png_ptr, "Invalid IHDR chunk");
403
404 png_ptr->mode |= PNG_HAVE_IHDR;
405
406 png_crc_read(png_ptr, buf, 13);
407 png_crc_finish(png_ptr, 0);
408
409 width = png_get_uint_31(png_ptr, buf);
410 height = png_get_uint_31(png_ptr, buf + 4);
411 bit_depth = buf[8];
412 color_type = buf[9];
413 compression_type = buf[10];
414 filter_type = buf[11];
415 interlace_type = buf[12];
416
417 /* set internal variables */
418 png_ptr->width = width;
419 png_ptr->height = height;
420 png_ptr->bit_depth = (png_byte)bit_depth;
421 png_ptr->interlaced = (png_byte)interlace_type;
422 png_ptr->color_type = (png_byte)color_type;
423#if defined(PNG_MNG_FEATURES_SUPPORTED)
424 png_ptr->filter_type = (png_byte)filter_type;
425#endif
426 png_ptr->compression_type = (png_byte)compression_type;
427
428 /* find number of channels */
429 switch (png_ptr->color_type)
430 {
431 case PNG_COLOR_TYPE_GRAY:
432 case PNG_COLOR_TYPE_PALETTE:
433 png_ptr->channels = 1;
434 break;
435 case PNG_COLOR_TYPE_RGB:
436 png_ptr->channels = 3;
437 break;
438 case PNG_COLOR_TYPE_GRAY_ALPHA:
439 png_ptr->channels = 2;
440 break;
441 case PNG_COLOR_TYPE_RGB_ALPHA:
442 png_ptr->channels = 4;
443 break;
444 }
445
446 /* set up other useful info */
447 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
448 png_ptr->channels);
970f6abe
VZ
449 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
450 png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
451 png_debug1(3, "channels = %d", png_ptr->channels);
452 png_debug1(3, "rowbytes = %lu", png_ptr->rowbytes);
0272a10d
VZ
453 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
454 color_type, interlace_type, compression_type, filter_type);
455}
456
457/* read and check the palette */
458void /* PRIVATE */
459png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
460{
461 png_color palette[PNG_MAX_PALETTE_LENGTH];
462 int num, i;
463#ifndef PNG_NO_POINTER_INDEXING
464 png_colorp pal_ptr;
465#endif
466
970f6abe 467 png_debug(1, "in png_handle_PLTE");
0272a10d
VZ
468
469 if (!(png_ptr->mode & PNG_HAVE_IHDR))
470 png_error(png_ptr, "Missing IHDR before PLTE");
471 else if (png_ptr->mode & PNG_HAVE_IDAT)
472 {
473 png_warning(png_ptr, "Invalid PLTE after IDAT");
474 png_crc_finish(png_ptr, length);
475 return;
476 }
477 else if (png_ptr->mode & PNG_HAVE_PLTE)
478 png_error(png_ptr, "Duplicate PLTE chunk");
479
480 png_ptr->mode |= PNG_HAVE_PLTE;
481
482 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
483 {
484 png_warning(png_ptr,
485 "Ignoring PLTE chunk in grayscale PNG");
486 png_crc_finish(png_ptr, length);
487 return;
488 }
489#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
490 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
491 {
492 png_crc_finish(png_ptr, length);
493 return;
494 }
495#endif
496
497 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
498 {
499 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
500 {
501 png_warning(png_ptr, "Invalid palette chunk");
502 png_crc_finish(png_ptr, length);
503 return;
504 }
505 else
506 {
507 png_error(png_ptr, "Invalid palette chunk");
508 }
509 }
510
511 num = (int)length / 3;
512
513#ifndef PNG_NO_POINTER_INDEXING
514 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
515 {
516 png_byte buf[3];
517
518 png_crc_read(png_ptr, buf, 3);
519 pal_ptr->red = buf[0];
520 pal_ptr->green = buf[1];
521 pal_ptr->blue = buf[2];
522 }
523#else
524 for (i = 0; i < num; i++)
525 {
526 png_byte buf[3];
527
528 png_crc_read(png_ptr, buf, 3);
529 /* don't depend upon png_color being any order */
530 palette[i].red = buf[0];
531 palette[i].green = buf[1];
532 palette[i].blue = buf[2];
533 }
534#endif
535
536 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
537 whatever the normal CRC configuration tells us. However, if we
538 have an RGB image, the PLTE can be considered ancillary, so
539 we will act as though it is. */
540#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
541 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
542#endif
543 {
544 png_crc_finish(png_ptr, 0);
545 }
546#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
547 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
548 {
549 /* If we don't want to use the data from an ancillary chunk,
550 we have two options: an error abort, or a warning and we
551 ignore the data in this chunk (which should be OK, since
552 it's considered ancillary for a RGB or RGBA image). */
553 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
554 {
555 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
556 {
557 png_chunk_error(png_ptr, "CRC error");
558 }
559 else
560 {
561 png_chunk_warning(png_ptr, "CRC error");
562 return;
563 }
564 }
565 /* Otherwise, we (optionally) emit a warning and use the chunk. */
566 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
567 {
568 png_chunk_warning(png_ptr, "CRC error");
569 }
570 }
571#endif
572
573 png_set_PLTE(png_ptr, info_ptr, palette, num);
574
575#if defined(PNG_READ_tRNS_SUPPORTED)
576 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
577 {
578 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
579 {
580 if (png_ptr->num_trans > (png_uint_16)num)
581 {
582 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
583 png_ptr->num_trans = (png_uint_16)num;
584 }
585 if (info_ptr->num_trans > (png_uint_16)num)
586 {
587 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
588 info_ptr->num_trans = (png_uint_16)num;
589 }
590 }
591 }
592#endif
593
594}
595
596void /* PRIVATE */
597png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
598{
970f6abe 599 png_debug(1, "in png_handle_IEND");
0272a10d
VZ
600
601 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
602 {
603 png_error(png_ptr, "No image in file");
604 }
605
606 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
607
608 if (length != 0)
609 {
610 png_warning(png_ptr, "Incorrect IEND chunk length");
611 }
612 png_crc_finish(png_ptr, length);
613
970f6abe 614 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
0272a10d
VZ
615}
616
617#if defined(PNG_READ_gAMA_SUPPORTED)
618void /* PRIVATE */
619png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
620{
621 png_fixed_point igamma;
622#ifdef PNG_FLOATING_POINT_SUPPORTED
623 float file_gamma;
624#endif
625 png_byte buf[4];
626
970f6abe 627 png_debug(1, "in png_handle_gAMA");
0272a10d
VZ
628
629 if (!(png_ptr->mode & PNG_HAVE_IHDR))
630 png_error(png_ptr, "Missing IHDR before gAMA");
631 else if (png_ptr->mode & PNG_HAVE_IDAT)
632 {
633 png_warning(png_ptr, "Invalid gAMA after IDAT");
634 png_crc_finish(png_ptr, length);
635 return;
636 }
637 else if (png_ptr->mode & PNG_HAVE_PLTE)
638 /* Should be an error, but we can cope with it */
639 png_warning(png_ptr, "Out of place gAMA chunk");
640
641 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
642#if defined(PNG_READ_sRGB_SUPPORTED)
643 && !(info_ptr->valid & PNG_INFO_sRGB)
644#endif
645 )
646 {
647 png_warning(png_ptr, "Duplicate gAMA chunk");
648 png_crc_finish(png_ptr, length);
649 return;
650 }
651
652 if (length != 4)
653 {
654 png_warning(png_ptr, "Incorrect gAMA chunk length");
655 png_crc_finish(png_ptr, length);
656 return;
657 }
658
659 png_crc_read(png_ptr, buf, 4);
660 if (png_crc_finish(png_ptr, 0))
661 return;
662
663 igamma = (png_fixed_point)png_get_uint_32(buf);
664 /* check for zero gamma */
665 if (igamma == 0)
666 {
667 png_warning(png_ptr,
668 "Ignoring gAMA chunk with gamma=0");
669 return;
670 }
671
672#if defined(PNG_READ_sRGB_SUPPORTED)
673 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
674 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
675 {
676 png_warning(png_ptr,
677 "Ignoring incorrect gAMA value when sRGB is also present");
678#ifndef PNG_NO_CONSOLE_IO
970f6abe 679 fprintf(stderr, "gamma = (%d/100000)", (int)igamma);
0272a10d
VZ
680#endif
681 return;
682 }
683#endif /* PNG_READ_sRGB_SUPPORTED */
684
685#ifdef PNG_FLOATING_POINT_SUPPORTED
686 file_gamma = (float)igamma / (float)100000.0;
687# ifdef PNG_READ_GAMMA_SUPPORTED
688 png_ptr->gamma = file_gamma;
689# endif
690 png_set_gAMA(png_ptr, info_ptr, file_gamma);
691#endif
692#ifdef PNG_FIXED_POINT_SUPPORTED
693 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
694#endif
695}
696#endif
697
698#if defined(PNG_READ_sBIT_SUPPORTED)
699void /* PRIVATE */
700png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
701{
702 png_size_t truelen;
703 png_byte buf[4];
704
970f6abe 705 png_debug(1, "in png_handle_sBIT");
0272a10d
VZ
706
707 buf[0] = buf[1] = buf[2] = buf[3] = 0;
708
709 if (!(png_ptr->mode & PNG_HAVE_IHDR))
710 png_error(png_ptr, "Missing IHDR before sBIT");
711 else if (png_ptr->mode & PNG_HAVE_IDAT)
712 {
713 png_warning(png_ptr, "Invalid sBIT after IDAT");
714 png_crc_finish(png_ptr, length);
715 return;
716 }
717 else if (png_ptr->mode & PNG_HAVE_PLTE)
718 {
719 /* Should be an error, but we can cope with it */
720 png_warning(png_ptr, "Out of place sBIT chunk");
721 }
722 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
723 {
724 png_warning(png_ptr, "Duplicate sBIT chunk");
725 png_crc_finish(png_ptr, length);
726 return;
727 }
728
729 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
730 truelen = 3;
731 else
732 truelen = (png_size_t)png_ptr->channels;
733
734 if (length != truelen || length > 4)
735 {
736 png_warning(png_ptr, "Incorrect sBIT chunk length");
737 png_crc_finish(png_ptr, length);
738 return;
739 }
740
741 png_crc_read(png_ptr, buf, truelen);
742 if (png_crc_finish(png_ptr, 0))
743 return;
744
745 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
746 {
747 png_ptr->sig_bit.red = buf[0];
748 png_ptr->sig_bit.green = buf[1];
749 png_ptr->sig_bit.blue = buf[2];
750 png_ptr->sig_bit.alpha = buf[3];
751 }
752 else
753 {
754 png_ptr->sig_bit.gray = buf[0];
755 png_ptr->sig_bit.red = buf[0];
756 png_ptr->sig_bit.green = buf[0];
757 png_ptr->sig_bit.blue = buf[0];
758 png_ptr->sig_bit.alpha = buf[1];
759 }
760 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
761}
762#endif
763
764#if defined(PNG_READ_cHRM_SUPPORTED)
765void /* PRIVATE */
766png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
767{
970f6abe 768 png_byte buf[32];
0272a10d
VZ
769#ifdef PNG_FLOATING_POINT_SUPPORTED
770 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
771#endif
772 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
773 int_y_green, int_x_blue, int_y_blue;
774
775 png_uint_32 uint_x, uint_y;
776
970f6abe 777 png_debug(1, "in png_handle_cHRM");
0272a10d
VZ
778
779 if (!(png_ptr->mode & PNG_HAVE_IHDR))
780 png_error(png_ptr, "Missing IHDR before cHRM");
781 else if (png_ptr->mode & PNG_HAVE_IDAT)
782 {
783 png_warning(png_ptr, "Invalid cHRM after IDAT");
784 png_crc_finish(png_ptr, length);
785 return;
786 }
787 else if (png_ptr->mode & PNG_HAVE_PLTE)
788 /* Should be an error, but we can cope with it */
789 png_warning(png_ptr, "Missing PLTE before cHRM");
790
791 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
792#if defined(PNG_READ_sRGB_SUPPORTED)
793 && !(info_ptr->valid & PNG_INFO_sRGB)
794#endif
795 )
796 {
797 png_warning(png_ptr, "Duplicate cHRM chunk");
798 png_crc_finish(png_ptr, length);
799 return;
800 }
801
802 if (length != 32)
803 {
804 png_warning(png_ptr, "Incorrect cHRM chunk length");
805 png_crc_finish(png_ptr, length);
806 return;
807 }
808
970f6abe
VZ
809 png_crc_read(png_ptr, buf, 32);
810 if (png_crc_finish(png_ptr, 0))
0272a10d 811 return;
0272a10d 812
0272a10d 813 uint_x = png_get_uint_32(buf);
970f6abe
VZ
814 uint_y = png_get_uint_32(buf + 4);
815 int_x_white = (png_fixed_point)uint_x;
816 int_y_white = (png_fixed_point)uint_y;
0272a10d 817
970f6abe
VZ
818 uint_x = png_get_uint_32(buf + 8);
819 uint_y = png_get_uint_32(buf + 12);
0272a10d
VZ
820 int_x_red = (png_fixed_point)uint_x;
821 int_y_red = (png_fixed_point)uint_y;
822
970f6abe
VZ
823 uint_x = png_get_uint_32(buf + 16);
824 uint_y = png_get_uint_32(buf + 20);
0272a10d
VZ
825 int_x_green = (png_fixed_point)uint_x;
826 int_y_green = (png_fixed_point)uint_y;
827
970f6abe
VZ
828 uint_x = png_get_uint_32(buf + 24);
829 uint_y = png_get_uint_32(buf + 28);
0272a10d
VZ
830 int_x_blue = (png_fixed_point)uint_x;
831 int_y_blue = (png_fixed_point)uint_y;
832
833#ifdef PNG_FLOATING_POINT_SUPPORTED
834 white_x = (float)int_x_white / (float)100000.0;
835 white_y = (float)int_y_white / (float)100000.0;
836 red_x = (float)int_x_red / (float)100000.0;
837 red_y = (float)int_y_red / (float)100000.0;
838 green_x = (float)int_x_green / (float)100000.0;
839 green_y = (float)int_y_green / (float)100000.0;
840 blue_x = (float)int_x_blue / (float)100000.0;
841 blue_y = (float)int_y_blue / (float)100000.0;
842#endif
843
844#if defined(PNG_READ_sRGB_SUPPORTED)
845 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
846 {
847 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
848 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
849 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
850 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
851 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
852 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
853 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
854 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
855 {
856 png_warning(png_ptr,
857 "Ignoring incorrect cHRM value when sRGB is also present");
858#ifndef PNG_NO_CONSOLE_IO
859#ifdef PNG_FLOATING_POINT_SUPPORTED
970f6abe 860 fprintf(stderr, "wx=%f, wy=%f, rx=%f, ry=%f\n",
0272a10d 861 white_x, white_y, red_x, red_y);
970f6abe 862 fprintf(stderr, "gx=%f, gy=%f, bx=%f, by=%f\n",
0272a10d
VZ
863 green_x, green_y, blue_x, blue_y);
864#else
970f6abe 865 fprintf(stderr, "wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
0272a10d 866 int_x_white, int_y_white, int_x_red, int_y_red);
970f6abe 867 fprintf(stderr, "gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
0272a10d
VZ
868 int_x_green, int_y_green, int_x_blue, int_y_blue);
869#endif
870#endif /* PNG_NO_CONSOLE_IO */
871 }
0272a10d
VZ
872 return;
873 }
874#endif /* PNG_READ_sRGB_SUPPORTED */
875
876#ifdef PNG_FLOATING_POINT_SUPPORTED
877 png_set_cHRM(png_ptr, info_ptr,
878 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
879#endif
880#ifdef PNG_FIXED_POINT_SUPPORTED
881 png_set_cHRM_fixed(png_ptr, info_ptr,
882 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
883 int_y_green, int_x_blue, int_y_blue);
884#endif
0272a10d
VZ
885}
886#endif
887
888#if defined(PNG_READ_sRGB_SUPPORTED)
889void /* PRIVATE */
890png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
891{
892 int intent;
893 png_byte buf[1];
894
970f6abe 895 png_debug(1, "in png_handle_sRGB");
0272a10d
VZ
896
897 if (!(png_ptr->mode & PNG_HAVE_IHDR))
898 png_error(png_ptr, "Missing IHDR before sRGB");
899 else if (png_ptr->mode & PNG_HAVE_IDAT)
900 {
901 png_warning(png_ptr, "Invalid sRGB after IDAT");
902 png_crc_finish(png_ptr, length);
903 return;
904 }
905 else if (png_ptr->mode & PNG_HAVE_PLTE)
906 /* Should be an error, but we can cope with it */
907 png_warning(png_ptr, "Out of place sRGB chunk");
908
909 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
910 {
911 png_warning(png_ptr, "Duplicate sRGB chunk");
912 png_crc_finish(png_ptr, length);
913 return;
914 }
915
916 if (length != 1)
917 {
918 png_warning(png_ptr, "Incorrect sRGB chunk length");
919 png_crc_finish(png_ptr, length);
920 return;
921 }
922
923 png_crc_read(png_ptr, buf, 1);
924 if (png_crc_finish(png_ptr, 0))
925 return;
926
927 intent = buf[0];
928 /* check for bad intent */
929 if (intent >= PNG_sRGB_INTENT_LAST)
930 {
931 png_warning(png_ptr, "Unknown sRGB intent");
932 return;
933 }
934
935#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
936 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
937 {
938 png_fixed_point igamma;
939#ifdef PNG_FIXED_POINT_SUPPORTED
940 igamma=info_ptr->int_gamma;
941#else
942# ifdef PNG_FLOATING_POINT_SUPPORTED
943 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
944# endif
945#endif
946 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
947 {
948 png_warning(png_ptr,
949 "Ignoring incorrect gAMA value when sRGB is also present");
950#ifndef PNG_NO_CONSOLE_IO
951# ifdef PNG_FIXED_POINT_SUPPORTED
970f6abe
VZ
952 fprintf(stderr, "incorrect gamma=(%d/100000)\n",
953 (int)png_ptr->int_gamma);
0272a10d
VZ
954# else
955# ifdef PNG_FLOATING_POINT_SUPPORTED
970f6abe 956 fprintf(stderr, "incorrect gamma=%f\n", png_ptr->gamma);
0272a10d
VZ
957# endif
958# endif
959#endif
960 }
961 }
962#endif /* PNG_READ_gAMA_SUPPORTED */
963
964#ifdef PNG_READ_cHRM_SUPPORTED
965#ifdef PNG_FIXED_POINT_SUPPORTED
966 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
967 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
968 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
969 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
970 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
971 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
972 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
973 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
974 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
975 {
976 png_warning(png_ptr,
977 "Ignoring incorrect cHRM value when sRGB is also present");
978 }
979#endif /* PNG_FIXED_POINT_SUPPORTED */
980#endif /* PNG_READ_cHRM_SUPPORTED */
981
982 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
983}
984#endif /* PNG_READ_sRGB_SUPPORTED */
985
986#if defined(PNG_READ_iCCP_SUPPORTED)
987void /* PRIVATE */
988png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
989/* Note: this does not properly handle chunks that are > 64K under DOS */
990{
0272a10d
VZ
991 png_byte compression_type;
992 png_bytep pC;
993 png_charp profile;
994 png_uint_32 skip = 0;
995 png_uint_32 profile_size, profile_length;
996 png_size_t slength, prefix_length, data_length;
997
970f6abe 998 png_debug(1, "in png_handle_iCCP");
0272a10d
VZ
999
1000 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1001 png_error(png_ptr, "Missing IHDR before iCCP");
1002 else if (png_ptr->mode & PNG_HAVE_IDAT)
1003 {
1004 png_warning(png_ptr, "Invalid iCCP after IDAT");
1005 png_crc_finish(png_ptr, length);
1006 return;
1007 }
1008 else if (png_ptr->mode & PNG_HAVE_PLTE)
1009 /* Should be an error, but we can cope with it */
1010 png_warning(png_ptr, "Out of place iCCP chunk");
1011
1012 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1013 {
1014 png_warning(png_ptr, "Duplicate iCCP chunk");
1015 png_crc_finish(png_ptr, length);
1016 return;
1017 }
1018
1019#ifdef PNG_MAX_MALLOC_64K
1020 if (length > (png_uint_32)65535L)
1021 {
1022 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1023 skip = length - (png_uint_32)65535L;
1024 length = (png_uint_32)65535L;
1025 }
1026#endif
1027
970f6abe
VZ
1028 png_free(png_ptr, png_ptr->chunkdata);
1029 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
0272a10d 1030 slength = (png_size_t)length;
970f6abe 1031 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
1032
1033 if (png_crc_finish(png_ptr, skip))
1034 {
970f6abe
VZ
1035 png_free(png_ptr, png_ptr->chunkdata);
1036 png_ptr->chunkdata = NULL;
0272a10d
VZ
1037 return;
1038 }
1039
970f6abe 1040 png_ptr->chunkdata[slength] = 0x00;
0272a10d 1041
970f6abe 1042 for (profile = png_ptr->chunkdata; *profile; profile++)
0272a10d
VZ
1043 /* empty loop to find end of name */ ;
1044
1045 ++profile;
1046
1047 /* there should be at least one zero (the compression type byte)
1048 following the separator, and we should be on it */
970f6abe 1049 if ( profile >= png_ptr->chunkdata + slength - 1)
0272a10d 1050 {
970f6abe
VZ
1051 png_free(png_ptr, png_ptr->chunkdata);
1052 png_ptr->chunkdata = NULL;
0272a10d
VZ
1053 png_warning(png_ptr, "Malformed iCCP chunk");
1054 return;
1055 }
1056
1057 /* compression_type should always be zero */
1058 compression_type = *profile++;
1059 if (compression_type)
1060 {
1061 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
970f6abe 1062 compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
0272a10d
VZ
1063 wrote nonzero) */
1064 }
1065
970f6abe
VZ
1066 prefix_length = profile - png_ptr->chunkdata;
1067 png_decompress_chunk(png_ptr, compression_type,
1068 slength, prefix_length, &data_length);
0272a10d
VZ
1069
1070 profile_length = data_length - prefix_length;
1071
1072 if ( prefix_length > data_length || profile_length < 4)
1073 {
970f6abe
VZ
1074 png_free(png_ptr, png_ptr->chunkdata);
1075 png_ptr->chunkdata = NULL;
0272a10d
VZ
1076 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1077 return;
1078 }
1079
1080 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
970f6abe
VZ
1081 pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
1082 profile_size = ((*(pC ))<<24) |
1083 ((*(pC + 1))<<16) |
1084 ((*(pC + 2))<< 8) |
1085 ((*(pC + 3)) );
0272a10d 1086
970f6abe 1087 if (profile_size < profile_length)
0272a10d
VZ
1088 profile_length = profile_size;
1089
970f6abe 1090 if (profile_size > profile_length)
0272a10d 1091 {
970f6abe
VZ
1092 png_free(png_ptr, png_ptr->chunkdata);
1093 png_ptr->chunkdata = NULL;
0272a10d
VZ
1094 png_warning(png_ptr, "Ignoring truncated iCCP profile.");
1095 return;
1096 }
1097
970f6abe
VZ
1098 png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
1099 compression_type, png_ptr->chunkdata + prefix_length, profile_length);
1100 png_free(png_ptr, png_ptr->chunkdata);
1101 png_ptr->chunkdata = NULL;
0272a10d
VZ
1102}
1103#endif /* PNG_READ_iCCP_SUPPORTED */
1104
1105#if defined(PNG_READ_sPLT_SUPPORTED)
1106void /* PRIVATE */
1107png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1108/* Note: this does not properly handle chunks that are > 64K under DOS */
1109{
0272a10d
VZ
1110 png_bytep entry_start;
1111 png_sPLT_t new_palette;
1112#ifdef PNG_NO_POINTER_INDEXING
1113 png_sPLT_entryp pp;
1114#endif
1115 int data_length, entry_size, i;
1116 png_uint_32 skip = 0;
1117 png_size_t slength;
1118
970f6abe 1119 png_debug(1, "in png_handle_sPLT");
0272a10d
VZ
1120
1121 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1122 png_error(png_ptr, "Missing IHDR before sPLT");
1123 else if (png_ptr->mode & PNG_HAVE_IDAT)
1124 {
1125 png_warning(png_ptr, "Invalid sPLT after IDAT");
1126 png_crc_finish(png_ptr, length);
1127 return;
1128 }
1129
1130#ifdef PNG_MAX_MALLOC_64K
1131 if (length > (png_uint_32)65535L)
1132 {
1133 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1134 skip = length - (png_uint_32)65535L;
1135 length = (png_uint_32)65535L;
1136 }
1137#endif
1138
970f6abe
VZ
1139 png_free(png_ptr, png_ptr->chunkdata);
1140 png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
0272a10d 1141 slength = (png_size_t)length;
970f6abe 1142 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
1143
1144 if (png_crc_finish(png_ptr, skip))
1145 {
970f6abe
VZ
1146 png_free(png_ptr, png_ptr->chunkdata);
1147 png_ptr->chunkdata = NULL;
0272a10d
VZ
1148 return;
1149 }
1150
970f6abe 1151 png_ptr->chunkdata[slength] = 0x00;
0272a10d 1152
970f6abe 1153 for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start; entry_start++)
0272a10d
VZ
1154 /* empty loop to find end of name */ ;
1155 ++entry_start;
1156
1157 /* a sample depth should follow the separator, and we should be on it */
970f6abe 1158 if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
0272a10d 1159 {
970f6abe
VZ
1160 png_free(png_ptr, png_ptr->chunkdata);
1161 png_ptr->chunkdata = NULL;
0272a10d
VZ
1162 png_warning(png_ptr, "malformed sPLT chunk");
1163 return;
1164 }
1165
1166 new_palette.depth = *entry_start++;
1167 entry_size = (new_palette.depth == 8 ? 6 : 10);
970f6abe 1168 data_length = (slength - (entry_start - (png_bytep)png_ptr->chunkdata));
0272a10d
VZ
1169
1170 /* integrity-check the data length */
1171 if (data_length % entry_size)
1172 {
970f6abe
VZ
1173 png_free(png_ptr, png_ptr->chunkdata);
1174 png_ptr->chunkdata = NULL;
0272a10d
VZ
1175 png_warning(png_ptr, "sPLT chunk has bad length");
1176 return;
1177 }
1178
1179 new_palette.nentries = (png_int_32) ( data_length / entry_size);
970f6abe
VZ
1180 if ((png_uint_32) new_palette.nentries >
1181 (png_uint_32) (PNG_SIZE_MAX / png_sizeof(png_sPLT_entry)))
0272a10d
VZ
1182 {
1183 png_warning(png_ptr, "sPLT chunk too long");
1184 return;
1185 }
1186 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1187 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1188 if (new_palette.entries == NULL)
1189 {
1190 png_warning(png_ptr, "sPLT chunk requires too much memory");
1191 return;
1192 }
1193
1194#ifndef PNG_NO_POINTER_INDEXING
1195 for (i = 0; i < new_palette.nentries; i++)
1196 {
1197 png_sPLT_entryp pp = new_palette.entries + i;
1198
1199 if (new_palette.depth == 8)
1200 {
1201 pp->red = *entry_start++;
1202 pp->green = *entry_start++;
1203 pp->blue = *entry_start++;
1204 pp->alpha = *entry_start++;
1205 }
1206 else
1207 {
1208 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1209 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1210 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1211 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1212 }
1213 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1214 }
1215#else
1216 pp = new_palette.entries;
1217 for (i = 0; i < new_palette.nentries; i++)
1218 {
1219
1220 if (new_palette.depth == 8)
1221 {
1222 pp[i].red = *entry_start++;
1223 pp[i].green = *entry_start++;
1224 pp[i].blue = *entry_start++;
1225 pp[i].alpha = *entry_start++;
1226 }
1227 else
1228 {
1229 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1230 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1231 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1232 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1233 }
1234 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1235 }
1236#endif
1237
1238 /* discard all chunk data except the name and stash that */
970f6abe 1239 new_palette.name = png_ptr->chunkdata;
0272a10d
VZ
1240
1241 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1242
970f6abe
VZ
1243 png_free(png_ptr, png_ptr->chunkdata);
1244 png_ptr->chunkdata = NULL;
0272a10d
VZ
1245 png_free(png_ptr, new_palette.entries);
1246}
1247#endif /* PNG_READ_sPLT_SUPPORTED */
1248
1249#if defined(PNG_READ_tRNS_SUPPORTED)
1250void /* PRIVATE */
1251png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1252{
1253 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
0272a10d 1254
970f6abe 1255 png_debug(1, "in png_handle_tRNS");
0272a10d
VZ
1256
1257 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1258 png_error(png_ptr, "Missing IHDR before tRNS");
1259 else if (png_ptr->mode & PNG_HAVE_IDAT)
1260 {
1261 png_warning(png_ptr, "Invalid tRNS after IDAT");
1262 png_crc_finish(png_ptr, length);
1263 return;
1264 }
1265 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1266 {
1267 png_warning(png_ptr, "Duplicate tRNS chunk");
1268 png_crc_finish(png_ptr, length);
1269 return;
1270 }
1271
1272 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1273 {
1274 png_byte buf[2];
1275
1276 if (length != 2)
1277 {
1278 png_warning(png_ptr, "Incorrect tRNS chunk length");
1279 png_crc_finish(png_ptr, length);
1280 return;
1281 }
1282
1283 png_crc_read(png_ptr, buf, 2);
1284 png_ptr->num_trans = 1;
970f6abe 1285 png_ptr->trans_values.gray = png_get_uint_16(buf);
0272a10d
VZ
1286 }
1287 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1288 {
1289 png_byte buf[6];
1290
1291 if (length != 6)
1292 {
1293 png_warning(png_ptr, "Incorrect tRNS chunk length");
1294 png_crc_finish(png_ptr, length);
1295 return;
1296 }
1297 png_crc_read(png_ptr, buf, (png_size_t)length);
1298 png_ptr->num_trans = 1;
970f6abe
VZ
1299 png_ptr->trans_values.red = png_get_uint_16(buf);
1300 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
1301 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
0272a10d
VZ
1302 }
1303 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1304 {
1305 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1306 {
1307 /* Should be an error, but we can cope with it. */
1308 png_warning(png_ptr, "Missing PLTE before tRNS");
1309 }
1310 if (length > (png_uint_32)png_ptr->num_palette ||
1311 length > PNG_MAX_PALETTE_LENGTH)
1312 {
1313 png_warning(png_ptr, "Incorrect tRNS chunk length");
1314 png_crc_finish(png_ptr, length);
1315 return;
1316 }
1317 if (length == 0)
1318 {
1319 png_warning(png_ptr, "Zero length tRNS chunk");
1320 png_crc_finish(png_ptr, length);
1321 return;
1322 }
1323 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1324 png_ptr->num_trans = (png_uint_16)length;
1325 }
1326 else
1327 {
1328 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1329 png_crc_finish(png_ptr, length);
1330 return;
1331 }
1332
1333 if (png_crc_finish(png_ptr, 0))
1334 {
1335 png_ptr->num_trans = 0;
1336 return;
1337 }
1338
1339 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1340 &(png_ptr->trans_values));
1341}
1342#endif
1343
1344#if defined(PNG_READ_bKGD_SUPPORTED)
1345void /* PRIVATE */
1346png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1347{
1348 png_size_t truelen;
1349 png_byte buf[6];
1350
970f6abe 1351 png_debug(1, "in png_handle_bKGD");
0272a10d
VZ
1352
1353 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1354 png_error(png_ptr, "Missing IHDR before bKGD");
1355 else if (png_ptr->mode & PNG_HAVE_IDAT)
1356 {
1357 png_warning(png_ptr, "Invalid bKGD after IDAT");
1358 png_crc_finish(png_ptr, length);
1359 return;
1360 }
1361 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1362 !(png_ptr->mode & PNG_HAVE_PLTE))
1363 {
1364 png_warning(png_ptr, "Missing PLTE before bKGD");
1365 png_crc_finish(png_ptr, length);
1366 return;
1367 }
1368 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1369 {
1370 png_warning(png_ptr, "Duplicate bKGD chunk");
1371 png_crc_finish(png_ptr, length);
1372 return;
1373 }
1374
1375 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1376 truelen = 1;
1377 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1378 truelen = 6;
1379 else
1380 truelen = 2;
1381
1382 if (length != truelen)
1383 {
1384 png_warning(png_ptr, "Incorrect bKGD chunk length");
1385 png_crc_finish(png_ptr, length);
1386 return;
1387 }
1388
1389 png_crc_read(png_ptr, buf, truelen);
1390 if (png_crc_finish(png_ptr, 0))
1391 return;
1392
1393 /* We convert the index value into RGB components so that we can allow
1394 * arbitrary RGB values for background when we have transparency, and
1395 * so it is easy to determine the RGB values of the background color
1396 * from the info_ptr struct. */
1397 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1398 {
1399 png_ptr->background.index = buf[0];
970f6abe 1400 if (info_ptr && info_ptr->num_palette)
0272a10d 1401 {
970f6abe 1402 if (buf[0] >= info_ptr->num_palette)
0272a10d
VZ
1403 {
1404 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1405 return;
1406 }
1407 png_ptr->background.red =
1408 (png_uint_16)png_ptr->palette[buf[0]].red;
1409 png_ptr->background.green =
1410 (png_uint_16)png_ptr->palette[buf[0]].green;
1411 png_ptr->background.blue =
1412 (png_uint_16)png_ptr->palette[buf[0]].blue;
1413 }
1414 }
1415 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1416 {
1417 png_ptr->background.red =
1418 png_ptr->background.green =
1419 png_ptr->background.blue =
1420 png_ptr->background.gray = png_get_uint_16(buf);
1421 }
1422 else
1423 {
1424 png_ptr->background.red = png_get_uint_16(buf);
1425 png_ptr->background.green = png_get_uint_16(buf + 2);
1426 png_ptr->background.blue = png_get_uint_16(buf + 4);
1427 }
1428
1429 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1430}
1431#endif
1432
1433#if defined(PNG_READ_hIST_SUPPORTED)
1434void /* PRIVATE */
1435png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1436{
1437 unsigned int num, i;
1438 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1439
970f6abe 1440 png_debug(1, "in png_handle_hIST");
0272a10d
VZ
1441
1442 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1443 png_error(png_ptr, "Missing IHDR before hIST");
1444 else if (png_ptr->mode & PNG_HAVE_IDAT)
1445 {
1446 png_warning(png_ptr, "Invalid hIST after IDAT");
1447 png_crc_finish(png_ptr, length);
1448 return;
1449 }
1450 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1451 {
1452 png_warning(png_ptr, "Missing PLTE before hIST");
1453 png_crc_finish(png_ptr, length);
1454 return;
1455 }
1456 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1457 {
1458 png_warning(png_ptr, "Duplicate hIST chunk");
1459 png_crc_finish(png_ptr, length);
1460 return;
1461 }
1462
1463 num = length / 2 ;
1464 if (num != (unsigned int) png_ptr->num_palette || num >
1465 (unsigned int) PNG_MAX_PALETTE_LENGTH)
1466 {
1467 png_warning(png_ptr, "Incorrect hIST chunk length");
1468 png_crc_finish(png_ptr, length);
1469 return;
1470 }
1471
1472 for (i = 0; i < num; i++)
1473 {
1474 png_byte buf[2];
1475
1476 png_crc_read(png_ptr, buf, 2);
1477 readbuf[i] = png_get_uint_16(buf);
1478 }
1479
1480 if (png_crc_finish(png_ptr, 0))
1481 return;
1482
1483 png_set_hIST(png_ptr, info_ptr, readbuf);
1484}
1485#endif
1486
1487#if defined(PNG_READ_pHYs_SUPPORTED)
1488void /* PRIVATE */
1489png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1490{
1491 png_byte buf[9];
1492 png_uint_32 res_x, res_y;
1493 int unit_type;
1494
970f6abe 1495 png_debug(1, "in png_handle_pHYs");
0272a10d
VZ
1496
1497 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1498 png_error(png_ptr, "Missing IHDR before pHYs");
1499 else if (png_ptr->mode & PNG_HAVE_IDAT)
1500 {
1501 png_warning(png_ptr, "Invalid pHYs after IDAT");
1502 png_crc_finish(png_ptr, length);
1503 return;
1504 }
1505 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1506 {
1507 png_warning(png_ptr, "Duplicate pHYs chunk");
1508 png_crc_finish(png_ptr, length);
1509 return;
1510 }
1511
1512 if (length != 9)
1513 {
1514 png_warning(png_ptr, "Incorrect pHYs chunk length");
1515 png_crc_finish(png_ptr, length);
1516 return;
1517 }
1518
1519 png_crc_read(png_ptr, buf, 9);
1520 if (png_crc_finish(png_ptr, 0))
1521 return;
1522
1523 res_x = png_get_uint_32(buf);
1524 res_y = png_get_uint_32(buf + 4);
1525 unit_type = buf[8];
1526 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1527}
1528#endif
1529
1530#if defined(PNG_READ_oFFs_SUPPORTED)
1531void /* PRIVATE */
1532png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1533{
1534 png_byte buf[9];
1535 png_int_32 offset_x, offset_y;
1536 int unit_type;
1537
970f6abe 1538 png_debug(1, "in png_handle_oFFs");
0272a10d
VZ
1539
1540 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1541 png_error(png_ptr, "Missing IHDR before oFFs");
1542 else if (png_ptr->mode & PNG_HAVE_IDAT)
1543 {
1544 png_warning(png_ptr, "Invalid oFFs after IDAT");
1545 png_crc_finish(png_ptr, length);
1546 return;
1547 }
1548 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1549 {
1550 png_warning(png_ptr, "Duplicate oFFs chunk");
1551 png_crc_finish(png_ptr, length);
1552 return;
1553 }
1554
1555 if (length != 9)
1556 {
1557 png_warning(png_ptr, "Incorrect oFFs chunk length");
1558 png_crc_finish(png_ptr, length);
1559 return;
1560 }
1561
1562 png_crc_read(png_ptr, buf, 9);
1563 if (png_crc_finish(png_ptr, 0))
1564 return;
1565
1566 offset_x = png_get_int_32(buf);
1567 offset_y = png_get_int_32(buf + 4);
1568 unit_type = buf[8];
1569 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1570}
1571#endif
1572
1573#if defined(PNG_READ_pCAL_SUPPORTED)
1574/* read the pCAL chunk (described in the PNG Extensions document) */
1575void /* PRIVATE */
1576png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1577{
0272a10d
VZ
1578 png_int_32 X0, X1;
1579 png_byte type, nparams;
1580 png_charp buf, units, endptr;
1581 png_charpp params;
1582 png_size_t slength;
1583 int i;
1584
970f6abe 1585 png_debug(1, "in png_handle_pCAL");
0272a10d
VZ
1586
1587 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1588 png_error(png_ptr, "Missing IHDR before pCAL");
1589 else if (png_ptr->mode & PNG_HAVE_IDAT)
1590 {
1591 png_warning(png_ptr, "Invalid pCAL after IDAT");
1592 png_crc_finish(png_ptr, length);
1593 return;
1594 }
1595 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1596 {
1597 png_warning(png_ptr, "Duplicate pCAL chunk");
1598 png_crc_finish(png_ptr, length);
1599 return;
1600 }
1601
970f6abe 1602 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)",
0272a10d 1603 length + 1);
970f6abe
VZ
1604 png_free(png_ptr, png_ptr->chunkdata);
1605 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1606 if (png_ptr->chunkdata == NULL)
0272a10d
VZ
1607 {
1608 png_warning(png_ptr, "No memory for pCAL purpose.");
1609 return;
1610 }
1611 slength = (png_size_t)length;
970f6abe 1612 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
1613
1614 if (png_crc_finish(png_ptr, 0))
1615 {
970f6abe
VZ
1616 png_free(png_ptr, png_ptr->chunkdata);
1617 png_ptr->chunkdata = NULL;
0272a10d
VZ
1618 return;
1619 }
1620
970f6abe 1621 png_ptr->chunkdata[slength] = 0x00; /* null terminate the last string */
0272a10d 1622
970f6abe
VZ
1623 png_debug(3, "Finding end of pCAL purpose string");
1624 for (buf = png_ptr->chunkdata; *buf; buf++)
0272a10d
VZ
1625 /* empty loop */ ;
1626
970f6abe 1627 endptr = png_ptr->chunkdata + slength;
0272a10d
VZ
1628
1629 /* We need to have at least 12 bytes after the purpose string
1630 in order to get the parameter information. */
1631 if (endptr <= buf + 12)
1632 {
1633 png_warning(png_ptr, "Invalid pCAL data");
970f6abe
VZ
1634 png_free(png_ptr, png_ptr->chunkdata);
1635 png_ptr->chunkdata = NULL;
0272a10d
VZ
1636 return;
1637 }
1638
970f6abe 1639 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units");
0272a10d
VZ
1640 X0 = png_get_int_32((png_bytep)buf+1);
1641 X1 = png_get_int_32((png_bytep)buf+5);
1642 type = buf[9];
1643 nparams = buf[10];
1644 units = buf + 11;
1645
970f6abe 1646 png_debug(3, "Checking pCAL equation type and number of parameters");
0272a10d
VZ
1647 /* Check that we have the right number of parameters for known
1648 equation types. */
1649 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1650 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1651 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1652 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1653 {
1654 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
970f6abe
VZ
1655 png_free(png_ptr, png_ptr->chunkdata);
1656 png_ptr->chunkdata = NULL;
0272a10d
VZ
1657 return;
1658 }
1659 else if (type >= PNG_EQUATION_LAST)
1660 {
1661 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1662 }
1663
1664 for (buf = units; *buf; buf++)
1665 /* Empty loop to move past the units string. */ ;
1666
970f6abe
VZ
1667 png_debug(3, "Allocating pCAL parameters array");
1668 params = (png_charpp)png_malloc_warn(png_ptr,
1669 (png_uint_32)(nparams * png_sizeof(png_charp))) ;
0272a10d
VZ
1670 if (params == NULL)
1671 {
970f6abe
VZ
1672 png_free(png_ptr, png_ptr->chunkdata);
1673 png_ptr->chunkdata = NULL;
0272a10d
VZ
1674 png_warning(png_ptr, "No memory for pCAL params.");
1675 return;
1676 }
1677
1678 /* Get pointers to the start of each parameter string. */
1679 for (i = 0; i < (int)nparams; i++)
1680 {
1681 buf++; /* Skip the null string terminator from previous parameter. */
1682
970f6abe
VZ
1683 png_debug1(3, "Reading pCAL parameter %d", i);
1684 for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
0272a10d
VZ
1685 /* Empty loop to move past each parameter string */ ;
1686
1687 /* Make sure we haven't run out of data yet */
1688 if (buf > endptr)
1689 {
1690 png_warning(png_ptr, "Invalid pCAL data");
970f6abe
VZ
1691 png_free(png_ptr, png_ptr->chunkdata);
1692 png_ptr->chunkdata = NULL;
0272a10d
VZ
1693 png_free(png_ptr, params);
1694 return;
1695 }
1696 }
1697
970f6abe 1698 png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
0272a10d
VZ
1699 units, params);
1700
970f6abe
VZ
1701 png_free(png_ptr, png_ptr->chunkdata);
1702 png_ptr->chunkdata = NULL;
0272a10d
VZ
1703 png_free(png_ptr, params);
1704}
1705#endif
1706
1707#if defined(PNG_READ_sCAL_SUPPORTED)
1708/* read the sCAL chunk */
1709void /* PRIVATE */
1710png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1711{
970f6abe 1712 png_charp ep;
0272a10d
VZ
1713#ifdef PNG_FLOATING_POINT_SUPPORTED
1714 double width, height;
1715 png_charp vp;
1716#else
1717#ifdef PNG_FIXED_POINT_SUPPORTED
1718 png_charp swidth, sheight;
1719#endif
1720#endif
1721 png_size_t slength;
1722
970f6abe 1723 png_debug(1, "in png_handle_sCAL");
0272a10d
VZ
1724
1725 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1726 png_error(png_ptr, "Missing IHDR before sCAL");
1727 else if (png_ptr->mode & PNG_HAVE_IDAT)
1728 {
1729 png_warning(png_ptr, "Invalid sCAL after IDAT");
1730 png_crc_finish(png_ptr, length);
1731 return;
1732 }
1733 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1734 {
1735 png_warning(png_ptr, "Duplicate sCAL chunk");
1736 png_crc_finish(png_ptr, length);
1737 return;
1738 }
1739
970f6abe 1740 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)",
0272a10d 1741 length + 1);
970f6abe
VZ
1742 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1743 if (png_ptr->chunkdata == NULL)
1744 {
1745 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
1746 return;
1747 }
0272a10d 1748 slength = (png_size_t)length;
970f6abe 1749 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
1750
1751 if (png_crc_finish(png_ptr, 0))
1752 {
970f6abe
VZ
1753 png_free(png_ptr, png_ptr->chunkdata);
1754 png_ptr->chunkdata = NULL;
0272a10d
VZ
1755 return;
1756 }
1757
970f6abe 1758 png_ptr->chunkdata[slength] = 0x00; /* null terminate the last string */
0272a10d 1759
970f6abe 1760 ep = png_ptr->chunkdata + 1; /* skip unit byte */
0272a10d
VZ
1761
1762#ifdef PNG_FLOATING_POINT_SUPPORTED
1763 width = png_strtod(png_ptr, ep, &vp);
1764 if (*vp)
1765 {
970f6abe
VZ
1766 png_warning(png_ptr, "malformed width string in sCAL chunk");
1767 return;
0272a10d
VZ
1768 }
1769#else
1770#ifdef PNG_FIXED_POINT_SUPPORTED
1771 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1772 if (swidth == NULL)
970f6abe
VZ
1773 {
1774 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
1775 return;
1776 }
0272a10d
VZ
1777 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1778#endif
1779#endif
1780
970f6abe 1781 for (ep = png_ptr->chunkdata; *ep; ep++)
0272a10d
VZ
1782 /* empty loop */ ;
1783 ep++;
1784
970f6abe
VZ
1785 if (png_ptr->chunkdata + slength < ep)
1786 {
1787 png_warning(png_ptr, "Truncated sCAL chunk");
1788#if defined(PNG_FIXED_POINT_SUPPORTED) && \
1789 !defined(PNG_FLOATING_POINT_SUPPORTED)
1790 png_free(png_ptr, swidth);
1791#endif
1792 png_free(png_ptr, png_ptr->chunkdata);
1793 png_ptr->chunkdata = NULL;
1794 return;
1795 }
1796
0272a10d
VZ
1797#ifdef PNG_FLOATING_POINT_SUPPORTED
1798 height = png_strtod(png_ptr, ep, &vp);
1799 if (*vp)
1800 {
970f6abe
VZ
1801 png_warning(png_ptr, "malformed height string in sCAL chunk");
1802 return;
0272a10d
VZ
1803 }
1804#else
1805#ifdef PNG_FIXED_POINT_SUPPORTED
1806 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
970f6abe
VZ
1807 if (sheight == NULL)
1808 {
1809 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
1810 return;
1811 }
0272a10d
VZ
1812 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1813#endif
1814#endif
1815
970f6abe 1816 if (png_ptr->chunkdata + slength < ep
0272a10d
VZ
1817#ifdef PNG_FLOATING_POINT_SUPPORTED
1818 || width <= 0. || height <= 0.
1819#endif
1820 )
1821 {
1822 png_warning(png_ptr, "Invalid sCAL data");
970f6abe
VZ
1823 png_free(png_ptr, png_ptr->chunkdata);
1824 png_ptr->chunkdata = NULL;
0272a10d
VZ
1825#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1826 png_free(png_ptr, swidth);
1827 png_free(png_ptr, sheight);
1828#endif
1829 return;
1830 }
1831
1832
1833#ifdef PNG_FLOATING_POINT_SUPPORTED
970f6abe 1834 png_set_sCAL(png_ptr, info_ptr, png_ptr->chunkdata[0], width, height);
0272a10d
VZ
1835#else
1836#ifdef PNG_FIXED_POINT_SUPPORTED
970f6abe 1837 png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0], swidth, sheight);
0272a10d
VZ
1838#endif
1839#endif
1840
970f6abe
VZ
1841 png_free(png_ptr, png_ptr->chunkdata);
1842 png_ptr->chunkdata = NULL;
0272a10d
VZ
1843#if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1844 png_free(png_ptr, swidth);
1845 png_free(png_ptr, sheight);
1846#endif
1847}
1848#endif
1849
1850#if defined(PNG_READ_tIME_SUPPORTED)
1851void /* PRIVATE */
1852png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1853{
1854 png_byte buf[7];
1855 png_time mod_time;
1856
970f6abe 1857 png_debug(1, "in png_handle_tIME");
0272a10d
VZ
1858
1859 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1860 png_error(png_ptr, "Out of place tIME chunk");
1861 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1862 {
1863 png_warning(png_ptr, "Duplicate tIME chunk");
1864 png_crc_finish(png_ptr, length);
1865 return;
1866 }
1867
1868 if (png_ptr->mode & PNG_HAVE_IDAT)
1869 png_ptr->mode |= PNG_AFTER_IDAT;
1870
1871 if (length != 7)
1872 {
1873 png_warning(png_ptr, "Incorrect tIME chunk length");
1874 png_crc_finish(png_ptr, length);
1875 return;
1876 }
1877
1878 png_crc_read(png_ptr, buf, 7);
1879 if (png_crc_finish(png_ptr, 0))
1880 return;
1881
1882 mod_time.second = buf[6];
1883 mod_time.minute = buf[5];
1884 mod_time.hour = buf[4];
1885 mod_time.day = buf[3];
1886 mod_time.month = buf[2];
1887 mod_time.year = png_get_uint_16(buf);
1888
1889 png_set_tIME(png_ptr, info_ptr, &mod_time);
1890}
1891#endif
1892
1893#if defined(PNG_READ_tEXt_SUPPORTED)
1894/* Note: this does not properly handle chunks that are > 64K under DOS */
1895void /* PRIVATE */
1896png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1897{
1898 png_textp text_ptr;
1899 png_charp key;
1900 png_charp text;
1901 png_uint_32 skip = 0;
1902 png_size_t slength;
1903 int ret;
1904
970f6abe 1905 png_debug(1, "in png_handle_tEXt");
0272a10d
VZ
1906
1907 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1908 png_error(png_ptr, "Missing IHDR before tEXt");
1909
1910 if (png_ptr->mode & PNG_HAVE_IDAT)
1911 png_ptr->mode |= PNG_AFTER_IDAT;
1912
1913#ifdef PNG_MAX_MALLOC_64K
1914 if (length > (png_uint_32)65535L)
1915 {
1916 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1917 skip = length - (png_uint_32)65535L;
1918 length = (png_uint_32)65535L;
1919 }
1920#endif
1921
970f6abe
VZ
1922 png_free(png_ptr, png_ptr->chunkdata);
1923 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1924 if (png_ptr->chunkdata == NULL)
0272a10d
VZ
1925 {
1926 png_warning(png_ptr, "No memory to process text chunk.");
1927 return;
1928 }
1929 slength = (png_size_t)length;
970f6abe 1930 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
1931
1932 if (png_crc_finish(png_ptr, skip))
1933 {
970f6abe
VZ
1934 png_free(png_ptr, png_ptr->chunkdata);
1935 png_ptr->chunkdata = NULL;
0272a10d
VZ
1936 return;
1937 }
1938
970f6abe 1939 key = png_ptr->chunkdata;
0272a10d
VZ
1940 key[slength] = 0x00;
1941
1942 for (text = key; *text; text++)
1943 /* empty loop to find end of key */ ;
1944
1945 if (text != key + slength)
1946 text++;
1947
1948 text_ptr = (png_textp)png_malloc_warn(png_ptr,
1949 (png_uint_32)png_sizeof(png_text));
1950 if (text_ptr == NULL)
1951 {
1952 png_warning(png_ptr, "Not enough memory to process text chunk.");
970f6abe
VZ
1953 png_free(png_ptr, png_ptr->chunkdata);
1954 png_ptr->chunkdata = NULL;
0272a10d
VZ
1955 return;
1956 }
1957 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1958 text_ptr->key = key;
1959#ifdef PNG_iTXt_SUPPORTED
1960 text_ptr->lang = NULL;
1961 text_ptr->lang_key = NULL;
1962 text_ptr->itxt_length = 0;
1963#endif
1964 text_ptr->text = text;
1965 text_ptr->text_length = png_strlen(text);
1966
970f6abe 1967 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
0272a10d 1968
970f6abe
VZ
1969 png_free(png_ptr, png_ptr->chunkdata);
1970 png_ptr->chunkdata = NULL;
0272a10d
VZ
1971 png_free(png_ptr, text_ptr);
1972 if (ret)
1973 png_warning(png_ptr, "Insufficient memory to process text chunk.");
1974}
1975#endif
1976
1977#if defined(PNG_READ_zTXt_SUPPORTED)
1978/* note: this does not correctly handle chunks that are > 64K under DOS */
1979void /* PRIVATE */
1980png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1981{
1982 png_textp text_ptr;
0272a10d
VZ
1983 png_charp text;
1984 int comp_type;
1985 int ret;
1986 png_size_t slength, prefix_len, data_len;
1987
970f6abe 1988 png_debug(1, "in png_handle_zTXt");
0272a10d
VZ
1989 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1990 png_error(png_ptr, "Missing IHDR before zTXt");
1991
1992 if (png_ptr->mode & PNG_HAVE_IDAT)
1993 png_ptr->mode |= PNG_AFTER_IDAT;
1994
1995#ifdef PNG_MAX_MALLOC_64K
1996 /* We will no doubt have problems with chunks even half this size, but
1997 there is no hard and fast rule to tell us where to stop. */
1998 if (length > (png_uint_32)65535L)
1999 {
970f6abe 2000 png_warning(png_ptr, "zTXt chunk too large to fit in memory");
0272a10d
VZ
2001 png_crc_finish(png_ptr, length);
2002 return;
2003 }
2004#endif
2005
970f6abe
VZ
2006 png_free(png_ptr, png_ptr->chunkdata);
2007 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2008 if (png_ptr->chunkdata == NULL)
0272a10d 2009 {
970f6abe 2010 png_warning(png_ptr, "Out of memory processing zTXt chunk.");
0272a10d
VZ
2011 return;
2012 }
2013 slength = (png_size_t)length;
970f6abe 2014 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
2015 if (png_crc_finish(png_ptr, 0))
2016 {
970f6abe
VZ
2017 png_free(png_ptr, png_ptr->chunkdata);
2018 png_ptr->chunkdata = NULL;
0272a10d
VZ
2019 return;
2020 }
2021
970f6abe 2022 png_ptr->chunkdata[slength] = 0x00;
0272a10d 2023
970f6abe 2024 for (text = png_ptr->chunkdata; *text; text++)
0272a10d
VZ
2025 /* empty loop */ ;
2026
2027 /* zTXt must have some text after the chunkdataword */
970f6abe 2028 if (text >= png_ptr->chunkdata + slength - 2)
0272a10d
VZ
2029 {
2030 png_warning(png_ptr, "Truncated zTXt chunk");
970f6abe
VZ
2031 png_free(png_ptr, png_ptr->chunkdata);
2032 png_ptr->chunkdata = NULL;
0272a10d
VZ
2033 return;
2034 }
2035 else
2036 {
2037 comp_type = *(++text);
2038 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2039 {
2040 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2041 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2042 }
2043 text++; /* skip the compression_method byte */
2044 }
970f6abe 2045 prefix_len = text - png_ptr->chunkdata;
0272a10d 2046
970f6abe
VZ
2047 png_decompress_chunk(png_ptr, comp_type,
2048 (png_size_t)length, prefix_len, &data_len);
0272a10d
VZ
2049
2050 text_ptr = (png_textp)png_malloc_warn(png_ptr,
970f6abe 2051 (png_uint_32)png_sizeof(png_text));
0272a10d
VZ
2052 if (text_ptr == NULL)
2053 {
970f6abe
VZ
2054 png_warning(png_ptr, "Not enough memory to process zTXt chunk.");
2055 png_free(png_ptr, png_ptr->chunkdata);
2056 png_ptr->chunkdata = NULL;
0272a10d
VZ
2057 return;
2058 }
2059 text_ptr->compression = comp_type;
970f6abe 2060 text_ptr->key = png_ptr->chunkdata;
0272a10d
VZ
2061#ifdef PNG_iTXt_SUPPORTED
2062 text_ptr->lang = NULL;
2063 text_ptr->lang_key = NULL;
2064 text_ptr->itxt_length = 0;
2065#endif
970f6abe 2066 text_ptr->text = png_ptr->chunkdata + prefix_len;
0272a10d
VZ
2067 text_ptr->text_length = data_len;
2068
970f6abe 2069 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
0272a10d
VZ
2070
2071 png_free(png_ptr, text_ptr);
970f6abe
VZ
2072 png_free(png_ptr, png_ptr->chunkdata);
2073 png_ptr->chunkdata = NULL;
0272a10d
VZ
2074 if (ret)
2075 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2076}
2077#endif
2078
2079#if defined(PNG_READ_iTXt_SUPPORTED)
2080/* note: this does not correctly handle chunks that are > 64K under DOS */
2081void /* PRIVATE */
2082png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2083{
2084 png_textp text_ptr;
0272a10d
VZ
2085 png_charp key, lang, text, lang_key;
2086 int comp_flag;
2087 int comp_type = 0;
2088 int ret;
2089 png_size_t slength, prefix_len, data_len;
2090
970f6abe 2091 png_debug(1, "in png_handle_iTXt");
0272a10d
VZ
2092
2093 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2094 png_error(png_ptr, "Missing IHDR before iTXt");
2095
2096 if (png_ptr->mode & PNG_HAVE_IDAT)
2097 png_ptr->mode |= PNG_AFTER_IDAT;
2098
2099#ifdef PNG_MAX_MALLOC_64K
2100 /* We will no doubt have problems with chunks even half this size, but
2101 there is no hard and fast rule to tell us where to stop. */
2102 if (length > (png_uint_32)65535L)
2103 {
970f6abe 2104 png_warning(png_ptr, "iTXt chunk too large to fit in memory");
0272a10d
VZ
2105 png_crc_finish(png_ptr, length);
2106 return;
2107 }
2108#endif
2109
970f6abe
VZ
2110 png_free(png_ptr, png_ptr->chunkdata);
2111 png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2112 if (png_ptr->chunkdata == NULL)
0272a10d
VZ
2113 {
2114 png_warning(png_ptr, "No memory to process iTXt chunk.");
2115 return;
2116 }
2117 slength = (png_size_t)length;
970f6abe 2118 png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
0272a10d
VZ
2119 if (png_crc_finish(png_ptr, 0))
2120 {
970f6abe
VZ
2121 png_free(png_ptr, png_ptr->chunkdata);
2122 png_ptr->chunkdata = NULL;
0272a10d
VZ
2123 return;
2124 }
2125
970f6abe 2126 png_ptr->chunkdata[slength] = 0x00;
0272a10d 2127
970f6abe 2128 for (lang = png_ptr->chunkdata; *lang; lang++)
0272a10d
VZ
2129 /* empty loop */ ;
2130 lang++; /* skip NUL separator */
2131
2132 /* iTXt must have a language tag (possibly empty), two compression bytes,
2133 translated keyword (possibly empty), and possibly some text after the
2134 keyword */
2135
970f6abe 2136 if (lang >= png_ptr->chunkdata + slength - 3)
0272a10d
VZ
2137 {
2138 png_warning(png_ptr, "Truncated iTXt chunk");
970f6abe
VZ
2139 png_free(png_ptr, png_ptr->chunkdata);
2140 png_ptr->chunkdata = NULL;
0272a10d
VZ
2141 return;
2142 }
2143 else
2144 {
2145 comp_flag = *lang++;
2146 comp_type = *lang++;
2147 }
2148
2149 for (lang_key = lang; *lang_key; lang_key++)
2150 /* empty loop */ ;
2151 lang_key++; /* skip NUL separator */
2152
970f6abe
VZ
2153 if (lang_key >= png_ptr->chunkdata + slength)
2154 {
2155 png_warning(png_ptr, "Truncated iTXt chunk");
2156 png_free(png_ptr, png_ptr->chunkdata);
2157 png_ptr->chunkdata = NULL;
2158 return;
2159 }
2160
0272a10d
VZ
2161 for (text = lang_key; *text; text++)
2162 /* empty loop */ ;
2163 text++; /* skip NUL separator */
970f6abe 2164 if (text >= png_ptr->chunkdata + slength)
0272a10d
VZ
2165 {
2166 png_warning(png_ptr, "Malformed iTXt chunk");
970f6abe
VZ
2167 png_free(png_ptr, png_ptr->chunkdata);
2168 png_ptr->chunkdata = NULL;
0272a10d
VZ
2169 return;
2170 }
2171
970f6abe 2172 prefix_len = text - png_ptr->chunkdata;
0272a10d 2173
970f6abe 2174 key=png_ptr->chunkdata;
0272a10d 2175 if (comp_flag)
970f6abe
VZ
2176 png_decompress_chunk(png_ptr, comp_type,
2177 (size_t)length, prefix_len, &data_len);
0272a10d 2178 else
970f6abe 2179 data_len = png_strlen(png_ptr->chunkdata + prefix_len);
0272a10d
VZ
2180 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2181 (png_uint_32)png_sizeof(png_text));
2182 if (text_ptr == NULL)
2183 {
970f6abe
VZ
2184 png_warning(png_ptr, "Not enough memory to process iTXt chunk.");
2185 png_free(png_ptr, png_ptr->chunkdata);
2186 png_ptr->chunkdata = NULL;
0272a10d
VZ
2187 return;
2188 }
2189 text_ptr->compression = (int)comp_flag + 1;
970f6abe
VZ
2190 text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
2191 text_ptr->lang = png_ptr->chunkdata + (lang - key);
0272a10d
VZ
2192 text_ptr->itxt_length = data_len;
2193 text_ptr->text_length = 0;
970f6abe
VZ
2194 text_ptr->key = png_ptr->chunkdata;
2195 text_ptr->text = png_ptr->chunkdata + prefix_len;
0272a10d 2196
970f6abe 2197 ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
0272a10d
VZ
2198
2199 png_free(png_ptr, text_ptr);
970f6abe
VZ
2200 png_free(png_ptr, png_ptr->chunkdata);
2201 png_ptr->chunkdata = NULL;
0272a10d
VZ
2202 if (ret)
2203 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
2204}
2205#endif
2206
2207/* This function is called when we haven't found a handler for a
2208 chunk. If there isn't a problem with the chunk itself (ie bad
2209 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2210 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2211 case it will be saved away to be written out later. */
2212void /* PRIVATE */
2213png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2214{
2215 png_uint_32 skip = 0;
2216
970f6abe 2217 png_debug(1, "in png_handle_unknown");
0272a10d
VZ
2218
2219 if (png_ptr->mode & PNG_HAVE_IDAT)
2220 {
2221#ifdef PNG_USE_LOCAL_ARRAYS
2222 PNG_CONST PNG_IDAT;
2223#endif
2224 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2225 png_ptr->mode |= PNG_AFTER_IDAT;
2226 }
2227
0272a10d
VZ
2228 if (!(png_ptr->chunk_name[0] & 0x20))
2229 {
2230#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
970f6abe 2231 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
0272a10d
VZ
2232 PNG_HANDLE_CHUNK_ALWAYS
2233#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2234 && png_ptr->read_user_chunk_fn == NULL
2235#endif
2236 )
2237#endif
2238 png_chunk_error(png_ptr, "unknown critical chunk");
2239 }
2240
2241#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2242 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
2243 (png_ptr->read_user_chunk_fn != NULL))
2244 {
2245#ifdef PNG_MAX_MALLOC_64K
2246 if (length > (png_uint_32)65535L)
2247 {
2248 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2249 skip = length - (png_uint_32)65535L;
2250 length = (png_uint_32)65535L;
2251 }
2252#endif
970f6abe
VZ
2253 png_memcpy((png_charp)png_ptr->unknown_chunk.name,
2254 (png_charp)png_ptr->chunk_name,
2255 png_sizeof(png_ptr->unknown_chunk.name));
2256 png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name)-1] = '\0';
0272a10d 2257 png_ptr->unknown_chunk.size = (png_size_t)length;
970f6abe
VZ
2258 if (length == 0)
2259 png_ptr->unknown_chunk.data = NULL;
2260 else
2261 {
2262 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2263 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2264 }
0272a10d 2265#if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
970f6abe 2266 if (png_ptr->read_user_chunk_fn != NULL)
0272a10d
VZ
2267 {
2268 /* callback to user unknown chunk handler */
2269 int ret;
2270 ret = (*(png_ptr->read_user_chunk_fn))
2271 (png_ptr, &png_ptr->unknown_chunk);
2272 if (ret < 0)
2273 png_chunk_error(png_ptr, "error in user chunk");
2274 if (ret == 0)
2275 {
2276 if (!(png_ptr->chunk_name[0] & 0x20))
970f6abe 2277 if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
0272a10d
VZ
2278 PNG_HANDLE_CHUNK_ALWAYS)
2279 png_chunk_error(png_ptr, "unknown critical chunk");
2280 png_set_unknown_chunks(png_ptr, info_ptr,
2281 &png_ptr->unknown_chunk, 1);
2282 }
2283 }
970f6abe 2284 else
0272a10d 2285#endif
970f6abe 2286 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
0272a10d
VZ
2287 png_free(png_ptr, png_ptr->unknown_chunk.data);
2288 png_ptr->unknown_chunk.data = NULL;
2289 }
2290 else
2291#endif
2292 skip = length;
2293
2294 png_crc_finish(png_ptr, skip);
2295
2296#if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2297 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
2298#endif
2299}
2300
2301/* This function is called to verify that a chunk name is valid.
2302 This function can't have the "critical chunk check" incorporated
2303 into it, since in the future we will need to be able to call user
2304 functions to handle unknown critical chunks after we check that
2305 the chunk name itself is valid. */
2306
2307#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
2308
2309void /* PRIVATE */
2310png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2311{
970f6abe 2312 png_debug(1, "in png_check_chunk_name");
0272a10d
VZ
2313 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2314 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2315 {
2316 png_chunk_error(png_ptr, "invalid chunk type");
2317 }
2318}
2319
2320/* Combines the row recently read in with the existing pixels in the
2321 row. This routine takes care of alpha and transparency if requested.
2322 This routine also handles the two methods of progressive display
2323 of interlaced images, depending on the mask value.
2324 The mask value describes which pixels are to be combined with
2325 the row. The pattern always repeats every 8 pixels, so just 8
2326 bits are needed. A one indicates the pixel is to be combined,
2327 a zero indicates the pixel is to be skipped. This is in addition
2328 to any alpha or transparency value associated with the pixel. If
2329 you want all pixels to be combined, pass 0xff (255) in mask. */
2330
2331void /* PRIVATE */
2332png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2333{
970f6abe 2334 png_debug(1, "in png_combine_row");
0272a10d
VZ
2335 if (mask == 0xff)
2336 {
2337 png_memcpy(row, png_ptr->row_buf + 1,
2338 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
2339 }
2340 else
2341 {
2342 switch (png_ptr->row_info.pixel_depth)
2343 {
2344 case 1:
2345 {
2346 png_bytep sp = png_ptr->row_buf + 1;
2347 png_bytep dp = row;
2348 int s_inc, s_start, s_end;
2349 int m = 0x80;
2350 int shift;
2351 png_uint_32 i;
2352 png_uint_32 row_width = png_ptr->width;
2353
2354#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2355 if (png_ptr->transformations & PNG_PACKSWAP)
2356 {
2357 s_start = 0;
2358 s_end = 7;
2359 s_inc = 1;
2360 }
2361 else
2362#endif
2363 {
2364 s_start = 7;
2365 s_end = 0;
2366 s_inc = -1;
2367 }
2368
2369 shift = s_start;
2370
2371 for (i = 0; i < row_width; i++)
2372 {
2373 if (m & mask)
2374 {
2375 int value;
2376
2377 value = (*sp >> shift) & 0x01;
2378 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2379 *dp |= (png_byte)(value << shift);
2380 }
2381
2382 if (shift == s_end)
2383 {
2384 shift = s_start;
2385 sp++;
2386 dp++;
2387 }
2388 else
2389 shift += s_inc;
2390
2391 if (m == 1)
2392 m = 0x80;
2393 else
2394 m >>= 1;
2395 }
2396 break;
2397 }
2398 case 2:
2399 {
2400 png_bytep sp = png_ptr->row_buf + 1;
2401 png_bytep dp = row;
2402 int s_start, s_end, s_inc;
2403 int m = 0x80;
2404 int shift;
2405 png_uint_32 i;
2406 png_uint_32 row_width = png_ptr->width;
2407 int value;
2408
2409#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2410 if (png_ptr->transformations & PNG_PACKSWAP)
2411 {
2412 s_start = 0;
2413 s_end = 6;
2414 s_inc = 2;
2415 }
2416 else
2417#endif
2418 {
2419 s_start = 6;
2420 s_end = 0;
2421 s_inc = -2;
2422 }
2423
2424 shift = s_start;
2425
2426 for (i = 0; i < row_width; i++)
2427 {
2428 if (m & mask)
2429 {
2430 value = (*sp >> shift) & 0x03;
2431 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2432 *dp |= (png_byte)(value << shift);
2433 }
2434
2435 if (shift == s_end)
2436 {
2437 shift = s_start;
2438 sp++;
2439 dp++;
2440 }
2441 else
2442 shift += s_inc;
2443 if (m == 1)
2444 m = 0x80;
2445 else
2446 m >>= 1;
2447 }
2448 break;
2449 }
2450 case 4:
2451 {
2452 png_bytep sp = png_ptr->row_buf + 1;
2453 png_bytep dp = row;
2454 int s_start, s_end, s_inc;
2455 int m = 0x80;
2456 int shift;
2457 png_uint_32 i;
2458 png_uint_32 row_width = png_ptr->width;
2459 int value;
2460
2461#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2462 if (png_ptr->transformations & PNG_PACKSWAP)
2463 {
2464 s_start = 0;
2465 s_end = 4;
2466 s_inc = 4;
2467 }
2468 else
2469#endif
2470 {
2471 s_start = 4;
2472 s_end = 0;
2473 s_inc = -4;
2474 }
2475 shift = s_start;
2476
2477 for (i = 0; i < row_width; i++)
2478 {
2479 if (m & mask)
2480 {
2481 value = (*sp >> shift) & 0xf;
2482 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2483 *dp |= (png_byte)(value << shift);
2484 }
2485
2486 if (shift == s_end)
2487 {
2488 shift = s_start;
2489 sp++;
2490 dp++;
2491 }
2492 else
2493 shift += s_inc;
2494 if (m == 1)
2495 m = 0x80;
2496 else
2497 m >>= 1;
2498 }
2499 break;
2500 }
2501 default:
2502 {
2503 png_bytep sp = png_ptr->row_buf + 1;
2504 png_bytep dp = row;
2505 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
2506 png_uint_32 i;
2507 png_uint_32 row_width = png_ptr->width;
2508 png_byte m = 0x80;
2509
2510
2511 for (i = 0; i < row_width; i++)
2512 {
2513 if (m & mask)
2514 {
2515 png_memcpy(dp, sp, pixel_bytes);
2516 }
2517
2518 sp += pixel_bytes;
2519 dp += pixel_bytes;
2520
2521 if (m == 1)
2522 m = 0x80;
2523 else
2524 m >>= 1;
2525 }
2526 break;
2527 }
2528 }
2529 }
2530}
2531
2532#ifdef PNG_READ_INTERLACING_SUPPORTED
2533/* OLD pre-1.0.9 interface:
2534void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
2535 png_uint_32 transformations)
2536 */
2537void /* PRIVATE */
2538png_do_read_interlace(png_structp png_ptr)
2539{
2540 png_row_infop row_info = &(png_ptr->row_info);
2541 png_bytep row = png_ptr->row_buf + 1;
2542 int pass = png_ptr->pass;
2543 png_uint_32 transformations = png_ptr->transformations;
2544#ifdef PNG_USE_LOCAL_ARRAYS
2545 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2546 /* offset to next interlace block */
2547 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2548#endif
2549
970f6abe 2550 png_debug(1, "in png_do_read_interlace");
0272a10d
VZ
2551 if (row != NULL && row_info != NULL)
2552 {
2553 png_uint_32 final_width;
2554
2555 final_width = row_info->width * png_pass_inc[pass];
2556
2557 switch (row_info->pixel_depth)
2558 {
2559 case 1:
2560 {
2561 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
2562 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
2563 int sshift, dshift;
2564 int s_start, s_end, s_inc;
2565 int jstop = png_pass_inc[pass];
2566 png_byte v;
2567 png_uint_32 i;
2568 int j;
2569
2570#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2571 if (transformations & PNG_PACKSWAP)
2572 {
2573 sshift = (int)((row_info->width + 7) & 0x07);
2574 dshift = (int)((final_width + 7) & 0x07);
2575 s_start = 7;
2576 s_end = 0;
2577 s_inc = -1;
2578 }
2579 else
2580#endif
2581 {
2582 sshift = 7 - (int)((row_info->width + 7) & 0x07);
2583 dshift = 7 - (int)((final_width + 7) & 0x07);
2584 s_start = 0;
2585 s_end = 7;
2586 s_inc = 1;
2587 }
2588
2589 for (i = 0; i < row_info->width; i++)
2590 {
2591 v = (png_byte)((*sp >> sshift) & 0x01);
2592 for (j = 0; j < jstop; j++)
2593 {
2594 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2595 *dp |= (png_byte)(v << dshift);
2596 if (dshift == s_end)
2597 {
2598 dshift = s_start;
2599 dp--;
2600 }
2601 else
2602 dshift += s_inc;
2603 }
2604 if (sshift == s_end)
2605 {
2606 sshift = s_start;
2607 sp--;
2608 }
2609 else
2610 sshift += s_inc;
2611 }
2612 break;
2613 }
2614 case 2:
2615 {
2616 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
2617 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
2618 int sshift, dshift;
2619 int s_start, s_end, s_inc;
2620 int jstop = png_pass_inc[pass];
2621 png_uint_32 i;
2622
2623#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2624 if (transformations & PNG_PACKSWAP)
2625 {
2626 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
2627 dshift = (int)(((final_width + 3) & 0x03) << 1);
2628 s_start = 6;
2629 s_end = 0;
2630 s_inc = -2;
2631 }
2632 else
2633#endif
2634 {
2635 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
2636 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
2637 s_start = 0;
2638 s_end = 6;
2639 s_inc = 2;
2640 }
2641
2642 for (i = 0; i < row_info->width; i++)
2643 {
2644 png_byte v;
2645 int j;
2646
2647 v = (png_byte)((*sp >> sshift) & 0x03);
2648 for (j = 0; j < jstop; j++)
2649 {
2650 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2651 *dp |= (png_byte)(v << dshift);
2652 if (dshift == s_end)
2653 {
2654 dshift = s_start;
2655 dp--;
2656 }
2657 else
2658 dshift += s_inc;
2659 }
2660 if (sshift == s_end)
2661 {
2662 sshift = s_start;
2663 sp--;
2664 }
2665 else
2666 sshift += s_inc;
2667 }
2668 break;
2669 }
2670 case 4:
2671 {
2672 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
2673 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
2674 int sshift, dshift;
2675 int s_start, s_end, s_inc;
2676 png_uint_32 i;
2677 int jstop = png_pass_inc[pass];
2678
2679#if defined(PNG_READ_PACKSWAP_SUPPORTED)
2680 if (transformations & PNG_PACKSWAP)
2681 {
2682 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
2683 dshift = (int)(((final_width + 1) & 0x01) << 2);
2684 s_start = 4;
2685 s_end = 0;
2686 s_inc = -4;
2687 }
2688 else
2689#endif
2690 {
2691 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
2692 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
2693 s_start = 0;
2694 s_end = 4;
2695 s_inc = 4;
2696 }
2697
2698 for (i = 0; i < row_info->width; i++)
2699 {
2700 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
2701 int j;
2702
2703 for (j = 0; j < jstop; j++)
2704 {
2705 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2706 *dp |= (png_byte)(v << dshift);
2707 if (dshift == s_end)
2708 {
2709 dshift = s_start;
2710 dp--;
2711 }
2712 else
2713 dshift += s_inc;
2714 }
2715 if (sshift == s_end)
2716 {
2717 sshift = s_start;
2718 sp--;
2719 }
2720 else
2721 sshift += s_inc;
2722 }
2723 break;
2724 }
2725 default:
2726 {
2727 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
2728 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
2729 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
2730
2731 int jstop = png_pass_inc[pass];
2732 png_uint_32 i;
2733
2734 for (i = 0; i < row_info->width; i++)
2735 {
2736 png_byte v[8];
2737 int j;
2738
2739 png_memcpy(v, sp, pixel_bytes);
2740 for (j = 0; j < jstop; j++)
2741 {
2742 png_memcpy(dp, v, pixel_bytes);
2743 dp -= pixel_bytes;
2744 }
2745 sp -= pixel_bytes;
2746 }
2747 break;
2748 }
2749 }
2750 row_info->width = final_width;
970f6abe 2751 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, final_width);
0272a10d
VZ
2752 }
2753#if !defined(PNG_READ_PACKSWAP_SUPPORTED)
2754 transformations = transformations; /* silence compiler warning */
2755#endif
2756}
2757#endif /* PNG_READ_INTERLACING_SUPPORTED */
2758
2759void /* PRIVATE */
2760png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
2761 png_bytep prev_row, int filter)
2762{
970f6abe
VZ
2763 png_debug(1, "in png_read_filter_row");
2764 png_debug2(2, "row = %lu, filter = %d", png_ptr->row_number, filter);
0272a10d
VZ
2765 switch (filter)
2766 {
2767 case PNG_FILTER_VALUE_NONE:
2768 break;
2769 case PNG_FILTER_VALUE_SUB:
2770 {
2771 png_uint_32 i;
2772 png_uint_32 istop = row_info->rowbytes;
2773 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2774 png_bytep rp = row + bpp;
2775 png_bytep lp = row;
2776
2777 for (i = bpp; i < istop; i++)
2778 {
2779 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
2780 rp++;
2781 }
2782 break;
2783 }
2784 case PNG_FILTER_VALUE_UP:
2785 {
2786 png_uint_32 i;
2787 png_uint_32 istop = row_info->rowbytes;
2788 png_bytep rp = row;
2789 png_bytep pp = prev_row;
2790
2791 for (i = 0; i < istop; i++)
2792 {
2793 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2794 rp++;
2795 }
2796 break;
2797 }
2798 case PNG_FILTER_VALUE_AVG:
2799 {
2800 png_uint_32 i;
2801 png_bytep rp = row;
2802 png_bytep pp = prev_row;
2803 png_bytep lp = row;
2804 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2805 png_uint_32 istop = row_info->rowbytes - bpp;
2806
2807 for (i = 0; i < bpp; i++)
2808 {
2809 *rp = (png_byte)(((int)(*rp) +
2810 ((int)(*pp++) / 2 )) & 0xff);
2811 rp++;
2812 }
2813
2814 for (i = 0; i < istop; i++)
2815 {
2816 *rp = (png_byte)(((int)(*rp) +
2817 (int)(*pp++ + *lp++) / 2 ) & 0xff);
2818 rp++;
2819 }
2820 break;
2821 }
2822 case PNG_FILTER_VALUE_PAETH:
2823 {
2824 png_uint_32 i;
2825 png_bytep rp = row;
2826 png_bytep pp = prev_row;
2827 png_bytep lp = row;
2828 png_bytep cp = prev_row;
2829 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
2830 png_uint_32 istop=row_info->rowbytes - bpp;
2831
2832 for (i = 0; i < bpp; i++)
2833 {
2834 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
2835 rp++;
2836 }
2837
2838 for (i = 0; i < istop; i++) /* use leftover rp,pp */
2839 {
2840 int a, b, c, pa, pb, pc, p;
2841
2842 a = *lp++;
2843 b = *pp++;
2844 c = *cp++;
2845
2846 p = b - c;
2847 pc = a - c;
2848
2849#ifdef PNG_USE_ABS
2850 pa = abs(p);
2851 pb = abs(pc);
2852 pc = abs(p + pc);
2853#else
2854 pa = p < 0 ? -p : p;
2855 pb = pc < 0 ? -pc : pc;
2856 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
2857#endif
2858
2859 /*
2860 if (pa <= pb && pa <= pc)
2861 p = a;
2862 else if (pb <= pc)
2863 p = b;
2864 else
2865 p = c;
2866 */
2867
970f6abe 2868 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
0272a10d
VZ
2869
2870 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
2871 rp++;
2872 }
2873 break;
2874 }
2875 default:
2876 png_warning(png_ptr, "Ignoring bad adaptive filter type");
970f6abe 2877 *row = 0;
0272a10d
VZ
2878 break;
2879 }
2880}
2881
2882void /* PRIVATE */
2883png_read_finish_row(png_structp png_ptr)
2884{
2885#ifdef PNG_USE_LOCAL_ARRAYS
970f6abe 2886#ifdef PNG_READ_INTERLACING_SUPPORTED
0272a10d
VZ
2887 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
2888
2889 /* start of interlace block */
2890 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2891
2892 /* offset to next interlace block */
2893 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2894
2895 /* start of interlace block in the y direction */
2896 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
2897
2898 /* offset to next interlace block in the y direction */
2899 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
970f6abe 2900#endif /* PNG_READ_INTERLACING_SUPPORTED */
0272a10d
VZ
2901#endif
2902
970f6abe 2903 png_debug(1, "in png_read_finish_row");
0272a10d
VZ
2904 png_ptr->row_number++;
2905 if (png_ptr->row_number < png_ptr->num_rows)
2906 return;
2907
970f6abe 2908#ifdef PNG_READ_INTERLACING_SUPPORTED
0272a10d
VZ
2909 if (png_ptr->interlaced)
2910 {
2911 png_ptr->row_number = 0;
2912 png_memset_check(png_ptr, png_ptr->prev_row, 0,
2913 png_ptr->rowbytes + 1);
2914 do
2915 {
2916 png_ptr->pass++;
2917 if (png_ptr->pass >= 7)
2918 break;
2919 png_ptr->iwidth = (png_ptr->width +
2920 png_pass_inc[png_ptr->pass] - 1 -
2921 png_pass_start[png_ptr->pass]) /
2922 png_pass_inc[png_ptr->pass];
2923
2924 png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
2925 png_ptr->iwidth) + 1;
2926
2927 if (!(png_ptr->transformations & PNG_INTERLACE))
2928 {
2929 png_ptr->num_rows = (png_ptr->height +
2930 png_pass_yinc[png_ptr->pass] - 1 -
2931 png_pass_ystart[png_ptr->pass]) /
2932 png_pass_yinc[png_ptr->pass];
2933 if (!(png_ptr->num_rows))
2934 continue;
2935 }
2936 else /* if (png_ptr->transformations & PNG_INTERLACE) */
2937 break;
2938 } while (png_ptr->iwidth == 0);
2939
2940 if (png_ptr->pass < 7)
2941 return;
2942 }
970f6abe 2943#endif /* PNG_READ_INTERLACING_SUPPORTED */
0272a10d
VZ
2944
2945 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
2946 {
2947#ifdef PNG_USE_LOCAL_ARRAYS
2948 PNG_CONST PNG_IDAT;
2949#endif
2950 char extra;
2951 int ret;
2952
2953 png_ptr->zstream.next_out = (Byte *)&extra;
2954 png_ptr->zstream.avail_out = (uInt)1;
970f6abe 2955 for (;;)
0272a10d
VZ
2956 {
2957 if (!(png_ptr->zstream.avail_in))
2958 {
2959 while (!png_ptr->idat_size)
2960 {
2961 png_byte chunk_length[4];
2962
2963 png_crc_finish(png_ptr, 0);
2964
2965 png_read_data(png_ptr, chunk_length, 4);
2966 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
2967 png_reset_crc(png_ptr);
2968 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
970f6abe 2969 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
0272a10d
VZ
2970 png_error(png_ptr, "Not enough image data");
2971
2972 }
2973 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2974 png_ptr->zstream.next_in = png_ptr->zbuf;
2975 if (png_ptr->zbuf_size > png_ptr->idat_size)
2976 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2977 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2978 png_ptr->idat_size -= png_ptr->zstream.avail_in;
2979 }
2980 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
2981 if (ret == Z_STREAM_END)
2982 {
2983 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
2984 png_ptr->idat_size)
2985 png_warning(png_ptr, "Extra compressed data");
2986 png_ptr->mode |= PNG_AFTER_IDAT;
2987 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2988 break;
2989 }
2990 if (ret != Z_OK)
2991 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
2992 "Decompression Error");
2993
2994 if (!(png_ptr->zstream.avail_out))
2995 {
2996 png_warning(png_ptr, "Extra compressed data.");
2997 png_ptr->mode |= PNG_AFTER_IDAT;
2998 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2999 break;
3000 }
3001
3002 }
3003 png_ptr->zstream.avail_out = 0;
3004 }
3005
3006 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
3007 png_warning(png_ptr, "Extra compression data");
3008
3009 inflateReset(&png_ptr->zstream);
3010
3011 png_ptr->mode |= PNG_AFTER_IDAT;
3012}
3013
3014void /* PRIVATE */
3015png_read_start_row(png_structp png_ptr)
3016{
3017#ifdef PNG_USE_LOCAL_ARRAYS
970f6abe 3018#ifdef PNG_READ_INTERLACING_SUPPORTED
0272a10d
VZ
3019 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3020
3021 /* start of interlace block */
3022 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3023
3024 /* offset to next interlace block */
3025 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3026
3027 /* start of interlace block in the y direction */
3028 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3029
3030 /* offset to next interlace block in the y direction */
3031 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
970f6abe 3032#endif
0272a10d
VZ
3033#endif
3034
3035 int max_pixel_depth;
970f6abe 3036 png_size_t row_bytes;
0272a10d 3037
970f6abe 3038 png_debug(1, "in png_read_start_row");
0272a10d
VZ
3039 png_ptr->zstream.avail_in = 0;
3040 png_init_read_transformations(png_ptr);
970f6abe 3041#ifdef PNG_READ_INTERLACING_SUPPORTED
0272a10d
VZ
3042 if (png_ptr->interlaced)
3043 {
3044 if (!(png_ptr->transformations & PNG_INTERLACE))
3045 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
3046 png_pass_ystart[0]) / png_pass_yinc[0];
3047 else
3048 png_ptr->num_rows = png_ptr->height;
3049
3050 png_ptr->iwidth = (png_ptr->width +
3051 png_pass_inc[png_ptr->pass] - 1 -
3052 png_pass_start[png_ptr->pass]) /
3053 png_pass_inc[png_ptr->pass];
3054
970f6abe
VZ
3055 png_ptr->irowbytes =
3056 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1;
0272a10d
VZ
3057 }
3058 else
970f6abe 3059#endif /* PNG_READ_INTERLACING_SUPPORTED */
0272a10d
VZ
3060 {
3061 png_ptr->num_rows = png_ptr->height;
3062 png_ptr->iwidth = png_ptr->width;
3063 png_ptr->irowbytes = png_ptr->rowbytes + 1;
3064 }
3065 max_pixel_depth = png_ptr->pixel_depth;
3066
3067#if defined(PNG_READ_PACK_SUPPORTED)
3068 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
3069 max_pixel_depth = 8;
3070#endif
3071
3072#if defined(PNG_READ_EXPAND_SUPPORTED)
3073 if (png_ptr->transformations & PNG_EXPAND)
3074 {
3075 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3076 {
3077 if (png_ptr->num_trans)
3078 max_pixel_depth = 32;
3079 else
3080 max_pixel_depth = 24;
3081 }
3082 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3083 {
3084 if (max_pixel_depth < 8)
3085 max_pixel_depth = 8;
3086 if (png_ptr->num_trans)
3087 max_pixel_depth *= 2;
3088 }
3089 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3090 {
3091 if (png_ptr->num_trans)
3092 {
3093 max_pixel_depth *= 4;
3094 max_pixel_depth /= 3;
3095 }
3096 }
3097 }
3098#endif
3099
3100#if defined(PNG_READ_FILLER_SUPPORTED)
3101 if (png_ptr->transformations & (PNG_FILLER))
3102 {
3103 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
3104 max_pixel_depth = 32;
3105 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
3106 {
3107 if (max_pixel_depth <= 8)
3108 max_pixel_depth = 16;
3109 else
3110 max_pixel_depth = 32;
3111 }
3112 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
3113 {
3114 if (max_pixel_depth <= 32)
3115 max_pixel_depth = 32;
3116 else
3117 max_pixel_depth = 64;
3118 }
3119 }
3120#endif
3121
3122#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
3123 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
3124 {
3125 if (
3126#if defined(PNG_READ_EXPAND_SUPPORTED)
3127 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
3128#endif
3129#if defined(PNG_READ_FILLER_SUPPORTED)
3130 (png_ptr->transformations & (PNG_FILLER)) ||
3131#endif
3132 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
3133 {
3134 if (max_pixel_depth <= 16)
3135 max_pixel_depth = 32;
3136 else
3137 max_pixel_depth = 64;
3138 }
3139 else
3140 {
3141 if (max_pixel_depth <= 8)
3142 {
3143 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3144 max_pixel_depth = 32;
3145 else
3146 max_pixel_depth = 24;
3147 }
3148 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
3149 max_pixel_depth = 64;
3150 else
3151 max_pixel_depth = 48;
3152 }
3153 }
3154#endif
3155
3156#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
3157defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
970f6abe 3158 if (png_ptr->transformations & PNG_USER_TRANSFORM)
0272a10d 3159 {
970f6abe 3160 int user_pixel_depth = png_ptr->user_transform_depth*
0272a10d 3161 png_ptr->user_transform_channels;
970f6abe 3162 if (user_pixel_depth > max_pixel_depth)
0272a10d
VZ
3163 max_pixel_depth=user_pixel_depth;
3164 }
3165#endif
3166
3167 /* align the width on the next larger 8 pixels. Mainly used
3168 for interlacing */
3169 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
3170 /* calculate the maximum bytes needed, adding a byte and a pixel
3171 for safety's sake */
970f6abe 3172 row_bytes = PNG_ROWBYTES(max_pixel_depth, row_bytes) +
0272a10d
VZ
3173 1 + ((max_pixel_depth + 7) >> 3);
3174#ifdef PNG_MAX_MALLOC_64K
3175 if (row_bytes > (png_uint_32)65536L)
3176 png_error(png_ptr, "This image requires a row greater than 64KB");
3177#endif
970f6abe
VZ
3178
3179 if (row_bytes + 64 > png_ptr->old_big_row_buf_size)
3180 {
3181 png_free(png_ptr, png_ptr->big_row_buf);
3182 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
3183 png_ptr->row_buf = png_ptr->big_row_buf+32;
3184 png_ptr->old_big_row_buf_size = row_bytes+64;
3185 }
0272a10d
VZ
3186
3187#ifdef PNG_MAX_MALLOC_64K
3188 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
3189 png_error(png_ptr, "This image requires a row greater than 64KB");
3190#endif
3191 if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
3192 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
970f6abe
VZ
3193
3194 if (png_ptr->rowbytes+1 > png_ptr->old_prev_row_size)
3195 {
3196 png_free(png_ptr, png_ptr->prev_row);
3197 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
3198 png_ptr->rowbytes + 1));
3199 png_ptr->old_prev_row_size = png_ptr->rowbytes+1;
3200 }
0272a10d
VZ
3201
3202 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
3203
970f6abe
VZ
3204 png_debug1(3, "width = %lu,", png_ptr->width);
3205 png_debug1(3, "height = %lu,", png_ptr->height);
3206 png_debug1(3, "iwidth = %lu,", png_ptr->iwidth);
3207 png_debug1(3, "num_rows = %lu", png_ptr->num_rows);
3208 png_debug1(3, "rowbytes = %lu,", png_ptr->rowbytes);
3209 png_debug1(3, "irowbytes = %lu,", png_ptr->irowbytes);
0272a10d
VZ
3210
3211 png_ptr->flags |= PNG_FLAG_ROW_INIT;
3212}
3213#endif /* PNG_READ_SUPPORTED */