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