]> git.saurik.com Git - wxWidgets.git/blame - src/png/pngrutil.c
added wxUSE_INTL around wxLocale::GetSystemEncoding
[wxWidgets.git] / src / png / pngrutil.c
CommitLineData
c801d85f
KB
1
2/* pngrutil.c - utilities to read a PNG file
3 *
a626cc03 4 * libpng 1.0.3 - January 14, 1999
c801d85f
KB
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
7 * Copyright (c) 1996, 1997 Andreas Dilger
a626cc03 8 * Copyright (c) 1998, 1999 Glenn Randers-Pehrson
c801d85f 9 *
a626cc03 10 * This file contains routines that are only called from within
c801d85f
KB
11 * libpng itself during the course of reading an image.
12 */
13
14#define PNG_INTERNAL
a626cc03 15#include "png.h"
c801d85f
KB
16
17#ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
a626cc03 18/* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
c801d85f
KB
19png_uint_32
20png_get_uint_32(png_bytep buf)
21{
a626cc03 22 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
c801d85f
KB
23 ((png_uint_32)(*(buf + 1)) << 16) +
24 ((png_uint_32)(*(buf + 2)) << 8) +
25 (png_uint_32)(*(buf + 3));
26
27 return (i);
28}
29
30#if defined(PNG_READ_pCAL_SUPPORTED)
a626cc03 31/* Grab a signed 32-bit integer from a buffer in big-endian format. The
c801d85f
KB
32 * data is stored in the PNG file in two's complement format, and it is
33 * assumed that the machine format for signed integers is the same. */
34png_int_32
35png_get_int_32(png_bytep buf)
36{
a626cc03 37 png_int_32 i = ((png_int_32)(*buf) << 24) +
c801d85f
KB
38 ((png_int_32)(*(buf + 1)) << 16) +
39 ((png_int_32)(*(buf + 2)) << 8) +
40 (png_int_32)(*(buf + 3));
41
42 return (i);
43}
44#endif /* PNG_READ_pCAL_SUPPORTED */
45
a626cc03 46/* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
c801d85f
KB
47png_uint_16
48png_get_uint_16(png_bytep buf)
49{
a626cc03 50 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
c801d85f
KB
51 (png_uint_16)(*(buf + 1)));
52
53 return (i);
54}
55#endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
56
57/* Read data, and (optionally) run it through the CRC. */
58void
59png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
60{
61 png_read_data(png_ptr, buf, length);
62 png_calculate_crc(png_ptr, buf, length);
63}
64
65/* Optionally skip data and then check the CRC. Depending on whether we
66 are reading a ancillary or critical chunk, and how the program has set
67 things up, we may calculate the CRC on the data and print a message.
68 Returns '1' if there was a CRC error, '0' otherwise. */
69int
70png_crc_finish(png_structp png_ptr, png_uint_32 skip)
71{
a626cc03
RR
72 png_size_t i;
73 png_size_t istop = png_ptr->zbuf_size;
c801d85f 74
a626cc03 75 for (i = (png_size_t)skip; i > istop; i -= istop)
c801d85f
KB
76 {
77 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
78 }
79 if (i)
80 {
a626cc03 81 png_crc_read(png_ptr, png_ptr->zbuf, i);
c801d85f
KB
82 }
83
84 if (png_crc_error(png_ptr))
85 {
86 if ((png_ptr->chunk_name[0] & 0x20 && /* Ancillary */
87 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
88 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
89 png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))
90 {
91 png_chunk_warning(png_ptr, "CRC error");
92 }
93 else
94 {
95 png_chunk_error(png_ptr, "CRC error");
96 }
97 return (1);
98 }
99
100 return (0);
101}
102
103/* Compare the CRC stored in the PNG file with that calculated by libpng from
104 the data it has read thus far. */
105int
106png_crc_error(png_structp png_ptr)
107{
108 png_byte crc_bytes[4];
109 png_uint_32 crc;
110 int need_crc = 1;
111
112 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
113 {
114 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
115 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
116 need_crc = 0;
117 }
118 else /* critical */
119 {
120 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
121 need_crc = 0;
122 }
123
124 png_read_data(png_ptr, crc_bytes, 4);
125
126 if (need_crc)
127 {
128 crc = png_get_uint_32(crc_bytes);
129 return ((int)(crc != png_ptr->crc));
130 }
131 else
132 return (0);
133}
134
135
136/* read and check the IDHR chunk */
137void
138png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
139{
140 png_byte buf[13];
141 png_uint_32 width, height;
142 int bit_depth, color_type, compression_type, filter_type;
143 int interlace_type;
144
145 png_debug(1, "in png_handle_IHDR\n");
146
147 if (png_ptr->mode != PNG_BEFORE_IHDR)
148 png_error(png_ptr, "Out of place IHDR");
149
150 /* check the length */
151 if (length != 13)
152 png_error(png_ptr, "Invalid IHDR chunk");
153
154 png_ptr->mode |= PNG_HAVE_IHDR;
155
156 png_crc_read(png_ptr, buf, 13);
157 png_crc_finish(png_ptr, 0);
158
159 width = png_get_uint_32(buf);
160 height = png_get_uint_32(buf + 4);
161 bit_depth = buf[8];
162 color_type = buf[9];
163 compression_type = buf[10];
164 filter_type = buf[11];
165 interlace_type = buf[12];
166
167 /* check for width and height valid values */
168 if (width == 0 || width > (png_uint_32)2147483647L || height == 0 ||
169 height > (png_uint_32)2147483647L)
170 png_error(png_ptr, "Invalid image size in IHDR");
171
172 /* check other values */
173 if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
174 bit_depth != 8 && bit_depth != 16)
175 png_error(png_ptr, "Invalid bit depth in IHDR");
176
177 if (color_type < 0 || color_type == 1 ||
178 color_type == 5 || color_type > 6)
179 png_error(png_ptr, "Invalid color type in IHDR");
180
181 if ((color_type == PNG_COLOR_TYPE_PALETTE && bit_depth) > 8 ||
182 ((color_type == PNG_COLOR_TYPE_RGB ||
183 color_type == PNG_COLOR_TYPE_GRAY_ALPHA ||
184 color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8))
185 png_error(png_ptr, "Invalid color type/bit depth combination in IHDR");
186
187 if (interlace_type >= PNG_INTERLACE_LAST)
188 png_error(png_ptr, "Unknown interlace method in IHDR");
189
190 if (compression_type != PNG_COMPRESSION_TYPE_BASE)
191 png_error(png_ptr, "Unknown compression method in IHDR");
192
193 if (filter_type != PNG_FILTER_TYPE_BASE)
194 png_error(png_ptr, "Unknown filter method in IHDR");
195
196 /* set internal variables */
197 png_ptr->width = width;
198 png_ptr->height = height;
199 png_ptr->bit_depth = (png_byte)bit_depth;
200 png_ptr->interlaced = (png_byte)interlace_type;
201 png_ptr->color_type = (png_byte)color_type;
202
203 /* find number of channels */
204 switch (png_ptr->color_type)
205 {
206 case PNG_COLOR_TYPE_GRAY:
207 case PNG_COLOR_TYPE_PALETTE:
208 png_ptr->channels = 1;
209 break;
210 case PNG_COLOR_TYPE_RGB:
211 png_ptr->channels = 3;
212 break;
213 case PNG_COLOR_TYPE_GRAY_ALPHA:
214 png_ptr->channels = 2;
215 break;
216 case PNG_COLOR_TYPE_RGB_ALPHA:
217 png_ptr->channels = 4;
218 break;
219 }
220
221 /* set up other useful info */
222 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
223 png_ptr->channels);
224 png_ptr->rowbytes = ((png_ptr->width *
225 (png_uint_32)png_ptr->pixel_depth + 7) >> 3);
226 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
227 png_debug1(3,"channels = %d\n", png_ptr->channels);
228 png_debug1(3,"rowbytes = %d\n", png_ptr->rowbytes);
229 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
230 color_type, interlace_type, compression_type, filter_type);
231}
232
233/* read and check the palette */
234void
235png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
236{
237 png_colorp palette;
238 int num, i;
239
240 png_debug(1, "in png_handle_PLTE\n");
241
242 if (!(png_ptr->mode & PNG_HAVE_IHDR))
243 png_error(png_ptr, "Missing IHDR before PLTE");
244 else if (png_ptr->mode & PNG_HAVE_IDAT)
245 {
246 png_warning(png_ptr, "Invalid PLTE after IDAT");
247 png_crc_finish(png_ptr, length);
248 return;
249 }
250 else if (png_ptr->mode & PNG_HAVE_PLTE)
251 png_error(png_ptr, "Duplicate PLTE chunk");
252
253 png_ptr->mode |= PNG_HAVE_PLTE;
254
c801d85f
KB
255#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
256 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
257 {
258 png_crc_finish(png_ptr, length);
259 return;
260 }
261#endif
262
263 if (length % 3)
264 {
265 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
266 {
267 png_warning(png_ptr, "Invalid palette chunk");
268 png_crc_finish(png_ptr, length);
269 return;
270 }
271 else
272 {
273 png_error(png_ptr, "Invalid palette chunk");
274 }
275 }
276
277 num = (int)length / 3;
278 palette = (png_colorp)png_zalloc(png_ptr, (uInt)num, sizeof (png_color));
279 png_ptr->flags |= PNG_FLAG_FREE_PALETTE;
280 for (i = 0; i < num; i++)
281 {
282 png_byte buf[3];
283
284 png_crc_read(png_ptr, buf, 3);
285 /* don't depend upon png_color being any order */
286 palette[i].red = buf[0];
287 palette[i].green = buf[1];
288 palette[i].blue = buf[2];
289 }
290
291 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
292 whatever the normal CRC configuration tells us. However, if we
293 have an RGB image, the PLTE can be considered ancillary, so
294 we will act as though it is. */
295#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
296 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
297#endif
298 {
299 png_crc_finish(png_ptr, 0);
300 }
301#if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
302 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
303 {
304 /* If we don't want to use the data from an ancillary chunk,
305 we have two options: an error abort, or a warning and we
306 ignore the data in this chunk (which should be OK, since
307 it's considered ancillary for a RGB or RGBA image). */
308 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
309 {
310 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
311 {
312 png_chunk_error(png_ptr, "CRC error");
313 }
314 else
315 {
316 png_chunk_warning(png_ptr, "CRC error");
317 png_ptr->flags &= ~PNG_FLAG_FREE_PALETTE;
318 png_zfree(png_ptr, palette);
319 return;
320 }
321 }
322 /* Otherwise, we (optionally) emit a warning and use the chunk. */
323 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
324 {
325 png_chunk_warning(png_ptr, "CRC error");
326 }
327 }
328#endif
329 png_ptr->palette = palette;
330 png_ptr->num_palette = (png_uint_16)num;
331 png_set_PLTE(png_ptr, info_ptr, palette, num);
a626cc03
RR
332
333#if defined (PNG_READ_tRNS_SUPPORTED)
334 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
335 {
336 if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tRNS)
337 {
338 if (png_ptr->num_trans > png_ptr->num_palette)
339 {
340 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
341 png_ptr->num_trans = png_ptr->num_palette;
342 }
343 }
344 }
345#endif
346
c801d85f
KB
347}
348
349void
350png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
351{
352 png_debug(1, "in png_handle_IEND\n");
353
354 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
355 {
356 png_error(png_ptr, "No image in file");
357
358 /* to quiet compiler warnings about unused info_ptr */
359 if (info_ptr == NULL)
360 return;
361 }
362
363 png_ptr->mode |= PNG_AFTER_IDAT | PNG_HAVE_IEND;
364
365 if (length != 0)
366 {
367 png_warning(png_ptr, "Incorrect IEND chunk length");
368 }
369 png_crc_finish(png_ptr, length);
370}
371
372#if defined(PNG_READ_gAMA_SUPPORTED)
373void
374png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
375{
376 png_uint_32 igamma;
377 float file_gamma;
378 png_byte buf[4];
379
380 png_debug(1, "in png_handle_gAMA\n");
381
382 if (!(png_ptr->mode & PNG_HAVE_IHDR))
383 png_error(png_ptr, "Missing IHDR before gAMA");
384 else if (png_ptr->mode & PNG_HAVE_IDAT)
385 {
386 png_warning(png_ptr, "Invalid gAMA after IDAT");
387 png_crc_finish(png_ptr, length);
388 return;
389 }
390 else if (png_ptr->mode & PNG_HAVE_PLTE)
391 /* Should be an error, but we can cope with it */
392 png_warning(png_ptr, "Out of place gAMA chunk");
393
394 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_gAMA
395#if defined(PNG_READ_sRGB_SUPPORTED)
396 && !(info_ptr->valid & PNG_INFO_sRGB)
397#endif
398 )
399 {
400 png_warning(png_ptr, "Duplicate gAMA chunk");
401 png_crc_finish(png_ptr, length);
402 return;
403 }
404
405 if (length != 4)
406 {
407 png_warning(png_ptr, "Incorrect gAMA chunk length");
408 png_crc_finish(png_ptr, length);
409 return;
410 }
411
412 png_crc_read(png_ptr, buf, 4);
413 if (png_crc_finish(png_ptr, 0))
414 return;
415
416 igamma = png_get_uint_32(buf);
417 /* check for zero gamma */
418 if (igamma == 0)
419 return;
420
421#if defined(PNG_READ_sRGB_SUPPORTED)
422 if (info_ptr->valid & PNG_INFO_sRGB)
423 if(igamma != (png_uint_32)45000L)
424 {
425 png_warning(png_ptr,
426 "Ignoring incorrect gAMA value when sRGB is also present");
a626cc03 427#ifndef PNG_NO_CONSOLE_IO
c801d85f
KB
428 fprintf(stderr, "igamma = %lu\n", igamma);
429#endif
430 return;
431 }
432#endif /* PNG_READ_sRGB_SUPPORTED */
433
434 file_gamma = (float)igamma / (float)100000.0;
435#ifdef PNG_READ_GAMMA_SUPPORTED
436 png_ptr->gamma = file_gamma;
437#endif
438 png_set_gAMA(png_ptr, info_ptr, file_gamma);
439}
440#endif
441
442#if defined(PNG_READ_sBIT_SUPPORTED)
443void
444png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
445{
446 png_size_t truelen;
447 png_byte buf[4];
448
449 png_debug(1, "in png_handle_sBIT\n");
450
451 buf[0] = buf[1] = buf[2] = buf[3] = 0;
452
453 if (!(png_ptr->mode & PNG_HAVE_IHDR))
454 png_error(png_ptr, "Missing IHDR before sBIT");
455 else if (png_ptr->mode & PNG_HAVE_IDAT)
456 {
457 png_warning(png_ptr, "Invalid sBIT after IDAT");
458 png_crc_finish(png_ptr, length);
459 return;
460 }
461 else if (png_ptr->mode & PNG_HAVE_PLTE)
462 {
463 /* Should be an error, but we can cope with it */
464 png_warning(png_ptr, "Out of place sBIT chunk");
465 }
466 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_sBIT)
467 {
468 png_warning(png_ptr, "Duplicate sBIT chunk");
469 png_crc_finish(png_ptr, length);
470 return;
471 }
472
473 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
474 truelen = 3;
475 else
476 truelen = (png_size_t)png_ptr->channels;
477
478 if (length != truelen)
479 {
480 png_warning(png_ptr, "Incorrect sBIT chunk length");
481 png_crc_finish(png_ptr, length);
482 return;
483 }
484
485 png_crc_read(png_ptr, buf, truelen);
486 if (png_crc_finish(png_ptr, 0))
487 return;
488
489 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
490 {
491 png_ptr->sig_bit.red = buf[0];
492 png_ptr->sig_bit.green = buf[1];
493 png_ptr->sig_bit.blue = buf[2];
494 png_ptr->sig_bit.alpha = buf[3];
495 }
496 else
497 {
498 png_ptr->sig_bit.gray = buf[0];
a626cc03
RR
499 png_ptr->sig_bit.red = buf[0];
500 png_ptr->sig_bit.green = buf[0];
501 png_ptr->sig_bit.blue = buf[0];
c801d85f
KB
502 png_ptr->sig_bit.alpha = buf[1];
503 }
504 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
505}
506#endif
507
508#if defined(PNG_READ_cHRM_SUPPORTED)
509void
510png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
511{
512 png_byte buf[4];
513 png_uint_32 val;
514 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
515
516 png_debug(1, "in png_handle_cHRM\n");
517
518 if (!(png_ptr->mode & PNG_HAVE_IHDR))
519 png_error(png_ptr, "Missing IHDR before sBIT");
520 else if (png_ptr->mode & PNG_HAVE_IDAT)
521 {
522 png_warning(png_ptr, "Invalid cHRM after IDAT");
523 png_crc_finish(png_ptr, length);
524 return;
525 }
526 else if (png_ptr->mode & PNG_HAVE_PLTE)
527 /* Should be an error, but we can cope with it */
528 png_warning(png_ptr, "Missing PLTE before cHRM");
529
530 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_cHRM
531#if defined(PNG_READ_sRGB_SUPPORTED)
532 && !(info_ptr->valid & PNG_INFO_sRGB)
533#endif
534 )
535 {
536 png_warning(png_ptr, "Duplicate cHRM chunk");
537 png_crc_finish(png_ptr, length);
538 return;
539 }
540
541 if (length != 32)
542 {
543 png_warning(png_ptr, "Incorrect cHRM chunk length");
544 png_crc_finish(png_ptr, length);
545 return;
546 }
547
548 png_crc_read(png_ptr, buf, 4);
549 val = png_get_uint_32(buf);
550 white_x = (float)val / (float)100000.0;
551
552 png_crc_read(png_ptr, buf, 4);
553 val = png_get_uint_32(buf);
554 white_y = (float)val / (float)100000.0;
555
556 if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
557 white_x + white_y > 1.0)
558 {
559 png_warning(png_ptr, "Invalid cHRM white point");
560 png_crc_finish(png_ptr, 24);
561 return;
562 }
563
564 png_crc_read(png_ptr, buf, 4);
565 val = png_get_uint_32(buf);
566 red_x = (float)val / (float)100000.0;
567
568 png_crc_read(png_ptr, buf, 4);
569 val = png_get_uint_32(buf);
570 red_y = (float)val / (float)100000.0;
571
572 if (red_x < 0 || red_x > 0.8 || red_y < 0 || red_y > 0.8 ||
573 red_x + red_y > 1.0)
574 {
575 png_warning(png_ptr, "Invalid cHRM red point");
576 png_crc_finish(png_ptr, 16);
577 return;
578 }
579
580 png_crc_read(png_ptr, buf, 4);
581 val = png_get_uint_32(buf);
582 green_x = (float)val / (float)100000.0;
583
584 png_crc_read(png_ptr, buf, 4);
585 val = png_get_uint_32(buf);
586 green_y = (float)val / (float)100000.0;
587
588 if (green_x < 0 || green_x > 0.8 || green_y < 0 || green_y > 0.8 ||
589 green_x + green_y > 1.0)
590 {
591 png_warning(png_ptr, "Invalid cHRM green point");
592 png_crc_finish(png_ptr, 8);
593 return;
594 }
595
596 png_crc_read(png_ptr, buf, 4);
597 val = png_get_uint_32(buf);
598 blue_x = (float)val / (float)100000.0;
599
600 png_crc_read(png_ptr, buf, 4);
601 val = png_get_uint_32(buf);
602 blue_y = (float)val / (float)100000.0;
603
604 if (blue_x < (float)0 || blue_x > (float)0.8 || blue_y < (float)0 ||
605 blue_y > (float)0.8 || blue_x + blue_y > (float)1.0)
606 {
607 png_warning(png_ptr, "Invalid cHRM blue point");
608 png_crc_finish(png_ptr, 0);
609 return;
610 }
611
612 if (png_crc_finish(png_ptr, 0))
613 return;
614
615#if defined(PNG_READ_sRGB_SUPPORTED)
616 if (info_ptr->valid & PNG_INFO_sRGB)
617 {
618 if (fabs(white_x - (float).3127) > (float).001 ||
619 fabs(white_y - (float).3290) > (float).001 ||
620 fabs( red_x - (float).6400) > (float).001 ||
621 fabs( red_y - (float).3300) > (float).001 ||
622 fabs(green_x - (float).3000) > (float).001 ||
623 fabs(green_y - (float).6000) > (float).001 ||
624 fabs( blue_x - (float).1500) > (float).001 ||
625 fabs( blue_y - (float).0600) > (float).001)
626 {
627
628 png_warning(png_ptr,
629 "Ignoring incorrect cHRM value when sRGB is also present");
a626cc03 630#ifndef PNG_NO_CONSOLE_IO
c801d85f
KB
631 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
632 white_x, white_y, red_x, red_y);
633 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
634 green_x, green_y, blue_x, blue_y);
635#endif
636 }
637 return;
638 }
639#endif /* PNG_READ_sRGB_SUPPORTED */
640
641 png_set_cHRM(png_ptr, info_ptr,
642 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
643}
644#endif
645
646#if defined(PNG_READ_sRGB_SUPPORTED)
647void
648png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
649{
650 int intent;
651 png_byte buf[1];
652
653 png_debug(1, "in png_handle_sRGB\n");
654
655 if (!(png_ptr->mode & PNG_HAVE_IHDR))
656 png_error(png_ptr, "Missing IHDR before sRGB");
657 else if (png_ptr->mode & PNG_HAVE_IDAT)
658 {
659 png_warning(png_ptr, "Invalid sRGB after IDAT");
660 png_crc_finish(png_ptr, length);
661 return;
662 }
663 else if (png_ptr->mode & PNG_HAVE_PLTE)
664 /* Should be an error, but we can cope with it */
665 png_warning(png_ptr, "Out of place sRGB chunk");
666
667 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_sRGB)
668 {
669 png_warning(png_ptr, "Duplicate sRGB chunk");
670 png_crc_finish(png_ptr, length);
671 return;
672 }
673
674 if (length != 1)
675 {
676 png_warning(png_ptr, "Incorrect sRGB chunk length");
677 png_crc_finish(png_ptr, length);
678 return;
679 }
680
681 png_crc_read(png_ptr, buf, 1);
682 if (png_crc_finish(png_ptr, 0))
683 return;
684
685 intent = buf[0];
686 /* check for bad intent */
687 if (intent >= PNG_sRGB_INTENT_LAST)
688 {
689 png_warning(png_ptr, "Unknown sRGB intent");
690 return;
691 }
692
693#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
694 if ((info_ptr->valid & PNG_INFO_gAMA))
695 if((png_uint_32)(png_ptr->gamma*(float)100000.+.5) != (png_uint_32)45000L)
696 {
697 png_warning(png_ptr,
698 "Ignoring incorrect gAMA value when sRGB is also present");
a626cc03 699#ifndef PNG_NO_CONSOLE_IO
c801d85f
KB
700 fprintf(stderr,"gamma=%f\n",png_ptr->gamma);
701#endif
702 }
703#endif /* PNG_READ_gAMA_SUPPORTED */
704
705#ifdef PNG_READ_cHRM_SUPPORTED
706 if (info_ptr->valid & PNG_INFO_cHRM)
707 if (fabs(info_ptr->x_white - (float).3127) > (float).001 ||
708 fabs(info_ptr->y_white - (float).3290) > (float).001 ||
709 fabs( info_ptr->x_red - (float).6400) > (float).001 ||
710 fabs( info_ptr->y_red - (float).3300) > (float).001 ||
711 fabs(info_ptr->x_green - (float).3000) > (float).001 ||
712 fabs(info_ptr->y_green - (float).6000) > (float).001 ||
713 fabs( info_ptr->x_blue - (float).1500) > (float).001 ||
714 fabs( info_ptr->y_blue - (float).0600) > (float).001)
715 {
716 png_warning(png_ptr,
717 "Ignoring incorrect cHRM value when sRGB is also present");
718 }
719#endif /* PNG_READ_cHRM_SUPPORTED */
720
721 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
722}
723#endif /* PNG_READ_sRGB_SUPPORTED */
724
725#if defined(PNG_READ_tRNS_SUPPORTED)
726void
727png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
728{
729 png_debug(1, "in png_handle_tRNS\n");
730
731 if (!(png_ptr->mode & PNG_HAVE_IHDR))
732 png_error(png_ptr, "Missing IHDR before tRNS");
733 else if (png_ptr->mode & PNG_HAVE_IDAT)
734 {
735 png_warning(png_ptr, "Invalid tRNS after IDAT");
736 png_crc_finish(png_ptr, length);
737 return;
738 }
739 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tRNS)
740 {
741 png_warning(png_ptr, "Duplicate tRNS chunk");
742 png_crc_finish(png_ptr, length);
743 return;
744 }
745
746 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
747 {
748 if (!(png_ptr->mode & PNG_HAVE_PLTE))
749 {
750 /* Should be an error, but we can cope with it */
751 png_warning(png_ptr, "Missing PLTE before tRNS");
752 }
753 else if (length > png_ptr->num_palette)
754 {
755 png_warning(png_ptr, "Incorrect tRNS chunk length");
756 png_crc_finish(png_ptr, length);
757 return;
758 }
a626cc03
RR
759 if (length == 0)
760 {
761 png_warning(png_ptr, "Zero length tRNS chunk");
762 png_crc_finish(png_ptr, length);
763 return;
764 }
c801d85f
KB
765
766 png_ptr->trans = (png_bytep)png_malloc(png_ptr, length);
767 png_ptr->flags |= PNG_FLAG_FREE_TRANS;
768 png_crc_read(png_ptr, png_ptr->trans, (png_size_t)length);
769 png_ptr->num_trans = (png_uint_16)length;
770 }
771 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
772 {
773 png_byte buf[6];
774
775 if (length != 6)
776 {
777 png_warning(png_ptr, "Incorrect tRNS chunk length");
778 png_crc_finish(png_ptr, length);
779 return;
780 }
781
782 png_crc_read(png_ptr, buf, (png_size_t)length);
783 png_ptr->num_trans = 1;
784 png_ptr->trans_values.red = png_get_uint_16(buf);
785 png_ptr->trans_values.green = png_get_uint_16(buf + 2);
786 png_ptr->trans_values.blue = png_get_uint_16(buf + 4);
787 }
788 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
789 {
790 png_byte buf[6];
791
792 if (length != 2)
793 {
794 png_warning(png_ptr, "Incorrect tRNS chunk length");
795 png_crc_finish(png_ptr, length);
796 return;
797 }
798
799 png_crc_read(png_ptr, buf, 2);
800 png_ptr->num_trans = 1;
801 png_ptr->trans_values.gray = png_get_uint_16(buf);
802 }
803 else
804 {
805 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
806 png_crc_finish(png_ptr, length);
807 return;
808 }
809
810 if (png_crc_finish(png_ptr, 0))
811 return;
812
813 png_set_tRNS(png_ptr, info_ptr, png_ptr->trans, png_ptr->num_trans,
814 &(png_ptr->trans_values));
815}
816#endif
817
818#if defined(PNG_READ_bKGD_SUPPORTED)
819void
820png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
821{
822 png_size_t truelen;
823 png_byte buf[6];
824
825 png_debug(1, "in png_handle_bKGD\n");
826
827 if (!(png_ptr->mode & PNG_HAVE_IHDR))
828 png_error(png_ptr, "Missing IHDR before bKGD");
829 else if (png_ptr->mode & PNG_HAVE_IDAT)
830 {
831 png_warning(png_ptr, "Invalid bKGD after IDAT");
832 png_crc_finish(png_ptr, length);
833 return;
834 }
835 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
836 !(png_ptr->mode & PNG_HAVE_PLTE))
837 {
838 png_warning(png_ptr, "Missing PLTE before bKGD");
839 png_crc_finish(png_ptr, length);
840 return;
841 }
842 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_bKGD)
843 {
844 png_warning(png_ptr, "Duplicate bKGD chunk");
845 png_crc_finish(png_ptr, length);
846 return;
847 }
848
849 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
850 truelen = 1;
851 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
852 truelen = 6;
853 else
854 truelen = 2;
855
856 if (length != truelen)
857 {
858 png_warning(png_ptr, "Incorrect bKGD chunk length");
859 png_crc_finish(png_ptr, length);
860 return;
861 }
862
863 png_crc_read(png_ptr, buf, truelen);
864 if (png_crc_finish(png_ptr, 0))
865 return;
866
867 /* We convert the index value into RGB components so that we can allow
868 * arbitrary RGB values for background when we have transparency, and
869 * so it is easy to determine the RGB values of the background color
870 * from the info_ptr struct. */
871 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
872 {
873 png_ptr->background.index = buf[0];
874 png_ptr->background.red = (png_uint_16)png_ptr->palette[buf[0]].red;
875 png_ptr->background.green = (png_uint_16)png_ptr->palette[buf[0]].green;
876 png_ptr->background.blue = (png_uint_16)png_ptr->palette[buf[0]].blue;
877 }
878 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
879 {
880 png_ptr->background.red =
881 png_ptr->background.green =
882 png_ptr->background.blue =
883 png_ptr->background.gray = png_get_uint_16(buf);
884 }
885 else
886 {
887 png_ptr->background.red = png_get_uint_16(buf);
888 png_ptr->background.green = png_get_uint_16(buf + 2);
889 png_ptr->background.blue = png_get_uint_16(buf + 4);
890 }
891
892 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
893}
894#endif
895
896#if defined(PNG_READ_hIST_SUPPORTED)
897void
898png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
899{
900 int num, i;
901
902 png_debug(1, "in png_handle_hIST\n");
903
904 if (!(png_ptr->mode & PNG_HAVE_IHDR))
905 png_error(png_ptr, "Missing IHDR before hIST");
906 else if (png_ptr->mode & PNG_HAVE_IDAT)
907 {
908 png_warning(png_ptr, "Invalid hIST after IDAT");
909 png_crc_finish(png_ptr, length);
910 return;
911 }
912 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
913 {
914 png_warning(png_ptr, "Missing PLTE before hIST");
915 png_crc_finish(png_ptr, length);
916 return;
917 }
918 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_hIST)
919 {
920 png_warning(png_ptr, "Duplicate hIST chunk");
921 png_crc_finish(png_ptr, length);
922 return;
923 }
924
925 if (length != (png_uint_32)(2 * png_ptr->num_palette))
926 {
927 png_warning(png_ptr, "Incorrect hIST chunk length");
928 png_crc_finish(png_ptr, length);
929 return;
930 }
931
932 num = (int)length / 2;
933 png_ptr->hist = (png_uint_16p)png_malloc(png_ptr,
934 (png_uint_32)(num * sizeof (png_uint_16)));
935 png_ptr->flags |= PNG_FLAG_FREE_HIST;
936 for (i = 0; i < num; i++)
937 {
938 png_byte buf[2];
939
940 png_crc_read(png_ptr, buf, 2);
941 png_ptr->hist[i] = png_get_uint_16(buf);
942 }
943
944 if (png_crc_finish(png_ptr, 0))
945 return;
946
947 png_set_hIST(png_ptr, info_ptr, png_ptr->hist);
948}
949#endif
950
951#if defined(PNG_READ_pHYs_SUPPORTED)
952void
953png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
954{
955 png_byte buf[9];
956 png_uint_32 res_x, res_y;
957 int unit_type;
958
959 png_debug(1, "in png_handle_pHYs\n");
960
961 if (!(png_ptr->mode & PNG_HAVE_IHDR))
962 png_error(png_ptr, "Missing IHDR before pHYS");
963 else if (png_ptr->mode & PNG_HAVE_IDAT)
964 {
965 png_warning(png_ptr, "Invalid pHYS after IDAT");
966 png_crc_finish(png_ptr, length);
967 return;
968 }
969 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_pHYs)
970 {
971 png_warning(png_ptr, "Duplicate pHYS chunk");
972 png_crc_finish(png_ptr, length);
973 return;
974 }
975
976 if (length != 9)
977 {
978 png_warning(png_ptr, "Incorrect pHYs chunk length");
979 png_crc_finish(png_ptr, length);
980 return;
981 }
982
983 png_crc_read(png_ptr, buf, 9);
984 if (png_crc_finish(png_ptr, 0))
985 return;
986
987 res_x = png_get_uint_32(buf);
988 res_y = png_get_uint_32(buf + 4);
989 unit_type = buf[8];
990 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
991}
992#endif
993
994#if defined(PNG_READ_oFFs_SUPPORTED)
995void
996png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
997{
998 png_byte buf[9];
999 png_uint_32 offset_x, offset_y;
1000 int unit_type;
1001
1002 png_debug(1, "in png_handle_oFFs\n");
1003
1004 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1005 png_error(png_ptr, "Missing IHDR before oFFs");
1006 else if (png_ptr->mode & PNG_HAVE_IDAT)
1007 {
1008 png_warning(png_ptr, "Invalid oFFs after IDAT");
1009 png_crc_finish(png_ptr, length);
1010 return;
1011 }
1012 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_oFFs)
1013 {
1014 png_warning(png_ptr, "Duplicate oFFs chunk");
1015 png_crc_finish(png_ptr, length);
1016 return;
1017 }
1018
1019 if (length != 9)
1020 {
1021 png_warning(png_ptr, "Incorrect oFFs chunk length");
1022 png_crc_finish(png_ptr, length);
1023 return;
1024 }
1025
1026 png_crc_read(png_ptr, buf, 9);
1027 if (png_crc_finish(png_ptr, 0))
1028 return;
1029
1030 offset_x = png_get_uint_32(buf);
1031 offset_y = png_get_uint_32(buf + 4);
1032 unit_type = buf[8];
1033 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1034}
1035#endif
1036
1037#if defined(PNG_READ_pCAL_SUPPORTED)
1038/* read the pCAL chunk (png-scivis-19970203) */
1039void
1040png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1041{
1042 png_charp purpose;
1043 png_int_32 X0, X1;
1044 png_byte type, nparams;
1045 png_charp buf, units, endptr;
1046 png_charpp params;
1047 png_size_t slength;
1048 int i;
1049
1050 png_debug(1, "in png_handle_pCAL\n");
1051
1052 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1053 png_error(png_ptr, "Missing IHDR before pCAL");
1054 else if (png_ptr->mode & PNG_HAVE_IDAT)
1055 {
1056 png_warning(png_ptr, "Invalid pCAL after IDAT");
1057 png_crc_finish(png_ptr, length);
1058 return;
1059 }
1060 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_pCAL)
1061 {
1062 png_warning(png_ptr, "Duplicate pCAL chunk");
1063 png_crc_finish(png_ptr, length);
1064 return;
1065 }
1066
1067 png_debug1(2, "Allocating and reading pCAL chunk data (%d bytes)\n",
1068 length + 1);
1069 purpose = (png_charp)png_malloc(png_ptr, length + 1);
1070 slength = (png_size_t)length;
1071 png_crc_read(png_ptr, (png_bytep)purpose, slength);
1072
1073 if (png_crc_finish(png_ptr, 0))
1074 {
1075 png_free(png_ptr, purpose);
1076 return;
1077 }
1078
1079 purpose[slength] = 0x00; /* null terminate the last string */
1080
1081 png_debug(3, "Finding end of pCAL purpose string\n");
a626cc03 1082 for (buf = purpose; *buf; buf++)
c801d85f
KB
1083 /* empty loop */ ;
1084
1085 endptr = purpose + slength;
1086
1087 /* We need to have at least 12 bytes after the purpose string
1088 in order to get the parameter information. */
1089 if (endptr <= buf + 12)
1090 {
1091 png_warning(png_ptr, "Invalid pCAL data");
1092 png_free(png_ptr, purpose);
1093 return;
1094 }
1095
1096 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1097 X0 = png_get_int_32((png_bytep)buf+1);
1098 X1 = png_get_int_32((png_bytep)buf+5);
1099 type = buf[9];
1100 nparams = buf[10];
1101 units = buf + 11;
1102
1103 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1104 /* Check that we have the right number of parameters for known
1105 equation types. */
1106 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1107 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1108 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1109 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1110 {
1111 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1112 png_free(png_ptr, purpose);
1113 return;
1114 }
1115 else if (type >= PNG_EQUATION_LAST)
1116 {
1117 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1118 }
1119
a626cc03 1120 for (buf = units; *buf; buf++)
c801d85f
KB
1121 /* Empty loop to move past the units string. */ ;
1122
1123 png_debug(3, "Allocating pCAL parameters array\n");
1124 params = (png_charpp)png_malloc(png_ptr, (png_uint_32)(nparams
1125 *sizeof(png_charp))) ;
1126
1127 /* Get pointers to the start of each parameter string. */
1128 for (i = 0; i < (int)nparams; i++)
1129 {
1130 buf++; /* Skip the null string terminator from previous parameter. */
1131
1132 png_debug1(3, "Reading pCAL parameter %d\n", i);
1133 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
1134 /* Empty loop to move past each parameter string */ ;
1135
1136 /* Make sure we haven't run out of data yet */
1137 if (buf > endptr)
1138 {
1139 png_warning(png_ptr, "Invalid pCAL data");
1140 png_free(png_ptr, purpose);
1141 png_free(png_ptr, params);
1142 return;
1143 }
1144 }
1145
1146 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1147 units, params);
1148
1149 png_free(png_ptr, purpose);
1150 png_free(png_ptr, params);
1151}
1152#endif
1153
1154#if defined(PNG_READ_tIME_SUPPORTED)
1155void
1156png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1157{
1158 png_byte buf[7];
1159 png_time mod_time;
1160
1161 png_debug(1, "in png_handle_tIME\n");
1162
1163 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1164 png_error(png_ptr, "Out of place tIME chunk");
1165 else if (info_ptr != NULL && info_ptr->valid & PNG_INFO_tIME)
1166 {
1167 png_warning(png_ptr, "Duplicate tIME chunk");
1168 png_crc_finish(png_ptr, length);
1169 return;
1170 }
1171
1172 if (png_ptr->mode & PNG_HAVE_IDAT)
1173 png_ptr->mode |= PNG_AFTER_IDAT;
1174
1175 if (length != 7)
1176 {
1177 png_warning(png_ptr, "Incorrect tIME chunk length");
1178 png_crc_finish(png_ptr, length);
1179 return;
1180 }
1181
1182 png_crc_read(png_ptr, buf, 7);
1183 if (png_crc_finish(png_ptr, 0))
1184 return;
1185
1186 mod_time.second = buf[6];
1187 mod_time.minute = buf[5];
1188 mod_time.hour = buf[4];
1189 mod_time.day = buf[3];
1190 mod_time.month = buf[2];
1191 mod_time.year = png_get_uint_16(buf);
1192
1193 png_set_tIME(png_ptr, info_ptr, &mod_time);
1194}
1195#endif
1196
1197#if defined(PNG_READ_tEXt_SUPPORTED)
1198/* Note: this does not properly handle chunks that are > 64K under DOS */
1199void
1200png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1201{
1202 png_textp text_ptr;
1203 png_charp key;
1204 png_charp text;
1205 png_uint_32 skip = 0;
1206 png_size_t slength;
1207
1208 png_debug(1, "in png_handle_tEXt\n");
1209
1210 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1211 png_error(png_ptr, "Missing IHDR before tEXt");
1212
1213 if (png_ptr->mode & PNG_HAVE_IDAT)
1214 png_ptr->mode |= PNG_AFTER_IDAT;
1215
1216#ifdef PNG_MAX_MALLOC_64K
1217 if (length > (png_uint_32)65535L)
1218 {
1219 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1220 skip = length - (png_uint_32)65535L;
1221 length = (png_uint_32)65535L;
1222 }
1223#endif
1224
1225 key = (png_charp)png_malloc(png_ptr, length + 1);
1226 slength = (png_size_t)length;
1227 png_crc_read(png_ptr, (png_bytep)key, slength);
1228
1229 if (png_crc_finish(png_ptr, skip))
1230 {
1231 png_free(png_ptr, key);
1232 return;
1233 }
1234
1235 key[slength] = 0x00;
1236
1237 for (text = key; *text; text++)
1238 /* empty loop to find end of key */ ;
1239
1240 if (text != key + slength)
1241 text++;
1242
1243 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1244 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1245 text_ptr->key = key;
1246 text_ptr->text = text;
1247
1248 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1249
1250 png_free(png_ptr, text_ptr);
1251}
1252#endif
1253
1254#if defined(PNG_READ_zTXt_SUPPORTED)
1255/* note: this does not correctly handle chunks that are > 64K under DOS */
1256void
1257png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1258{
1259 static char msg[] = "Error decoding zTXt chunk";
1260 png_textp text_ptr;
1261 png_charp key;
1262 png_charp text;
1263 int comp_type = PNG_TEXT_COMPRESSION_NONE;
1264 png_size_t slength;
1265
1266 png_debug(1, "in png_handle_zTXt\n");
1267
1268 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1269 png_error(png_ptr, "Missing IHDR before zTXt");
1270
1271 if (png_ptr->mode & PNG_HAVE_IDAT)
1272 png_ptr->mode |= PNG_AFTER_IDAT;
1273
1274#ifdef PNG_MAX_MALLOC_64K
1275 /* We will no doubt have problems with chunks even half this size, but
1276 there is no hard and fast rule to tell us where to stop. */
1277 if (length > (png_uint_32)65535L)
1278 {
1279 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1280 png_crc_finish(png_ptr, length);
1281 return;
1282 }
1283#endif
1284
1285 key = (png_charp)png_malloc(png_ptr, length + 1);
1286 slength = (png_size_t)length;
1287 png_crc_read(png_ptr, (png_bytep)key, slength);
1288 if (png_crc_finish(png_ptr, 0))
1289 {
1290 png_free(png_ptr, key);
1291 return;
1292 }
1293
1294 key[slength] = 0x00;
1295
1296 for (text = key; *text; text++)
1297 /* empty loop */ ;
1298
1299 /* zTXt must have some text after the keyword */
1300 if (text == key + slength)
1301 {
1302 png_warning(png_ptr, "Zero length zTXt chunk");
1303 }
1304 else if ((comp_type = *(++text)) == PNG_TEXT_COMPRESSION_zTXt)
1305 {
1306 png_size_t text_size, key_size;
1307 text++;
1308
1309 png_ptr->zstream.next_in = (png_bytep)text;
1310 png_ptr->zstream.avail_in = (uInt)(length - (text - key));
1311 png_ptr->zstream.next_out = png_ptr->zbuf;
1312 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
1313
1314 key_size = (png_size_t)(text - key);
1315 text_size = 0;
1316 text = NULL;
1317
1318 while (png_ptr->zstream.avail_in)
1319 {
1320 int ret;
1321
1322 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
1323 if (ret != Z_OK && ret != Z_STREAM_END)
1324 {
1325 if (png_ptr->zstream.msg != NULL)
1326 png_warning(png_ptr, png_ptr->zstream.msg);
1327 else
1328 png_warning(png_ptr, msg);
1329 inflateReset(&png_ptr->zstream);
1330 png_ptr->zstream.avail_in = 0;
1331
1332 if (text == NULL)
1333 {
1334 text_size = key_size + sizeof(msg) + 1;
1335 text = (png_charp)png_malloc(png_ptr, (png_uint_32)text_size);
1336 png_memcpy(text, key, key_size);
1337 }
1338
1339 text[text_size - 1] = 0x00;
1340
1341 /* Copy what we can of the error message into the text chunk */
1342 text_size = (png_size_t)(slength - (text - key) - 1);
1343 text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
1344 png_memcpy(text + key_size, msg, text_size + 1);
1345 break;
1346 }
1347 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
1348 {
1349 if (text == NULL)
1350 {
1351 text = (png_charp)png_malloc(png_ptr,
1352 (png_uint_32)(png_ptr->zbuf_size - png_ptr->zstream.avail_out
1353 + key_size + 1));
1354 png_memcpy(text + key_size, png_ptr->zbuf,
1355 png_ptr->zbuf_size - png_ptr->zstream.avail_out);
1356 png_memcpy(text, key, key_size);
1357 text_size = key_size + png_ptr->zbuf_size -
1358 png_ptr->zstream.avail_out;
1359 *(text + text_size) = 0x00;
1360 }
1361 else
1362 {
1363 png_charp tmp;
1364
1365 tmp = text;
1366 text = (png_charp)png_malloc(png_ptr, (png_uint_32)(text_size +
1367 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
1368 png_memcpy(text, tmp, text_size);
1369 png_free(png_ptr, tmp);
1370 png_memcpy(text + text_size, png_ptr->zbuf,
1371 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
1372 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
1373 *(text + text_size) = 0x00;
1374 }
1375 if (ret != Z_STREAM_END)
1376 {
1377 png_ptr->zstream.next_out = png_ptr->zbuf;
1378 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
1379 }
1380 else
1381 {
1382 break;
1383 }
1384 }
1385 }
1386
1387 inflateReset(&png_ptr->zstream);
1388 png_ptr->zstream.avail_in = 0;
1389
1390 png_free(png_ptr, key);
1391 key = text;
1392 text += key_size;
1393 }
1394 else /* if (comp_type >= PNG_TEXT_COMPRESSION_LAST) */
1395 {
1396 png_size_t text_size;
1397#if !defined(PNG_NO_STDIO)
1398 char umsg[50];
1399
1400 sprintf(umsg, "Unknown zTXt compression type %d", comp_type);
1401 png_warning(png_ptr, umsg);
1402#else
1403 png_warning(png_ptr, "Unknown zTXt compression type");
1404#endif
1405
1406 /* Copy what we can of the error message into the text chunk */
1407 text_size = (png_size_t)(slength - (text - key) - 1);
1408 text_size = sizeof(msg) > text_size ? text_size : sizeof(msg);
1409 png_memcpy(text, msg, text_size + 1);
1410 }
1411
1412 text_ptr = (png_textp)png_malloc(png_ptr, (png_uint_32)sizeof(png_text));
1413 text_ptr->compression = comp_type;
1414 text_ptr->key = key;
1415 text_ptr->text = text;
1416
1417 png_set_text(png_ptr, info_ptr, text_ptr, 1);
1418
1419 png_free(png_ptr, text_ptr);
1420}
1421#endif
1422
1423/* This function is called when we haven't found a handler for a
1424 chunk. If there isn't a problem with the chunk itself (ie bad
1425 chunk name, CRC, or a critical chunk), the chunk is silently ignored. */
1426void
1427png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1428{
1429 png_debug(1, "in png_handle_unknown\n");
1430
1431 /* In the future we can have code here that calls user-supplied
1432 * callback functions for unknown chunks before they are ignored or
1433 * cause an error.
1434 */
1435 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
1436
1437 if (!(png_ptr->chunk_name[0] & 0x20))
1438 {
1439 png_chunk_error(png_ptr, "unknown critical chunk");
1440
1441 /* to quiet compiler warnings about unused info_ptr */
1442 if (info_ptr == NULL)
1443 return;
1444 }
1445
1446 if (png_ptr->mode & PNG_HAVE_IDAT)
1447 png_ptr->mode |= PNG_AFTER_IDAT;
1448
1449 png_crc_finish(png_ptr, length);
1450
1451}
1452
1453/* This function is called to verify that a chunk name is valid.
1454 This function can't have the "critical chunk check" incorporated
1455 into it, since in the future we will need to be able to call user
1456 functions to handle unknown critical chunks after we check that
1457 the chunk name itself is valid. */
1458
1459#define isnonalpha(c) ((c) < 41 || (c) > 122 || ((c) > 90 && (c) < 97))
1460
1461void
1462png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
1463{
1464 png_debug(1, "in png_check_chunk_name\n");
1465 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
1466 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
1467 {
1468 png_chunk_error(png_ptr, "invalid chunk type");
1469 }
1470}
1471
a626cc03
RR
1472/* Combines the row recently read in with the existing pixels in the
1473 row. This routine takes care of alpha and transparency if requested.
c801d85f
KB
1474 This routine also handles the two methods of progressive display
1475 of interlaced images, depending on the mask value.
1476 The mask value describes which pixels are to be combined with
1477 the row. The pattern always repeats every 8 pixels, so just 8
a626cc03 1478 bits are needed. A one indicates the pixel is to be combined,
c801d85f
KB
1479 a zero indicates the pixel is to be skipped. This is in addition
1480 to any alpha or transparency value associated with the pixel. If
1481 you want all pixels to be combined, pass 0xff (255) in mask. */
1482void
1483png_combine_row(png_structp png_ptr, png_bytep row,
1484 int mask)
1485{
1486 png_debug(1,"in png_combine_row\n");
1487 if (mask == 0xff)
1488 {
1489 png_memcpy(row, png_ptr->row_buf + 1,
1490 (png_size_t)((png_ptr->width *
1491 png_ptr->row_info.pixel_depth + 7) >> 3));
1492 }
1493 else
1494 {
1495 switch (png_ptr->row_info.pixel_depth)
1496 {
1497 case 1:
1498 {
a626cc03
RR
1499 png_bytep sp = png_ptr->row_buf + 1;
1500 png_bytep dp = row;
c801d85f 1501 int s_inc, s_start, s_end;
a626cc03 1502 int m = 0x80;
c801d85f
KB
1503 int shift;
1504 png_uint_32 i;
a626cc03 1505 png_uint_32 row_width = png_ptr->width;
c801d85f 1506
c801d85f
KB
1507#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1508 if (png_ptr->transformations & PNG_PACKSWAP)
1509 {
1510 s_start = 0;
1511 s_end = 7;
1512 s_inc = 1;
1513 }
1514 else
1515#endif
1516 {
1517 s_start = 7;
1518 s_end = 0;
1519 s_inc = -1;
1520 }
1521
1522 shift = s_start;
1523
a626cc03 1524 for (i = 0; i < row_width; i++)
c801d85f
KB
1525 {
1526 if (m & mask)
1527 {
1528 int value;
1529
1530 value = (*sp >> shift) & 0x1;
1531 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
1532 *dp |= (png_byte)(value << shift);
1533 }
1534
1535 if (shift == s_end)
1536 {
1537 shift = s_start;
1538 sp++;
1539 dp++;
1540 }
1541 else
1542 shift += s_inc;
1543
1544 if (m == 1)
1545 m = 0x80;
1546 else
1547 m >>= 1;
1548 }
1549 break;
1550 }
1551 case 2:
1552 {
a626cc03
RR
1553 png_bytep sp = png_ptr->row_buf + 1;
1554 png_bytep dp = row;
c801d85f 1555 int s_start, s_end, s_inc;
a626cc03 1556 int m = 0x80;
c801d85f
KB
1557 int shift;
1558 png_uint_32 i;
a626cc03 1559 png_uint_32 row_width = png_ptr->width;
c801d85f
KB
1560 int value;
1561
c801d85f
KB
1562#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1563 if (png_ptr->transformations & PNG_PACKSWAP)
1564 {
1565 s_start = 0;
1566 s_end = 6;
1567 s_inc = 2;
1568 }
1569 else
1570#endif
1571 {
1572 s_start = 6;
1573 s_end = 0;
1574 s_inc = -2;
1575 }
1576
1577 shift = s_start;
1578
a626cc03 1579 for (i = 0; i < row_width; i++)
c801d85f
KB
1580 {
1581 if (m & mask)
1582 {
1583 value = (*sp >> shift) & 0x3;
1584 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
1585 *dp |= (png_byte)(value << shift);
1586 }
1587
1588 if (shift == s_end)
1589 {
1590 shift = s_start;
1591 sp++;
1592 dp++;
1593 }
1594 else
1595 shift += s_inc;
1596 if (m == 1)
1597 m = 0x80;
1598 else
1599 m >>= 1;
1600 }
1601 break;
1602 }
1603 case 4:
1604 {
a626cc03
RR
1605 png_bytep sp = png_ptr->row_buf + 1;
1606 png_bytep dp = row;
c801d85f 1607 int s_start, s_end, s_inc;
a626cc03 1608 int m = 0x80;
c801d85f
KB
1609 int shift;
1610 png_uint_32 i;
a626cc03 1611 png_uint_32 row_width = png_ptr->width;
c801d85f
KB
1612 int value;
1613
c801d85f
KB
1614#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1615 if (png_ptr->transformations & PNG_PACKSWAP)
1616 {
1617 s_start = 0;
1618 s_end = 4;
1619 s_inc = 4;
1620 }
1621 else
1622#endif
1623 {
1624 s_start = 4;
1625 s_end = 0;
1626 s_inc = -4;
1627 }
1628 shift = s_start;
1629
a626cc03 1630 for (i = 0; i < row_width; i++)
c801d85f
KB
1631 {
1632 if (m & mask)
1633 {
1634 value = (*sp >> shift) & 0xf;
1635 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
1636 *dp |= (png_byte)(value << shift);
1637 }
1638
1639 if (shift == s_end)
1640 {
1641 shift = s_start;
1642 sp++;
1643 dp++;
1644 }
1645 else
1646 shift += s_inc;
1647 if (m == 1)
1648 m = 0x80;
1649 else
1650 m >>= 1;
1651 }
1652 break;
1653 }
1654 default:
1655 {
a626cc03
RR
1656 png_bytep sp = png_ptr->row_buf + 1;
1657 png_bytep dp = row;
1658 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
c801d85f 1659 png_uint_32 i;
a626cc03
RR
1660 png_uint_32 row_width = png_ptr->width;
1661 png_byte m = 0x80;
c801d85f 1662
c801d85f 1663
a626cc03 1664 for (i = 0; i < row_width; i++)
c801d85f
KB
1665 {
1666 if (m & mask)
1667 {
1668 png_memcpy(dp, sp, pixel_bytes);
1669 }
1670
1671 sp += pixel_bytes;
1672 dp += pixel_bytes;
1673
1674 if (m == 1)
1675 m = 0x80;
1676 else
1677 m >>= 1;
1678 }
1679 break;
1680 }
1681 }
1682 }
1683}
1684
1685#if defined(PNG_READ_INTERLACING_SUPPORTED)
1686void
1687png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
1688 png_uint_32 transformations)
1689{
1690 png_debug(1,"in png_do_read_interlace\n");
1691 if (row != NULL && row_info != NULL)
1692 {
1693 png_uint_32 final_width;
1694
1695 final_width = row_info->width * png_pass_inc[pass];
1696
1697 switch (row_info->pixel_depth)
1698 {
1699 case 1:
1700 {
a626cc03
RR
1701 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
1702 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
c801d85f
KB
1703 int sshift, dshift;
1704 int s_start, s_end, s_inc;
a626cc03 1705 int jstop = png_pass_inc[pass];
c801d85f
KB
1706 png_byte v;
1707 png_uint_32 i;
1708 int j;
1709
c801d85f
KB
1710#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1711 if (transformations & PNG_PACKSWAP)
1712 {
1713 sshift = (int)((row_info->width + 7) & 7);
1714 dshift = (int)((final_width + 7) & 7);
1715 s_start = 7;
1716 s_end = 0;
1717 s_inc = -1;
1718 }
1719 else
1720#endif
1721 {
1722 sshift = 7 - (int)((row_info->width + 7) & 7);
1723 dshift = 7 - (int)((final_width + 7) & 7);
1724 s_start = 0;
1725 s_end = 7;
1726 s_inc = 1;
1727 }
1728
a626cc03 1729 for (i = 0; i < row_info->width; i++)
c801d85f
KB
1730 {
1731 v = (png_byte)((*sp >> sshift) & 0x1);
a626cc03 1732 for (j = 0; j < jstop; j++)
c801d85f
KB
1733 {
1734 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
1735 *dp |= (png_byte)(v << dshift);
1736 if (dshift == s_end)
1737 {
1738 dshift = s_start;
1739 dp--;
1740 }
1741 else
1742 dshift += s_inc;
1743 }
1744 if (sshift == s_end)
1745 {
1746 sshift = s_start;
1747 sp--;
1748 }
1749 else
1750 sshift += s_inc;
1751 }
1752 break;
1753 }
1754 case 2:
1755 {
a626cc03
RR
1756 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
1757 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
c801d85f
KB
1758 int sshift, dshift;
1759 int s_start, s_end, s_inc;
a626cc03 1760 int jstop = png_pass_inc[pass];
c801d85f
KB
1761 png_uint_32 i;
1762
c801d85f
KB
1763#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1764 if (transformations & PNG_PACKSWAP)
1765 {
1766 sshift = (int)(((row_info->width + 3) & 3) << 1);
1767 dshift = (int)(((final_width + 3) & 3) << 1);
1768 s_start = 6;
1769 s_end = 0;
1770 s_inc = -2;
1771 }
1772 else
1773#endif
1774 {
1775 sshift = (int)((3 - ((row_info->width + 3) & 3)) << 1);
1776 dshift = (int)((3 - ((final_width + 3) & 3)) << 1);
1777 s_start = 0;
1778 s_end = 6;
1779 s_inc = 2;
1780 }
1781
a626cc03 1782 for (i = 0; i < row_info->width; i++)
c801d85f
KB
1783 {
1784 png_byte v;
1785 int j;
1786
1787 v = (png_byte)((*sp >> sshift) & 0x3);
a626cc03 1788 for (j = 0; j < jstop; j++)
c801d85f
KB
1789 {
1790 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
1791 *dp |= (png_byte)(v << dshift);
1792 if (dshift == s_end)
1793 {
1794 dshift = s_start;
1795 dp--;
1796 }
1797 else
1798 dshift += s_inc;
1799 }
1800 if (sshift == s_end)
1801 {
1802 sshift = s_start;
1803 sp--;
1804 }
1805 else
1806 sshift += s_inc;
1807 }
1808 break;
1809 }
1810 case 4:
1811 {
a626cc03
RR
1812 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
1813 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
c801d85f
KB
1814 int sshift, dshift;
1815 int s_start, s_end, s_inc;
1816 png_uint_32 i;
a626cc03 1817 int jstop = png_pass_inc[pass];
c801d85f 1818
c801d85f
KB
1819#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1820 if (transformations & PNG_PACKSWAP)
1821 {
1822 sshift = (int)(((row_info->width + 1) & 1) << 2);
1823 dshift = (int)(((final_width + 1) & 1) << 2);
1824 s_start = 4;
1825 s_end = 0;
1826 s_inc = -4;
1827 }
1828 else
1829#endif
1830 {
1831 sshift = (int)((1 - ((row_info->width + 1) & 1)) << 2);
1832 dshift = (int)((1 - ((final_width + 1) & 1)) << 2);
1833 s_start = 0;
1834 s_end = 4;
1835 s_inc = 4;
1836 }
1837
a626cc03 1838 for (i = 0; i < row_info->width; i++)
c801d85f 1839 {
a626cc03 1840 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
c801d85f
KB
1841 int j;
1842
a626cc03 1843 for (j = 0; j < jstop; j++)
c801d85f
KB
1844 {
1845 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
1846 *dp |= (png_byte)(v << dshift);
1847 if (dshift == s_end)
1848 {
1849 dshift = s_start;
1850 dp--;
1851 }
1852 else
1853 dshift += s_inc;
1854 }
1855 if (sshift == s_end)
1856 {
1857 sshift = s_start;
1858 sp--;
1859 }
1860 else
1861 sshift += s_inc;
1862 }
1863 break;
1864 }
1865 default:
1866 {
a626cc03
RR
1867 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
1868 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
1869 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
1870 int jstop = png_pass_inc[pass];
c801d85f 1871 png_uint_32 i;
c801d85f 1872
a626cc03 1873 for (i = 0; i < row_info->width; i++)
c801d85f
KB
1874 {
1875 png_byte v[8];
1876 int j;
1877
1878 png_memcpy(v, sp, pixel_bytes);
a626cc03 1879 for (j = 0; j < jstop; j++)
c801d85f
KB
1880 {
1881 png_memcpy(dp, v, pixel_bytes);
1882 dp -= pixel_bytes;
1883 }
1884 sp -= pixel_bytes;
1885 }
1886 break;
1887 }
1888 }
1889 row_info->width = final_width;
1890 row_info->rowbytes = ((final_width *
1891 (png_uint_32)row_info->pixel_depth + 7) >> 3);
1892 }
1893}
1894#endif
1895
1896void
1897png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
1898 png_bytep prev_row, int filter)
1899{
1900 png_debug(1, "in png_read_filter_row\n");
1901 png_debug2(2,"row = %d, filter = %d\n", png_ptr->row_number, filter);
1902
1903
1904 switch (filter)
1905 {
1906 case PNG_FILTER_VALUE_NONE:
1907 break;
1908 case PNG_FILTER_VALUE_SUB:
1909 {
1910 png_uint_32 i;
a626cc03
RR
1911 png_uint_32 istop = row_info->rowbytes;
1912 png_uint_32 bpp = (row_info->pixel_depth + 7) / 8;
1913 png_bytep rp = row + bpp;
1914 png_bytep lp = row;
c801d85f 1915
a626cc03 1916 for (i = bpp; i < istop; i++)
c801d85f 1917 {
a626cc03
RR
1918 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
1919 rp++;
c801d85f
KB
1920 }
1921 break;
1922 }
1923 case PNG_FILTER_VALUE_UP:
1924 {
1925 png_uint_32 i;
a626cc03
RR
1926 png_uint_32 istop = row_info->rowbytes;
1927 png_bytep rp = row;
1928 png_bytep pp = prev_row;
c801d85f 1929
a626cc03 1930 for (i = 0; i < istop; i++)
c801d85f 1931 {
a626cc03
RR
1932 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
1933 rp++;
c801d85f
KB
1934 }
1935 break;
1936 }
1937 case PNG_FILTER_VALUE_AVG:
1938 {
1939 png_uint_32 i;
a626cc03
RR
1940 png_bytep rp = row;
1941 png_bytep pp = prev_row;
1942 png_bytep lp = row;
1943 png_uint_32 bpp = (row_info->pixel_depth + 7) / 8;
1944 png_uint_32 istop = row_info->rowbytes - bpp;
1945
1946 for (i = 0; i < bpp; i++)
c801d85f
KB
1947 {
1948 *rp = (png_byte)(((int)(*rp) +
a626cc03
RR
1949 ((int)(*pp++) / 2)) & 0xff);
1950 rp++;
c801d85f 1951 }
a626cc03
RR
1952
1953 for (i = 0; i < istop; i++)
c801d85f
KB
1954 {
1955 *rp = (png_byte)(((int)(*rp) +
a626cc03
RR
1956 (int)(*pp++ + *lp++) / 2) & 0xff);
1957 rp++;
c801d85f
KB
1958 }
1959 break;
1960 }
1961 case PNG_FILTER_VALUE_PAETH:
1962 {
c801d85f 1963 png_uint_32 i;
a626cc03
RR
1964 png_bytep rp = row;
1965 png_bytep pp = prev_row;
1966 png_bytep lp = row;
1967 png_bytep cp = prev_row;
1968 png_uint_32 bpp = (row_info->pixel_depth + 7) / 8;
1969 png_uint_32 istop=row_info->rowbytes - bpp;
1970
1971 for (i = 0; i < bpp; i++)
1972 {
1973 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
1974 rp++;
1975 }
1976
1977 for (i = 0; i < istop; i++) /* use leftover rp,pp */
c801d85f
KB
1978 {
1979 int a, b, c, pa, pb, pc, p;
1980
a626cc03
RR
1981 a = *lp++;
1982 b = *pp++;
1983 c = *cp++;
1984
1985 p = b - c;
1986 pc = a - c;
1987
1988#ifdef PNG_USE_ABS
1989 pa = abs(p);
1990 pb = abs(pc);
1991 pc = abs(p + pc);
1992#else
1993 pa = p < 0 ? -p : p;
1994 pb = pc < 0 ? -pc : pc;
1995 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
1996#endif
1997
1998 /*
1999 if (pa <= pb && pa <= pc)
2000 p = a;
2001 else if (pb <= pc)
2002 p = b;
2003 else
2004 p = c;
2005 */
2006
2007 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
c801d85f
KB
2008
2009 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
a626cc03 2010 rp++;
c801d85f
KB
2011 }
2012 break;
2013 }
2014 default:
a626cc03
RR
2015 png_warning(png_ptr, "Ignoring bad adaptive filter type");
2016 *row=0;
c801d85f
KB
2017 break;
2018 }
2019}
2020
2021void
2022png_read_finish_row(png_structp png_ptr)
2023{
2024 png_debug(1, "in png_read_finish_row\n");
2025 png_ptr->row_number++;
2026 if (png_ptr->row_number < png_ptr->num_rows)
2027 return;
2028
2029 if (png_ptr->interlaced)
2030 {
2031 png_ptr->row_number = 0;
2032 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
2033 do
2034 {
2035 png_ptr->pass++;
2036 if (png_ptr->pass >= 7)
2037 break;
2038 png_ptr->iwidth = (png_ptr->width +
2039 png_pass_inc[png_ptr->pass] - 1 -
2040 png_pass_start[png_ptr->pass]) /
2041 png_pass_inc[png_ptr->pass];
2042 png_ptr->irowbytes = ((png_ptr->iwidth *
2043 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
2044
2045 if (!(png_ptr->transformations & PNG_INTERLACE))
2046 {
2047 png_ptr->num_rows = (png_ptr->height +
2048 png_pass_yinc[png_ptr->pass] - 1 -
2049 png_pass_ystart[png_ptr->pass]) /
2050 png_pass_yinc[png_ptr->pass];
2051 if (!(png_ptr->num_rows))
2052 continue;
2053 }
a626cc03 2054 else /* if (png_ptr->transformations & PNG_INTERLACE) */
c801d85f
KB
2055 break;
2056 } while (png_ptr->iwidth == 0);
2057
2058 if (png_ptr->pass < 7)
2059 return;
2060 }
2061
2062 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
2063 {
2064 char extra;
2065 int ret;
2066
2067 png_ptr->zstream.next_out = (Byte *)&extra;
2068 png_ptr->zstream.avail_out = (uInt)1;
2069 for(;;)
2070 {
2071 if (!(png_ptr->zstream.avail_in))
2072 {
2073 while (!png_ptr->idat_size)
2074 {
2075 png_byte chunk_length[4];
2076
2077 png_crc_finish(png_ptr, 0);
2078
2079 png_read_data(png_ptr, chunk_length, 4);
2080 png_ptr->idat_size = png_get_uint_32(chunk_length);
2081
2082 png_reset_crc(png_ptr);
2083 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
2084 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
2085 png_error(png_ptr, "Not enough image data");
2086
2087 }
2088 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
2089 png_ptr->zstream.next_in = png_ptr->zbuf;
2090 if (png_ptr->zbuf_size > png_ptr->idat_size)
2091 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
2092 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
2093 png_ptr->idat_size -= png_ptr->zstream.avail_in;
2094 }
2095 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
2096 if (ret == Z_STREAM_END)
2097 {
2098 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
2099 png_ptr->idat_size)
2100 png_error(png_ptr, "Extra compressed data");
2101 png_ptr->mode |= PNG_AFTER_IDAT;
2102 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
2103 break;
2104 }
2105 if (ret != Z_OK)
2106 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
2107 "Decompression Error");
2108
2109 if (!(png_ptr->zstream.avail_out))
2110 png_error(png_ptr, "Extra compressed data");
2111
2112 }
2113 png_ptr->zstream.avail_out = 0;
2114 }
2115
2116 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
2117 png_error(png_ptr, "Extra compression data");
2118
2119 inflateReset(&png_ptr->zstream);
2120
2121 png_ptr->mode |= PNG_AFTER_IDAT;
2122}
2123
2124void
2125png_read_start_row(png_structp png_ptr)
2126{
2127 int max_pixel_depth;
a626cc03 2128 png_uint_32 row_bytes;
c801d85f
KB
2129
2130 png_debug(1, "in png_read_start_row\n");
2131 png_ptr->zstream.avail_in = 0;
2132 png_init_read_transformations(png_ptr);
2133 if (png_ptr->interlaced)
2134 {
2135 if (!(png_ptr->transformations & PNG_INTERLACE))
2136 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
2137 png_pass_ystart[0]) / png_pass_yinc[0];
2138 else
2139 png_ptr->num_rows = png_ptr->height;
2140
2141 png_ptr->iwidth = (png_ptr->width +
2142 png_pass_inc[png_ptr->pass] - 1 -
2143 png_pass_start[png_ptr->pass]) /
2144 png_pass_inc[png_ptr->pass];
2145
a626cc03 2146 row_bytes = ((png_ptr->iwidth *
c801d85f 2147 (png_uint_32)png_ptr->pixel_depth + 7) >> 3) +1;
a626cc03
RR
2148 png_ptr->irowbytes = (png_size_t)row_bytes;
2149 if((png_uint_32)png_ptr->irowbytes != row_bytes)
c801d85f
KB
2150 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
2151 }
2152 else
2153 {
2154 png_ptr->num_rows = png_ptr->height;
2155 png_ptr->iwidth = png_ptr->width;
2156 png_ptr->irowbytes = png_ptr->rowbytes + 1;
2157 }
2158 max_pixel_depth = png_ptr->pixel_depth;
2159
2160#if defined(PNG_READ_PACK_SUPPORTED)
2161 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
2162 max_pixel_depth = 8;
2163#endif
2164
2165#if defined(PNG_READ_EXPAND_SUPPORTED)
2166 if (png_ptr->transformations & PNG_EXPAND)
2167 {
2168 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
2169 {
2170 if (png_ptr->num_trans)
2171 max_pixel_depth = 32;
2172 else
2173 max_pixel_depth = 24;
2174 }
2175 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2176 {
2177 if (max_pixel_depth < 8)
2178 max_pixel_depth = 8;
2179 if (png_ptr->num_trans)
2180 max_pixel_depth *= 2;
2181 }
2182 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2183 {
2184 if (png_ptr->num_trans)
2185 {
2186 max_pixel_depth *= 4;
2187 max_pixel_depth /= 3;
2188 }
2189 }
2190 }
2191#endif
2192
2193#if defined(PNG_READ_FILLER_SUPPORTED)
2194 if (png_ptr->transformations & (PNG_FILLER))
2195 {
a626cc03 2196 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
c801d85f 2197 max_pixel_depth = 32;
a626cc03
RR
2198 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
2199 {
2200 if (max_pixel_depth <= 8)
2201 max_pixel_depth = 16;
2202 else
2203 max_pixel_depth = 32;
2204 }
2205 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
2206 {
2207 if (max_pixel_depth <= 32)
2208 max_pixel_depth = 32;
2209 else
2210 max_pixel_depth = 64;
2211 }
c801d85f
KB
2212 }
2213#endif
2214
2215#if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
2216 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
2217 {
a626cc03
RR
2218 if (
2219#if defined(PNG_READ_EXPAND_SUPPORTED)
2220 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
2221#endif
2222#if defined(PNG_READ_FILLER_SUPPORTED)
2223 (png_ptr->transformations & (PNG_FILLER)) ||
2224#endif
2225 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
c801d85f
KB
2226 {
2227 if (max_pixel_depth <= 16)
2228 max_pixel_depth = 32;
a626cc03 2229 else
c801d85f
KB
2230 max_pixel_depth = 64;
2231 }
2232 else
2233 {
2234 if (max_pixel_depth <= 8)
2235 max_pixel_depth = 24;
a626cc03 2236 else
c801d85f
KB
2237 max_pixel_depth = 48;
2238 }
2239 }
2240#endif
2241
2242 /* align the width on the next larger 8 pixels. Mainly used
2243 for interlacing */
a626cc03 2244 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
c801d85f 2245 /* calculate the maximum bytes needed, adding a byte and a pixel
a626cc03
RR
2246 for safety's sake */
2247 row_bytes = ((row_bytes * (png_uint_32)max_pixel_depth + 7) >> 3) +
c801d85f
KB
2248 1 + ((max_pixel_depth + 7) >> 3);
2249#ifdef PNG_MAX_MALLOC_64K
a626cc03 2250 if (row_bytes > (png_uint_32)65536L)
c801d85f
KB
2251 png_error(png_ptr, "This image requires a row greater than 64KB");
2252#endif
a626cc03 2253 png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, row_bytes);
c801d85f
KB
2254
2255#ifdef PNG_MAX_MALLOC_64K
2256 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
2257 png_error(png_ptr, "This image requires a row greater than 64KB");
2258#endif
2259 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
2260 png_ptr->rowbytes + 1));
2261
2262 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
2263
2264 png_debug1(3, "width = %d,\n", png_ptr->width);
2265 png_debug1(3, "height = %d,\n", png_ptr->height);
2266 png_debug1(3, "iwidth = %d,\n", png_ptr->iwidth);
2267 png_debug1(3, "num_rows = %d\n", png_ptr->num_rows);
2268 png_debug1(3, "rowbytes = %d,\n", png_ptr->rowbytes);
2269 png_debug1(3, "irowbytes = %d,\n", png_ptr->irowbytes);
2270
2271 png_ptr->flags |= PNG_FLAG_ROW_INIT;
2272}