1
2 /* pngrutil.c - utilities to read a PNG file
3 *
4 * Last changed in libpng 1.2.19 August 18, 2007
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1998-2007 Glenn Randers-Pehrson
7 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
9 *
10 * This file contains routines that are only called from within
11 * libpng itself during the course of reading an image.
12 */
13
14 #define PNG_INTERNAL
15 #include "png.h"
16
17 #if defined(PNG_READ_SUPPORTED)
18
19 #if defined(_WIN32_WCE) && (_WIN32_WCE<0x500)
20 # define WIN32_WCE_OLD
21 #endif
22
23 #ifdef PNG_FLOATING_POINT_SUPPORTED
24 # if defined(WIN32_WCE_OLD)
25 /* strtod() function is not supported on WindowsCE */
png_strtod(png_structp png_ptr,PNG_CONST char * nptr,char ** endptr)26 __inline double png_strtod(png_structp png_ptr, PNG_CONST char *nptr, char **endptr)
27 {
28 double result = 0;
29 int len;
30 wchar_t *str, *end;
31
32 len = MultiByteToWideChar(CP_ACP, 0, nptr, -1, NULL, 0);
33 str = (wchar_t *)png_malloc(png_ptr, len * sizeof(wchar_t));
34 if ( NULL != str )
35 {
36 MultiByteToWideChar(CP_ACP, 0, nptr, -1, str, len);
37 result = wcstod(str, &end);
38 len = WideCharToMultiByte(CP_ACP, 0, end, -1, NULL, 0, NULL, NULL);
39 *endptr = (char *)nptr + (png_strlen(nptr) - len + 1);
40 png_free(png_ptr, str);
41 }
42 return result;
43 }
44 # else
45 # define png_strtod(p,a,b) strtod(a,b)
46 # endif
47 #endif
48
49 png_uint_32 PNGAPI
png_get_uint_31(png_structp png_ptr,png_bytep buf)50 png_get_uint_31(png_structp png_ptr, png_bytep buf)
51 {
52 png_uint_32 i = png_get_uint_32(buf);
53 if (i > PNG_UINT_31_MAX)
54 png_error(png_ptr, "PNG unsigned integer out of range.");
55 return (i);
56 }
57 #ifndef PNG_READ_BIG_ENDIAN_SUPPORTED
58 /* Grab an unsigned 32-bit integer from a buffer in big-endian format. */
59 png_uint_32 PNGAPI
png_get_uint_32(png_bytep buf)60 png_get_uint_32(png_bytep buf)
61 {
62 png_uint_32 i = ((png_uint_32)(*buf) << 24) +
63 ((png_uint_32)(*(buf + 1)) << 16) +
64 ((png_uint_32)(*(buf + 2)) << 8) +
65 (png_uint_32)(*(buf + 3));
66
67 return (i);
68 }
69
70 /* Grab a signed 32-bit integer from a buffer in big-endian format. The
71 * data is stored in the PNG file in two's complement format, and it is
72 * assumed that the machine format for signed integers is the same. */
73 png_int_32 PNGAPI
png_get_int_32(png_bytep buf)74 png_get_int_32(png_bytep buf)
75 {
76 png_int_32 i = ((png_int_32)(*buf) << 24) +
77 ((png_int_32)(*(buf + 1)) << 16) +
78 ((png_int_32)(*(buf + 2)) << 8) +
79 (png_int_32)(*(buf + 3));
80
81 return (i);
82 }
83
84 /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */
85 png_uint_16 PNGAPI
png_get_uint_16(png_bytep buf)86 png_get_uint_16(png_bytep buf)
87 {
88 png_uint_16 i = (png_uint_16)(((png_uint_16)(*buf) << 8) +
89 (png_uint_16)(*(buf + 1)));
90
91 return (i);
92 }
93 #endif /* PNG_READ_BIG_ENDIAN_SUPPORTED */
94
95 /* Read data, and (optionally) run it through the CRC. */
96 void /* PRIVATE */
png_crc_read(png_structp png_ptr,png_bytep buf,png_size_t length)97 png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
98 {
99 if(png_ptr == NULL) return;
100 png_read_data(png_ptr, buf, length);
101 png_calculate_crc(png_ptr, buf, length);
102 }
103
104 /* Optionally skip data and then check the CRC. Depending on whether we
105 are reading a ancillary or critical chunk, and how the program has set
106 things up, we may calculate the CRC on the data and print a message.
107 Returns '1' if there was a CRC error, '0' otherwise. */
108 int /* PRIVATE */
png_crc_finish(png_structp png_ptr,png_uint_32 skip)109 png_crc_finish(png_structp png_ptr, png_uint_32 skip)
110 {
111 png_size_t i;
112 png_size_t istop = png_ptr->zbuf_size;
113
114 for (i = (png_size_t)skip; i > istop; i -= istop)
115 {
116 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
117 }
118 if (i)
119 {
120 png_crc_read(png_ptr, png_ptr->zbuf, i);
121 }
122
123 if (png_crc_error(png_ptr))
124 {
125 if (((png_ptr->chunk_name[0] & 0x20) && /* Ancillary */
126 !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)) ||
127 (!(png_ptr->chunk_name[0] & 0x20) && /* Critical */
128 (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE)))
129 {
130 png_chunk_warning(png_ptr, "CRC error");
131 }
132 else
133 {
134 png_chunk_error(png_ptr, "CRC error");
135 }
136 return (1);
137 }
138
139 return (0);
140 }
141
142 /* Compare the CRC stored in the PNG file with that calculated by libpng from
143 the data it has read thus far. */
144 int /* PRIVATE */
png_crc_error(png_structp png_ptr)145 png_crc_error(png_structp png_ptr)
146 {
147 png_byte crc_bytes[4];
148 png_uint_32 crc;
149 int need_crc = 1;
150
151 if (png_ptr->chunk_name[0] & 0x20) /* ancillary */
152 {
153 if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
154 (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
155 need_crc = 0;
156 }
157 else /* critical */
158 {
159 if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
160 need_crc = 0;
161 }
162
163 png_read_data(png_ptr, crc_bytes, 4);
164
165 if (need_crc)
166 {
167 crc = png_get_uint_32(crc_bytes);
168 return ((int)(crc != png_ptr->crc));
169 }
170 else
171 return (0);
172 }
173
174 #if defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) || \
175 defined(PNG_READ_iCCP_SUPPORTED)
176 /*
177 * Decompress trailing data in a chunk. The assumption is that chunkdata
178 * points at an allocated area holding the contents of a chunk with a
179 * trailing compressed part. What we get back is an allocated area
180 * holding the original prefix part and an uncompressed version of the
181 * trailing part (the malloc area passed in is freed).
182 */
183 png_charp /* PRIVATE */
png_decompress_chunk(png_structp png_ptr,int comp_type,png_charp chunkdata,png_size_t chunklength,png_size_t prefix_size,png_size_t * newlength)184 png_decompress_chunk(png_structp png_ptr, int comp_type,
185 png_charp chunkdata, png_size_t chunklength,
186 png_size_t prefix_size, png_size_t *newlength)
187 {
188 static PNG_CONST char msg[] = "Error decoding compressed text";
189 png_charp text;
190 png_size_t text_size;
191
192 if (comp_type == PNG_COMPRESSION_TYPE_BASE)
193 {
194 int ret = Z_OK;
195 png_ptr->zstream.next_in = (png_bytep)(chunkdata + prefix_size);
196 png_ptr->zstream.avail_in = (uInt)(chunklength - prefix_size);
197 png_ptr->zstream.next_out = png_ptr->zbuf;
198 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
199
200 text_size = 0;
201 text = NULL;
202
203 while (png_ptr->zstream.avail_in)
204 {
205 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
206 if (ret != Z_OK && ret != Z_STREAM_END)
207 {
208 if (png_ptr->zstream.msg != NULL)
209 png_warning(png_ptr, png_ptr->zstream.msg);
210 else
211 png_warning(png_ptr, msg);
212 inflateReset(&png_ptr->zstream);
213 png_ptr->zstream.avail_in = 0;
214
215 if (text == NULL)
216 {
217 text_size = prefix_size + png_sizeof(msg) + 1;
218 text = (png_charp)png_malloc_warn(png_ptr, text_size);
219 if (text == NULL)
220 {
221 png_free(png_ptr,chunkdata);
222 png_error(png_ptr,"Not enough memory to decompress chunk");
223 }
224 png_memcpy(text, chunkdata, prefix_size);
225 }
226
227 text[text_size - 1] = 0x00;
228
229 /* Copy what we can of the error message into the text chunk */
230 text_size = (png_size_t)(chunklength - (text - chunkdata) - 1);
231 text_size = png_sizeof(msg) > text_size ? text_size :
232 png_sizeof(msg);
233 png_memcpy(text + prefix_size, msg, text_size + 1);
234 break;
235 }
236 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
237 {
238 if (text == NULL)
239 {
240 text_size = prefix_size +
241 png_ptr->zbuf_size - png_ptr->zstream.avail_out;
242 text = (png_charp)png_malloc_warn(png_ptr, text_size + 1);
243 if (text == NULL)
244 {
245 png_free(png_ptr,chunkdata);
246 png_error(png_ptr,"Not enough memory to decompress chunk.");
247 }
248 png_memcpy(text + prefix_size, png_ptr->zbuf,
249 text_size - prefix_size);
250 png_memcpy(text, chunkdata, prefix_size);
251 *(text + text_size) = 0x00;
252 }
253 else
254 {
255 png_charp tmp;
256
257 tmp = text;
258 text = (png_charp)png_malloc_warn(png_ptr,
259 (png_uint_32)(text_size +
260 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1));
261 if (text == NULL)
262 {
263 png_free(png_ptr, tmp);
264 png_free(png_ptr, chunkdata);
265 png_error(png_ptr,"Not enough memory to decompress chunk..");
266 }
267 png_memcpy(text, tmp, text_size);
268 png_free(png_ptr, tmp);
269 png_memcpy(text + text_size, png_ptr->zbuf,
270 (png_ptr->zbuf_size - png_ptr->zstream.avail_out));
271 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
272 *(text + text_size) = 0x00;
273 }
274 if (ret == Z_STREAM_END)
275 break;
276 else
277 {
278 png_ptr->zstream.next_out = png_ptr->zbuf;
279 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
280 }
281 }
282 }
283 if (ret != Z_STREAM_END)
284 {
285 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
286 char umsg[52];
287
288 if (ret == Z_BUF_ERROR)
289 png_snprintf(umsg, 52,
290 "Buffer error in compressed datastream in %s chunk",
291 png_ptr->chunk_name);
292 else if (ret == Z_DATA_ERROR)
293 png_snprintf(umsg, 52,
294 "Data error in compressed datastream in %s chunk",
295 png_ptr->chunk_name);
296 else
297 png_snprintf(umsg, 52,
298 "Incomplete compressed datastream in %s chunk",
299 png_ptr->chunk_name);
300 png_warning(png_ptr, umsg);
301 #else
302 png_warning(png_ptr,
303 "Incomplete compressed datastream in chunk other than IDAT");
304 #endif
305 text_size=prefix_size;
306 if (text == NULL)
307 {
308 text = (png_charp)png_malloc_warn(png_ptr, text_size+1);
309 if (text == NULL)
310 {
311 png_free(png_ptr, chunkdata);
312 png_error(png_ptr,"Not enough memory for text.");
313 }
314 png_memcpy(text, chunkdata, prefix_size);
315 }
316 *(text + text_size) = 0x00;
317 }
318
319 inflateReset(&png_ptr->zstream);
320 png_ptr->zstream.avail_in = 0;
321
322 png_free(png_ptr, chunkdata);
323 chunkdata = text;
324 *newlength=text_size;
325 }
326 else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
327 {
328 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
329 char umsg[50];
330
331 png_snprintf(umsg, 50,
332 "Unknown zTXt compression type %d", comp_type);
333 png_warning(png_ptr, umsg);
334 #else
335 png_warning(png_ptr, "Unknown zTXt compression type");
336 #endif
337
338 *(chunkdata + prefix_size) = 0x00;
339 *newlength=prefix_size;
340 }
341
342 return chunkdata;
343 }
344 #endif
345
346 /* read and check the IDHR chunk */
347 void /* PRIVATE */
png_handle_IHDR(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)348 png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
349 {
350 png_byte buf[13];
351 png_uint_32 width, height;
352 int bit_depth, color_type, compression_type, filter_type;
353 int interlace_type;
354
355 png_debug(1, "in png_handle_IHDR\n");
356
357 if (png_ptr->mode & PNG_HAVE_IHDR)
358 png_error(png_ptr, "Out of place IHDR");
359
360 /* check the length */
361 if (length != 13)
362 png_error(png_ptr, "Invalid IHDR chunk");
363
364 png_ptr->mode |= PNG_HAVE_IHDR;
365
366 png_crc_read(png_ptr, buf, 13);
367 png_crc_finish(png_ptr, 0);
368
369 width = png_get_uint_31(png_ptr, buf);
370 height = png_get_uint_31(png_ptr, buf + 4);
371 bit_depth = buf[8];
372 color_type = buf[9];
373 compression_type = buf[10];
374 filter_type = buf[11];
375 interlace_type = buf[12];
376
377 /* set internal variables */
378 png_ptr->width = width;
379 png_ptr->height = height;
380 png_ptr->bit_depth = (png_byte)bit_depth;
381 png_ptr->interlaced = (png_byte)interlace_type;
382 png_ptr->color_type = (png_byte)color_type;
383 #if defined(PNG_MNG_FEATURES_SUPPORTED)
384 png_ptr->filter_type = (png_byte)filter_type;
385 #endif
386 png_ptr->compression_type = (png_byte)compression_type;
387
388 /* find number of channels */
389 switch (png_ptr->color_type)
390 {
391 case PNG_COLOR_TYPE_GRAY:
392 case PNG_COLOR_TYPE_PALETTE:
393 png_ptr->channels = 1;
394 break;
395 case PNG_COLOR_TYPE_RGB:
396 png_ptr->channels = 3;
397 break;
398 case PNG_COLOR_TYPE_GRAY_ALPHA:
399 png_ptr->channels = 2;
400 break;
401 case PNG_COLOR_TYPE_RGB_ALPHA:
402 png_ptr->channels = 4;
403 break;
404 }
405
406 /* set up other useful info */
407 png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
408 png_ptr->channels);
409 png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->width);
410 png_debug1(3,"bit_depth = %d\n", png_ptr->bit_depth);
411 png_debug1(3,"channels = %d\n", png_ptr->channels);
412 png_debug1(3,"rowbytes = %lu\n", png_ptr->rowbytes);
413 png_set_IHDR(png_ptr, info_ptr, width, height, bit_depth,
414 color_type, interlace_type, compression_type, filter_type);
415 }
416
417 /* read and check the palette */
418 void /* PRIVATE */
png_handle_PLTE(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)419 png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
420 {
421 png_color palette[PNG_MAX_PALETTE_LENGTH];
422 int num, i;
423 #ifndef PNG_NO_POINTER_INDEXING
424 png_colorp pal_ptr;
425 #endif
426
427 png_debug(1, "in png_handle_PLTE\n");
428
429 if (!(png_ptr->mode & PNG_HAVE_IHDR))
430 png_error(png_ptr, "Missing IHDR before PLTE");
431 else if (png_ptr->mode & PNG_HAVE_IDAT)
432 {
433 png_warning(png_ptr, "Invalid PLTE after IDAT");
434 png_crc_finish(png_ptr, length);
435 return;
436 }
437 else if (png_ptr->mode & PNG_HAVE_PLTE)
438 png_error(png_ptr, "Duplicate PLTE chunk");
439
440 png_ptr->mode |= PNG_HAVE_PLTE;
441
442 if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
443 {
444 png_warning(png_ptr,
445 "Ignoring PLTE chunk in grayscale PNG");
446 png_crc_finish(png_ptr, length);
447 return;
448 }
449 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
450 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
451 {
452 png_crc_finish(png_ptr, length);
453 return;
454 }
455 #endif
456
457 if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
458 {
459 if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
460 {
461 png_warning(png_ptr, "Invalid palette chunk");
462 png_crc_finish(png_ptr, length);
463 return;
464 }
465 else
466 {
467 png_error(png_ptr, "Invalid palette chunk");
468 }
469 }
470
471 num = (int)length / 3;
472
473 #ifndef PNG_NO_POINTER_INDEXING
474 for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++)
475 {
476 png_byte buf[3];
477
478 png_crc_read(png_ptr, buf, 3);
479 pal_ptr->red = buf[0];
480 pal_ptr->green = buf[1];
481 pal_ptr->blue = buf[2];
482 }
483 #else
484 for (i = 0; i < num; i++)
485 {
486 png_byte buf[3];
487
488 png_crc_read(png_ptr, buf, 3);
489 /* don't depend upon png_color being any order */
490 palette[i].red = buf[0];
491 palette[i].green = buf[1];
492 palette[i].blue = buf[2];
493 }
494 #endif
495
496 /* If we actually NEED the PLTE chunk (ie for a paletted image), we do
497 whatever the normal CRC configuration tells us. However, if we
498 have an RGB image, the PLTE can be considered ancillary, so
499 we will act as though it is. */
500 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
501 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
502 #endif
503 {
504 png_crc_finish(png_ptr, 0);
505 }
506 #if !defined(PNG_READ_OPT_PLTE_SUPPORTED)
507 else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
508 {
509 /* If we don't want to use the data from an ancillary chunk,
510 we have two options: an error abort, or a warning and we
511 ignore the data in this chunk (which should be OK, since
512 it's considered ancillary for a RGB or RGBA image). */
513 if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
514 {
515 if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
516 {
517 png_chunk_error(png_ptr, "CRC error");
518 }
519 else
520 {
521 png_chunk_warning(png_ptr, "CRC error");
522 return;
523 }
524 }
525 /* Otherwise, we (optionally) emit a warning and use the chunk. */
526 else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
527 {
528 png_chunk_warning(png_ptr, "CRC error");
529 }
530 }
531 #endif
532
533 png_set_PLTE(png_ptr, info_ptr, palette, num);
534
535 #if defined(PNG_READ_tRNS_SUPPORTED)
536 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
537 {
538 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
539 {
540 if (png_ptr->num_trans > (png_uint_16)num)
541 {
542 png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
543 png_ptr->num_trans = (png_uint_16)num;
544 }
545 if (info_ptr->num_trans > (png_uint_16)num)
546 {
547 png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
548 info_ptr->num_trans = (png_uint_16)num;
549 }
550 }
551 }
552 #endif
553
554 }
555
556 void /* PRIVATE */
png_handle_IEND(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)557 png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
558 {
559 png_debug(1, "in png_handle_IEND\n");
560
561 if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
562 {
563 png_error(png_ptr, "No image in file");
564 }
565
566 png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
567
568 if (length != 0)
569 {
570 png_warning(png_ptr, "Incorrect IEND chunk length");
571 }
572 png_crc_finish(png_ptr, length);
573
574 info_ptr =info_ptr; /* quiet compiler warnings about unused info_ptr */
575 }
576
577 #if defined(PNG_READ_gAMA_SUPPORTED)
578 void /* PRIVATE */
png_handle_gAMA(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)579 png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
580 {
581 png_fixed_point igamma;
582 #ifdef PNG_FLOATING_POINT_SUPPORTED
583 float file_gamma;
584 #endif
585 png_byte buf[4];
586
587 png_debug(1, "in png_handle_gAMA\n");
588
589 if (!(png_ptr->mode & PNG_HAVE_IHDR))
590 png_error(png_ptr, "Missing IHDR before gAMA");
591 else if (png_ptr->mode & PNG_HAVE_IDAT)
592 {
593 png_warning(png_ptr, "Invalid gAMA after IDAT");
594 png_crc_finish(png_ptr, length);
595 return;
596 }
597 else if (png_ptr->mode & PNG_HAVE_PLTE)
598 /* Should be an error, but we can cope with it */
599 png_warning(png_ptr, "Out of place gAMA chunk");
600
601 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
602 #if defined(PNG_READ_sRGB_SUPPORTED)
603 && !(info_ptr->valid & PNG_INFO_sRGB)
604 #endif
605 )
606 {
607 png_warning(png_ptr, "Duplicate gAMA chunk");
608 png_crc_finish(png_ptr, length);
609 return;
610 }
611
612 if (length != 4)
613 {
614 png_warning(png_ptr, "Incorrect gAMA chunk length");
615 png_crc_finish(png_ptr, length);
616 return;
617 }
618
619 png_crc_read(png_ptr, buf, 4);
620 if (png_crc_finish(png_ptr, 0))
621 return;
622
623 igamma = (png_fixed_point)png_get_uint_32(buf);
624 /* check for zero gamma */
625 if (igamma == 0)
626 {
627 png_warning(png_ptr,
628 "Ignoring gAMA chunk with gamma=0");
629 return;
630 }
631
632 #if defined(PNG_READ_sRGB_SUPPORTED)
633 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
634 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
635 {
636 png_warning(png_ptr,
637 "Ignoring incorrect gAMA value when sRGB is also present");
638 #ifndef PNG_NO_CONSOLE_IO
639 fprintf(stderr, "gamma = (%d/100000)\n", (int)igamma);
640 #endif
641 return;
642 }
643 #endif /* PNG_READ_sRGB_SUPPORTED */
644
645 #ifdef PNG_FLOATING_POINT_SUPPORTED
646 file_gamma = (float)igamma / (float)100000.0;
647 # ifdef PNG_READ_GAMMA_SUPPORTED
648 png_ptr->gamma = file_gamma;
649 # endif
650 png_set_gAMA(png_ptr, info_ptr, file_gamma);
651 #endif
652 #ifdef PNG_FIXED_POINT_SUPPORTED
653 png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
654 #endif
655 }
656 #endif
657
658 #if defined(PNG_READ_sBIT_SUPPORTED)
659 void /* PRIVATE */
png_handle_sBIT(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)660 png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
661 {
662 png_size_t truelen;
663 png_byte buf[4];
664
665 png_debug(1, "in png_handle_sBIT\n");
666
667 buf[0] = buf[1] = buf[2] = buf[3] = 0;
668
669 if (!(png_ptr->mode & PNG_HAVE_IHDR))
670 png_error(png_ptr, "Missing IHDR before sBIT");
671 else if (png_ptr->mode & PNG_HAVE_IDAT)
672 {
673 png_warning(png_ptr, "Invalid sBIT after IDAT");
674 png_crc_finish(png_ptr, length);
675 return;
676 }
677 else if (png_ptr->mode & PNG_HAVE_PLTE)
678 {
679 /* Should be an error, but we can cope with it */
680 png_warning(png_ptr, "Out of place sBIT chunk");
681 }
682 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
683 {
684 png_warning(png_ptr, "Duplicate sBIT chunk");
685 png_crc_finish(png_ptr, length);
686 return;
687 }
688
689 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
690 truelen = 3;
691 else
692 truelen = (png_size_t)png_ptr->channels;
693
694 if (length != truelen || length > 4)
695 {
696 png_warning(png_ptr, "Incorrect sBIT chunk length");
697 png_crc_finish(png_ptr, length);
698 return;
699 }
700
701 png_crc_read(png_ptr, buf, truelen);
702 if (png_crc_finish(png_ptr, 0))
703 return;
704
705 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
706 {
707 png_ptr->sig_bit.red = buf[0];
708 png_ptr->sig_bit.green = buf[1];
709 png_ptr->sig_bit.blue = buf[2];
710 png_ptr->sig_bit.alpha = buf[3];
711 }
712 else
713 {
714 png_ptr->sig_bit.gray = buf[0];
715 png_ptr->sig_bit.red = buf[0];
716 png_ptr->sig_bit.green = buf[0];
717 png_ptr->sig_bit.blue = buf[0];
718 png_ptr->sig_bit.alpha = buf[1];
719 }
720 png_set_sBIT(png_ptr, info_ptr, &(png_ptr->sig_bit));
721 }
722 #endif
723
724 #if defined(PNG_READ_cHRM_SUPPORTED)
725 void /* PRIVATE */
png_handle_cHRM(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)726 png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
727 {
728 png_byte buf[4];
729 #ifdef PNG_FLOATING_POINT_SUPPORTED
730 float white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y;
731 #endif
732 png_fixed_point int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
733 int_y_green, int_x_blue, int_y_blue;
734
735 png_uint_32 uint_x, uint_y;
736
737 png_debug(1, "in png_handle_cHRM\n");
738
739 if (!(png_ptr->mode & PNG_HAVE_IHDR))
740 png_error(png_ptr, "Missing IHDR before cHRM");
741 else if (png_ptr->mode & PNG_HAVE_IDAT)
742 {
743 png_warning(png_ptr, "Invalid cHRM after IDAT");
744 png_crc_finish(png_ptr, length);
745 return;
746 }
747 else if (png_ptr->mode & PNG_HAVE_PLTE)
748 /* Should be an error, but we can cope with it */
749 png_warning(png_ptr, "Missing PLTE before cHRM");
750
751 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
752 #if defined(PNG_READ_sRGB_SUPPORTED)
753 && !(info_ptr->valid & PNG_INFO_sRGB)
754 #endif
755 )
756 {
757 png_warning(png_ptr, "Duplicate cHRM chunk");
758 png_crc_finish(png_ptr, length);
759 return;
760 }
761
762 if (length != 32)
763 {
764 png_warning(png_ptr, "Incorrect cHRM chunk length");
765 png_crc_finish(png_ptr, length);
766 return;
767 }
768
769 png_crc_read(png_ptr, buf, 4);
770 uint_x = png_get_uint_32(buf);
771
772 png_crc_read(png_ptr, buf, 4);
773 uint_y = png_get_uint_32(buf);
774
775 if (uint_x > 80000L || uint_y > 80000L ||
776 uint_x + uint_y > 100000L)
777 {
778 png_warning(png_ptr, "Invalid cHRM white point");
779 png_crc_finish(png_ptr, 24);
780 return;
781 }
782 int_x_white = (png_fixed_point)uint_x;
783 int_y_white = (png_fixed_point)uint_y;
784
785 png_crc_read(png_ptr, buf, 4);
786 uint_x = png_get_uint_32(buf);
787
788 png_crc_read(png_ptr, buf, 4);
789 uint_y = png_get_uint_32(buf);
790
791 if (uint_x + uint_y > 100000L)
792 {
793 png_warning(png_ptr, "Invalid cHRM red point");
794 png_crc_finish(png_ptr, 16);
795 return;
796 }
797 int_x_red = (png_fixed_point)uint_x;
798 int_y_red = (png_fixed_point)uint_y;
799
800 png_crc_read(png_ptr, buf, 4);
801 uint_x = png_get_uint_32(buf);
802
803 png_crc_read(png_ptr, buf, 4);
804 uint_y = png_get_uint_32(buf);
805
806 if (uint_x + uint_y > 100000L)
807 {
808 png_warning(png_ptr, "Invalid cHRM green point");
809 png_crc_finish(png_ptr, 8);
810 return;
811 }
812 int_x_green = (png_fixed_point)uint_x;
813 int_y_green = (png_fixed_point)uint_y;
814
815 png_crc_read(png_ptr, buf, 4);
816 uint_x = png_get_uint_32(buf);
817
818 png_crc_read(png_ptr, buf, 4);
819 uint_y = png_get_uint_32(buf);
820
821 if (uint_x + uint_y > 100000L)
822 {
823 png_warning(png_ptr, "Invalid cHRM blue point");
824 png_crc_finish(png_ptr, 0);
825 return;
826 }
827 int_x_blue = (png_fixed_point)uint_x;
828 int_y_blue = (png_fixed_point)uint_y;
829
830 #ifdef PNG_FLOATING_POINT_SUPPORTED
831 white_x = (float)int_x_white / (float)100000.0;
832 white_y = (float)int_y_white / (float)100000.0;
833 red_x = (float)int_x_red / (float)100000.0;
834 red_y = (float)int_y_red / (float)100000.0;
835 green_x = (float)int_x_green / (float)100000.0;
836 green_y = (float)int_y_green / (float)100000.0;
837 blue_x = (float)int_x_blue / (float)100000.0;
838 blue_y = (float)int_y_blue / (float)100000.0;
839 #endif
840
841 #if defined(PNG_READ_sRGB_SUPPORTED)
842 if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
843 {
844 if (PNG_OUT_OF_RANGE(int_x_white, 31270, 1000) ||
845 PNG_OUT_OF_RANGE(int_y_white, 32900, 1000) ||
846 PNG_OUT_OF_RANGE(int_x_red, 64000L, 1000) ||
847 PNG_OUT_OF_RANGE(int_y_red, 33000, 1000) ||
848 PNG_OUT_OF_RANGE(int_x_green, 30000, 1000) ||
849 PNG_OUT_OF_RANGE(int_y_green, 60000L, 1000) ||
850 PNG_OUT_OF_RANGE(int_x_blue, 15000, 1000) ||
851 PNG_OUT_OF_RANGE(int_y_blue, 6000, 1000))
852 {
853 png_warning(png_ptr,
854 "Ignoring incorrect cHRM value when sRGB is also present");
855 #ifndef PNG_NO_CONSOLE_IO
856 #ifdef PNG_FLOATING_POINT_SUPPORTED
857 fprintf(stderr,"wx=%f, wy=%f, rx=%f, ry=%f\n",
858 white_x, white_y, red_x, red_y);
859 fprintf(stderr,"gx=%f, gy=%f, bx=%f, by=%f\n",
860 green_x, green_y, blue_x, blue_y);
861 #else
862 fprintf(stderr,"wx=%ld, wy=%ld, rx=%ld, ry=%ld\n",
863 int_x_white, int_y_white, int_x_red, int_y_red);
864 fprintf(stderr,"gx=%ld, gy=%ld, bx=%ld, by=%ld\n",
865 int_x_green, int_y_green, int_x_blue, int_y_blue);
866 #endif
867 #endif /* PNG_NO_CONSOLE_IO */
868 }
869 png_crc_finish(png_ptr, 0);
870 return;
871 }
872 #endif /* PNG_READ_sRGB_SUPPORTED */
873
874 #ifdef PNG_FLOATING_POINT_SUPPORTED
875 png_set_cHRM(png_ptr, info_ptr,
876 white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y);
877 #endif
878 #ifdef PNG_FIXED_POINT_SUPPORTED
879 png_set_cHRM_fixed(png_ptr, info_ptr,
880 int_x_white, int_y_white, int_x_red, int_y_red, int_x_green,
881 int_y_green, int_x_blue, int_y_blue);
882 #endif
883 if (png_crc_finish(png_ptr, 0))
884 return;
885 }
886 #endif
887
888 #if defined(PNG_READ_sRGB_SUPPORTED)
889 void /* PRIVATE */
png_handle_sRGB(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)890 png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
891 {
892 int intent;
893 png_byte buf[1];
894
895 png_debug(1, "in png_handle_sRGB\n");
896
897 if (!(png_ptr->mode & PNG_HAVE_IHDR))
898 png_error(png_ptr, "Missing IHDR before sRGB");
899 else if (png_ptr->mode & PNG_HAVE_IDAT)
900 {
901 png_warning(png_ptr, "Invalid sRGB after IDAT");
902 png_crc_finish(png_ptr, length);
903 return;
904 }
905 else if (png_ptr->mode & PNG_HAVE_PLTE)
906 /* Should be an error, but we can cope with it */
907 png_warning(png_ptr, "Out of place sRGB chunk");
908
909 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
910 {
911 png_warning(png_ptr, "Duplicate sRGB chunk");
912 png_crc_finish(png_ptr, length);
913 return;
914 }
915
916 if (length != 1)
917 {
918 png_warning(png_ptr, "Incorrect sRGB chunk length");
919 png_crc_finish(png_ptr, length);
920 return;
921 }
922
923 png_crc_read(png_ptr, buf, 1);
924 if (png_crc_finish(png_ptr, 0))
925 return;
926
927 intent = buf[0];
928 /* check for bad intent */
929 if (intent >= PNG_sRGB_INTENT_LAST)
930 {
931 png_warning(png_ptr, "Unknown sRGB intent");
932 return;
933 }
934
935 #if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
936 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
937 {
938 png_fixed_point igamma;
939 #ifdef PNG_FIXED_POINT_SUPPORTED
940 igamma=info_ptr->int_gamma;
941 #else
942 # ifdef PNG_FLOATING_POINT_SUPPORTED
943 igamma=(png_fixed_point)(info_ptr->gamma * 100000.);
944 # endif
945 #endif
946 if (PNG_OUT_OF_RANGE(igamma, 45500L, 500))
947 {
948 png_warning(png_ptr,
949 "Ignoring incorrect gAMA value when sRGB is also present");
950 #ifndef PNG_NO_CONSOLE_IO
951 # ifdef PNG_FIXED_POINT_SUPPORTED
952 fprintf(stderr,"incorrect gamma=(%d/100000)\n",(int)png_ptr->int_gamma);
953 # else
954 # ifdef PNG_FLOATING_POINT_SUPPORTED
955 fprintf(stderr,"incorrect gamma=%f\n",png_ptr->gamma);
956 # endif
957 # endif
958 #endif
959 }
960 }
961 #endif /* PNG_READ_gAMA_SUPPORTED */
962
963 #ifdef PNG_READ_cHRM_SUPPORTED
964 #ifdef PNG_FIXED_POINT_SUPPORTED
965 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
966 if (PNG_OUT_OF_RANGE(info_ptr->int_x_white, 31270, 1000) ||
967 PNG_OUT_OF_RANGE(info_ptr->int_y_white, 32900, 1000) ||
968 PNG_OUT_OF_RANGE(info_ptr->int_x_red, 64000L, 1000) ||
969 PNG_OUT_OF_RANGE(info_ptr->int_y_red, 33000, 1000) ||
970 PNG_OUT_OF_RANGE(info_ptr->int_x_green, 30000, 1000) ||
971 PNG_OUT_OF_RANGE(info_ptr->int_y_green, 60000L, 1000) ||
972 PNG_OUT_OF_RANGE(info_ptr->int_x_blue, 15000, 1000) ||
973 PNG_OUT_OF_RANGE(info_ptr->int_y_blue, 6000, 1000))
974 {
975 png_warning(png_ptr,
976 "Ignoring incorrect cHRM value when sRGB is also present");
977 }
978 #endif /* PNG_FIXED_POINT_SUPPORTED */
979 #endif /* PNG_READ_cHRM_SUPPORTED */
980
981 png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
982 }
983 #endif /* PNG_READ_sRGB_SUPPORTED */
984
985 #if defined(PNG_READ_iCCP_SUPPORTED)
986 void /* PRIVATE */
png_handle_iCCP(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)987 png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
988 /* Note: this does not properly handle chunks that are > 64K under DOS */
989 {
990 png_charp chunkdata;
991 png_byte compression_type;
992 png_bytep pC;
993 png_charp profile;
994 png_uint_32 skip = 0;
995 png_uint_32 profile_size, profile_length;
996 png_size_t slength, prefix_length, data_length;
997
998 png_debug(1, "in png_handle_iCCP\n");
999
1000 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1001 png_error(png_ptr, "Missing IHDR before iCCP");
1002 else if (png_ptr->mode & PNG_HAVE_IDAT)
1003 {
1004 png_warning(png_ptr, "Invalid iCCP after IDAT");
1005 png_crc_finish(png_ptr, length);
1006 return;
1007 }
1008 else if (png_ptr->mode & PNG_HAVE_PLTE)
1009 /* Should be an error, but we can cope with it */
1010 png_warning(png_ptr, "Out of place iCCP chunk");
1011
1012 if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP))
1013 {
1014 png_warning(png_ptr, "Duplicate iCCP chunk");
1015 png_crc_finish(png_ptr, length);
1016 return;
1017 }
1018
1019 #ifdef PNG_MAX_MALLOC_64K
1020 if (length > (png_uint_32)65535L)
1021 {
1022 png_warning(png_ptr, "iCCP chunk too large to fit in memory");
1023 skip = length - (png_uint_32)65535L;
1024 length = (png_uint_32)65535L;
1025 }
1026 #endif
1027
1028 chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
1029 slength = (png_size_t)length;
1030 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1031
1032 if (png_crc_finish(png_ptr, skip))
1033 {
1034 png_free(png_ptr, chunkdata);
1035 return;
1036 }
1037
1038 chunkdata[slength] = 0x00;
1039
1040 for (profile = chunkdata; *profile; profile++)
1041 /* empty loop to find end of name */ ;
1042
1043 ++profile;
1044
1045 /* there should be at least one zero (the compression type byte)
1046 following the separator, and we should be on it */
1047 if ( profile >= chunkdata + slength - 1)
1048 {
1049 png_free(png_ptr, chunkdata);
1050 png_warning(png_ptr, "Malformed iCCP chunk");
1051 return;
1052 }
1053
1054 /* compression_type should always be zero */
1055 compression_type = *profile++;
1056 if (compression_type)
1057 {
1058 png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
1059 compression_type=0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
1060 wrote nonzero) */
1061 }
1062
1063 prefix_length = profile - chunkdata;
1064 chunkdata = png_decompress_chunk(png_ptr, compression_type, chunkdata,
1065 slength, prefix_length, &data_length);
1066
1067 profile_length = data_length - prefix_length;
1068
1069 if ( prefix_length > data_length || profile_length < 4)
1070 {
1071 png_free(png_ptr, chunkdata);
1072 png_warning(png_ptr, "Profile size field missing from iCCP chunk");
1073 return;
1074 }
1075
1076 /* Check the profile_size recorded in the first 32 bits of the ICC profile */
1077 pC = (png_bytep)(chunkdata+prefix_length);
1078 profile_size = ((*(pC ))<<24) |
1079 ((*(pC+1))<<16) |
1080 ((*(pC+2))<< 8) |
1081 ((*(pC+3)) );
1082
1083 if(profile_size < profile_length)
1084 profile_length = profile_size;
1085
1086 if(profile_size > profile_length)
1087 {
1088 png_free(png_ptr, chunkdata);
1089 png_warning(png_ptr, "Ignoring truncated iCCP profile.");
1090 return;
1091 }
1092
1093 png_set_iCCP(png_ptr, info_ptr, chunkdata, compression_type,
1094 chunkdata + prefix_length, profile_length);
1095 png_free(png_ptr, chunkdata);
1096 }
1097 #endif /* PNG_READ_iCCP_SUPPORTED */
1098
1099 #if defined(PNG_READ_sPLT_SUPPORTED)
1100 void /* PRIVATE */
png_handle_sPLT(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1101 png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1102 /* Note: this does not properly handle chunks that are > 64K under DOS */
1103 {
1104 png_bytep chunkdata;
1105 png_bytep entry_start;
1106 png_sPLT_t new_palette;
1107 #ifdef PNG_NO_POINTER_INDEXING
1108 png_sPLT_entryp pp;
1109 #endif
1110 int data_length, entry_size, i;
1111 png_uint_32 skip = 0;
1112 png_size_t slength;
1113
1114 png_debug(1, "in png_handle_sPLT\n");
1115
1116 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1117 png_error(png_ptr, "Missing IHDR before sPLT");
1118 else if (png_ptr->mode & PNG_HAVE_IDAT)
1119 {
1120 png_warning(png_ptr, "Invalid sPLT after IDAT");
1121 png_crc_finish(png_ptr, length);
1122 return;
1123 }
1124
1125 #ifdef PNG_MAX_MALLOC_64K
1126 if (length > (png_uint_32)65535L)
1127 {
1128 png_warning(png_ptr, "sPLT chunk too large to fit in memory");
1129 skip = length - (png_uint_32)65535L;
1130 length = (png_uint_32)65535L;
1131 }
1132 #endif
1133
1134 chunkdata = (png_bytep)png_malloc(png_ptr, length + 1);
1135 slength = (png_size_t)length;
1136 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1137
1138 if (png_crc_finish(png_ptr, skip))
1139 {
1140 png_free(png_ptr, chunkdata);
1141 return;
1142 }
1143
1144 chunkdata[slength] = 0x00;
1145
1146 for (entry_start = chunkdata; *entry_start; entry_start++)
1147 /* empty loop to find end of name */ ;
1148 ++entry_start;
1149
1150 /* a sample depth should follow the separator, and we should be on it */
1151 if (entry_start > chunkdata + slength - 2)
1152 {
1153 png_free(png_ptr, chunkdata);
1154 png_warning(png_ptr, "malformed sPLT chunk");
1155 return;
1156 }
1157
1158 new_palette.depth = *entry_start++;
1159 entry_size = (new_palette.depth == 8 ? 6 : 10);
1160 data_length = (slength - (entry_start - chunkdata));
1161
1162 /* integrity-check the data length */
1163 if (data_length % entry_size)
1164 {
1165 png_free(png_ptr, chunkdata);
1166 png_warning(png_ptr, "sPLT chunk has bad length");
1167 return;
1168 }
1169
1170 new_palette.nentries = (png_int_32) ( data_length / entry_size);
1171 if ((png_uint_32) new_palette.nentries > (png_uint_32) (PNG_SIZE_MAX /
1172 png_sizeof(png_sPLT_entry)))
1173 {
1174 png_warning(png_ptr, "sPLT chunk too long");
1175 return;
1176 }
1177 new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
1178 png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
1179 if (new_palette.entries == NULL)
1180 {
1181 png_warning(png_ptr, "sPLT chunk requires too much memory");
1182 return;
1183 }
1184
1185 #ifndef PNG_NO_POINTER_INDEXING
1186 for (i = 0; i < new_palette.nentries; i++)
1187 {
1188 png_sPLT_entryp pp = new_palette.entries + i;
1189
1190 if (new_palette.depth == 8)
1191 {
1192 pp->red = *entry_start++;
1193 pp->green = *entry_start++;
1194 pp->blue = *entry_start++;
1195 pp->alpha = *entry_start++;
1196 }
1197 else
1198 {
1199 pp->red = png_get_uint_16(entry_start); entry_start += 2;
1200 pp->green = png_get_uint_16(entry_start); entry_start += 2;
1201 pp->blue = png_get_uint_16(entry_start); entry_start += 2;
1202 pp->alpha = png_get_uint_16(entry_start); entry_start += 2;
1203 }
1204 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1205 }
1206 #else
1207 pp = new_palette.entries;
1208 for (i = 0; i < new_palette.nentries; i++)
1209 {
1210
1211 if (new_palette.depth == 8)
1212 {
1213 pp[i].red = *entry_start++;
1214 pp[i].green = *entry_start++;
1215 pp[i].blue = *entry_start++;
1216 pp[i].alpha = *entry_start++;
1217 }
1218 else
1219 {
1220 pp[i].red = png_get_uint_16(entry_start); entry_start += 2;
1221 pp[i].green = png_get_uint_16(entry_start); entry_start += 2;
1222 pp[i].blue = png_get_uint_16(entry_start); entry_start += 2;
1223 pp[i].alpha = png_get_uint_16(entry_start); entry_start += 2;
1224 }
1225 pp->frequency = png_get_uint_16(entry_start); entry_start += 2;
1226 }
1227 #endif
1228
1229 /* discard all chunk data except the name and stash that */
1230 new_palette.name = (png_charp)chunkdata;
1231
1232 png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
1233
1234 png_free(png_ptr, chunkdata);
1235 png_free(png_ptr, new_palette.entries);
1236 }
1237 #endif /* PNG_READ_sPLT_SUPPORTED */
1238
1239 #if defined(PNG_READ_tRNS_SUPPORTED)
1240 void /* PRIVATE */
png_handle_tRNS(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1241 png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1242 {
1243 png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
1244 int bit_mask;
1245
1246 png_debug(1, "in png_handle_tRNS\n");
1247
1248 /* For non-indexed color, mask off any bits in the tRNS value that
1249 * exceed the bit depth. Some creators were writing extra bits there.
1250 * This is not needed for indexed color. */
1251 bit_mask = (1 << png_ptr->bit_depth) - 1;
1252
1253 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1254 png_error(png_ptr, "Missing IHDR before tRNS");
1255 else if (png_ptr->mode & PNG_HAVE_IDAT)
1256 {
1257 png_warning(png_ptr, "Invalid tRNS after IDAT");
1258 png_crc_finish(png_ptr, length);
1259 return;
1260 }
1261 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1262 {
1263 png_warning(png_ptr, "Duplicate tRNS chunk");
1264 png_crc_finish(png_ptr, length);
1265 return;
1266 }
1267
1268 if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
1269 {
1270 png_byte buf[2];
1271
1272 if (length != 2)
1273 {
1274 png_warning(png_ptr, "Incorrect tRNS chunk length");
1275 png_crc_finish(png_ptr, length);
1276 return;
1277 }
1278
1279 png_crc_read(png_ptr, buf, 2);
1280 png_ptr->num_trans = 1;
1281 png_ptr->trans_values.gray = png_get_uint_16(buf) & bit_mask;
1282 }
1283 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
1284 {
1285 png_byte buf[6];
1286
1287 if (length != 6)
1288 {
1289 png_warning(png_ptr, "Incorrect tRNS chunk length");
1290 png_crc_finish(png_ptr, length);
1291 return;
1292 }
1293 png_crc_read(png_ptr, buf, (png_size_t)length);
1294 png_ptr->num_trans = 1;
1295 png_ptr->trans_values.red = png_get_uint_16(buf) & bit_mask;
1296 png_ptr->trans_values.green = png_get_uint_16(buf + 2) & bit_mask;
1297 png_ptr->trans_values.blue = png_get_uint_16(buf + 4) & bit_mask;
1298 }
1299 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1300 {
1301 if (!(png_ptr->mode & PNG_HAVE_PLTE))
1302 {
1303 /* Should be an error, but we can cope with it. */
1304 png_warning(png_ptr, "Missing PLTE before tRNS");
1305 }
1306 if (length > (png_uint_32)png_ptr->num_palette ||
1307 length > PNG_MAX_PALETTE_LENGTH)
1308 {
1309 png_warning(png_ptr, "Incorrect tRNS chunk length");
1310 png_crc_finish(png_ptr, length);
1311 return;
1312 }
1313 if (length == 0)
1314 {
1315 png_warning(png_ptr, "Zero length tRNS chunk");
1316 png_crc_finish(png_ptr, length);
1317 return;
1318 }
1319 png_crc_read(png_ptr, readbuf, (png_size_t)length);
1320 png_ptr->num_trans = (png_uint_16)length;
1321 }
1322 else
1323 {
1324 png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
1325 png_crc_finish(png_ptr, length);
1326 return;
1327 }
1328
1329 if (png_crc_finish(png_ptr, 0))
1330 {
1331 png_ptr->num_trans = 0;
1332 return;
1333 }
1334
1335 png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
1336 &(png_ptr->trans_values));
1337 }
1338 #endif
1339
1340 #if defined(PNG_READ_bKGD_SUPPORTED)
1341 void /* PRIVATE */
png_handle_bKGD(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1342 png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1343 {
1344 png_size_t truelen;
1345 png_byte buf[6];
1346
1347 png_debug(1, "in png_handle_bKGD\n");
1348
1349 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1350 png_error(png_ptr, "Missing IHDR before bKGD");
1351 else if (png_ptr->mode & PNG_HAVE_IDAT)
1352 {
1353 png_warning(png_ptr, "Invalid bKGD after IDAT");
1354 png_crc_finish(png_ptr, length);
1355 return;
1356 }
1357 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
1358 !(png_ptr->mode & PNG_HAVE_PLTE))
1359 {
1360 png_warning(png_ptr, "Missing PLTE before bKGD");
1361 png_crc_finish(png_ptr, length);
1362 return;
1363 }
1364 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
1365 {
1366 png_warning(png_ptr, "Duplicate bKGD chunk");
1367 png_crc_finish(png_ptr, length);
1368 return;
1369 }
1370
1371 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1372 truelen = 1;
1373 else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1374 truelen = 6;
1375 else
1376 truelen = 2;
1377
1378 if (length != truelen)
1379 {
1380 png_warning(png_ptr, "Incorrect bKGD chunk length");
1381 png_crc_finish(png_ptr, length);
1382 return;
1383 }
1384
1385 png_crc_read(png_ptr, buf, truelen);
1386 if (png_crc_finish(png_ptr, 0))
1387 return;
1388
1389 /* We convert the index value into RGB components so that we can allow
1390 * arbitrary RGB values for background when we have transparency, and
1391 * so it is easy to determine the RGB values of the background color
1392 * from the info_ptr struct. */
1393 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
1394 {
1395 png_ptr->background.index = buf[0];
1396 if(info_ptr->num_palette)
1397 {
1398 if(buf[0] > info_ptr->num_palette)
1399 {
1400 png_warning(png_ptr, "Incorrect bKGD chunk index value");
1401 return;
1402 }
1403 png_ptr->background.red =
1404 (png_uint_16)png_ptr->palette[buf[0]].red;
1405 png_ptr->background.green =
1406 (png_uint_16)png_ptr->palette[buf[0]].green;
1407 png_ptr->background.blue =
1408 (png_uint_16)png_ptr->palette[buf[0]].blue;
1409 }
1410 }
1411 else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
1412 {
1413 png_ptr->background.red =
1414 png_ptr->background.green =
1415 png_ptr->background.blue =
1416 png_ptr->background.gray = png_get_uint_16(buf);
1417 }
1418 else
1419 {
1420 png_ptr->background.red = png_get_uint_16(buf);
1421 png_ptr->background.green = png_get_uint_16(buf + 2);
1422 png_ptr->background.blue = png_get_uint_16(buf + 4);
1423 }
1424
1425 png_set_bKGD(png_ptr, info_ptr, &(png_ptr->background));
1426 }
1427 #endif
1428
1429 #if defined(PNG_READ_hIST_SUPPORTED)
1430 void /* PRIVATE */
png_handle_hIST(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1431 png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1432 {
1433 unsigned int num, i;
1434 png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
1435
1436 png_debug(1, "in png_handle_hIST\n");
1437
1438 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1439 png_error(png_ptr, "Missing IHDR before hIST");
1440 else if (png_ptr->mode & PNG_HAVE_IDAT)
1441 {
1442 png_warning(png_ptr, "Invalid hIST after IDAT");
1443 png_crc_finish(png_ptr, length);
1444 return;
1445 }
1446 else if (!(png_ptr->mode & PNG_HAVE_PLTE))
1447 {
1448 png_warning(png_ptr, "Missing PLTE before hIST");
1449 png_crc_finish(png_ptr, length);
1450 return;
1451 }
1452 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
1453 {
1454 png_warning(png_ptr, "Duplicate hIST chunk");
1455 png_crc_finish(png_ptr, length);
1456 return;
1457 }
1458
1459 num = length / 2 ;
1460 if (num != (unsigned int) png_ptr->num_palette || num >
1461 (unsigned int) PNG_MAX_PALETTE_LENGTH)
1462 {
1463 png_warning(png_ptr, "Incorrect hIST chunk length");
1464 png_crc_finish(png_ptr, length);
1465 return;
1466 }
1467
1468 for (i = 0; i < num; i++)
1469 {
1470 png_byte buf[2];
1471
1472 png_crc_read(png_ptr, buf, 2);
1473 readbuf[i] = png_get_uint_16(buf);
1474 }
1475
1476 if (png_crc_finish(png_ptr, 0))
1477 return;
1478
1479 png_set_hIST(png_ptr, info_ptr, readbuf);
1480 }
1481 #endif
1482
1483 #if defined(PNG_READ_pHYs_SUPPORTED)
1484 void /* PRIVATE */
png_handle_pHYs(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1485 png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1486 {
1487 png_byte buf[9];
1488 png_uint_32 res_x, res_y;
1489 int unit_type;
1490
1491 png_debug(1, "in png_handle_pHYs\n");
1492
1493 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1494 png_error(png_ptr, "Missing IHDR before pHYs");
1495 else if (png_ptr->mode & PNG_HAVE_IDAT)
1496 {
1497 png_warning(png_ptr, "Invalid pHYs after IDAT");
1498 png_crc_finish(png_ptr, length);
1499 return;
1500 }
1501 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
1502 {
1503 png_warning(png_ptr, "Duplicate pHYs chunk");
1504 png_crc_finish(png_ptr, length);
1505 return;
1506 }
1507
1508 if (length != 9)
1509 {
1510 png_warning(png_ptr, "Incorrect pHYs chunk length");
1511 png_crc_finish(png_ptr, length);
1512 return;
1513 }
1514
1515 png_crc_read(png_ptr, buf, 9);
1516 if (png_crc_finish(png_ptr, 0))
1517 return;
1518
1519 res_x = png_get_uint_32(buf);
1520 res_y = png_get_uint_32(buf + 4);
1521 unit_type = buf[8];
1522 png_set_pHYs(png_ptr, info_ptr, res_x, res_y, unit_type);
1523 }
1524 #endif
1525
1526 #if defined(PNG_READ_oFFs_SUPPORTED)
1527 void /* PRIVATE */
png_handle_oFFs(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1528 png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1529 {
1530 png_byte buf[9];
1531 png_int_32 offset_x, offset_y;
1532 int unit_type;
1533
1534 png_debug(1, "in png_handle_oFFs\n");
1535
1536 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1537 png_error(png_ptr, "Missing IHDR before oFFs");
1538 else if (png_ptr->mode & PNG_HAVE_IDAT)
1539 {
1540 png_warning(png_ptr, "Invalid oFFs after IDAT");
1541 png_crc_finish(png_ptr, length);
1542 return;
1543 }
1544 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
1545 {
1546 png_warning(png_ptr, "Duplicate oFFs chunk");
1547 png_crc_finish(png_ptr, length);
1548 return;
1549 }
1550
1551 if (length != 9)
1552 {
1553 png_warning(png_ptr, "Incorrect oFFs chunk length");
1554 png_crc_finish(png_ptr, length);
1555 return;
1556 }
1557
1558 png_crc_read(png_ptr, buf, 9);
1559 if (png_crc_finish(png_ptr, 0))
1560 return;
1561
1562 offset_x = png_get_int_32(buf);
1563 offset_y = png_get_int_32(buf + 4);
1564 unit_type = buf[8];
1565 png_set_oFFs(png_ptr, info_ptr, offset_x, offset_y, unit_type);
1566 }
1567 #endif
1568
1569 #if defined(PNG_READ_pCAL_SUPPORTED)
1570 /* read the pCAL chunk (described in the PNG Extensions document) */
1571 void /* PRIVATE */
png_handle_pCAL(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1572 png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1573 {
1574 png_charp purpose;
1575 png_int_32 X0, X1;
1576 png_byte type, nparams;
1577 png_charp buf, units, endptr;
1578 png_charpp params;
1579 png_size_t slength;
1580 int i;
1581
1582 png_debug(1, "in png_handle_pCAL\n");
1583
1584 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1585 png_error(png_ptr, "Missing IHDR before pCAL");
1586 else if (png_ptr->mode & PNG_HAVE_IDAT)
1587 {
1588 png_warning(png_ptr, "Invalid pCAL after IDAT");
1589 png_crc_finish(png_ptr, length);
1590 return;
1591 }
1592 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
1593 {
1594 png_warning(png_ptr, "Duplicate pCAL chunk");
1595 png_crc_finish(png_ptr, length);
1596 return;
1597 }
1598
1599 png_debug1(2, "Allocating and reading pCAL chunk data (%lu bytes)\n",
1600 length + 1);
1601 purpose = (png_charp)png_malloc_warn(png_ptr, length + 1);
1602 if (purpose == NULL)
1603 {
1604 png_warning(png_ptr, "No memory for pCAL purpose.");
1605 return;
1606 }
1607 slength = (png_size_t)length;
1608 png_crc_read(png_ptr, (png_bytep)purpose, slength);
1609
1610 if (png_crc_finish(png_ptr, 0))
1611 {
1612 png_free(png_ptr, purpose);
1613 return;
1614 }
1615
1616 purpose[slength] = 0x00; /* null terminate the last string */
1617
1618 png_debug(3, "Finding end of pCAL purpose string\n");
1619 for (buf = purpose; *buf; buf++)
1620 /* empty loop */ ;
1621
1622 endptr = purpose + slength;
1623
1624 /* We need to have at least 12 bytes after the purpose string
1625 in order to get the parameter information. */
1626 if (endptr <= buf + 12)
1627 {
1628 png_warning(png_ptr, "Invalid pCAL data");
1629 png_free(png_ptr, purpose);
1630 return;
1631 }
1632
1633 png_debug(3, "Reading pCAL X0, X1, type, nparams, and units\n");
1634 X0 = png_get_int_32((png_bytep)buf+1);
1635 X1 = png_get_int_32((png_bytep)buf+5);
1636 type = buf[9];
1637 nparams = buf[10];
1638 units = buf + 11;
1639
1640 png_debug(3, "Checking pCAL equation type and number of parameters\n");
1641 /* Check that we have the right number of parameters for known
1642 equation types. */
1643 if ((type == PNG_EQUATION_LINEAR && nparams != 2) ||
1644 (type == PNG_EQUATION_BASE_E && nparams != 3) ||
1645 (type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
1646 (type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
1647 {
1648 png_warning(png_ptr, "Invalid pCAL parameters for equation type");
1649 png_free(png_ptr, purpose);
1650 return;
1651 }
1652 else if (type >= PNG_EQUATION_LAST)
1653 {
1654 png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
1655 }
1656
1657 for (buf = units; *buf; buf++)
1658 /* Empty loop to move past the units string. */ ;
1659
1660 png_debug(3, "Allocating pCAL parameters array\n");
1661 params = (png_charpp)png_malloc_warn(png_ptr, (png_uint_32)(nparams
1662 *png_sizeof(png_charp))) ;
1663 if (params == NULL)
1664 {
1665 png_free(png_ptr, purpose);
1666 png_warning(png_ptr, "No memory for pCAL params.");
1667 return;
1668 }
1669
1670 /* Get pointers to the start of each parameter string. */
1671 for (i = 0; i < (int)nparams; i++)
1672 {
1673 buf++; /* Skip the null string terminator from previous parameter. */
1674
1675 png_debug1(3, "Reading pCAL parameter %d\n", i);
1676 for (params[i] = buf; *buf != 0x00 && buf <= endptr; buf++)
1677 /* Empty loop to move past each parameter string */ ;
1678
1679 /* Make sure we haven't run out of data yet */
1680 if (buf > endptr)
1681 {
1682 png_warning(png_ptr, "Invalid pCAL data");
1683 png_free(png_ptr, purpose);
1684 png_free(png_ptr, params);
1685 return;
1686 }
1687 }
1688
1689 png_set_pCAL(png_ptr, info_ptr, purpose, X0, X1, type, nparams,
1690 units, params);
1691
1692 png_free(png_ptr, purpose);
1693 png_free(png_ptr, params);
1694 }
1695 #endif
1696
1697 #if defined(PNG_READ_sCAL_SUPPORTED)
1698 /* read the sCAL chunk */
1699 void /* PRIVATE */
png_handle_sCAL(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1700 png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1701 {
1702 png_charp buffer, ep;
1703 #ifdef PNG_FLOATING_POINT_SUPPORTED
1704 double width, height;
1705 png_charp vp;
1706 #else
1707 #ifdef PNG_FIXED_POINT_SUPPORTED
1708 png_charp swidth, sheight;
1709 #endif
1710 #endif
1711 png_size_t slength;
1712
1713 png_debug(1, "in png_handle_sCAL\n");
1714
1715 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1716 png_error(png_ptr, "Missing IHDR before sCAL");
1717 else if (png_ptr->mode & PNG_HAVE_IDAT)
1718 {
1719 png_warning(png_ptr, "Invalid sCAL after IDAT");
1720 png_crc_finish(png_ptr, length);
1721 return;
1722 }
1723 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
1724 {
1725 png_warning(png_ptr, "Duplicate sCAL chunk");
1726 png_crc_finish(png_ptr, length);
1727 return;
1728 }
1729
1730 png_debug1(2, "Allocating and reading sCAL chunk data (%lu bytes)\n",
1731 length + 1);
1732 buffer = (png_charp)png_malloc_warn(png_ptr, length + 1);
1733 if (buffer == NULL)
1734 {
1735 png_warning(png_ptr, "Out of memory while processing sCAL chunk");
1736 return;
1737 }
1738 slength = (png_size_t)length;
1739 png_crc_read(png_ptr, (png_bytep)buffer, slength);
1740
1741 if (png_crc_finish(png_ptr, 0))
1742 {
1743 png_free(png_ptr, buffer);
1744 return;
1745 }
1746
1747 buffer[slength] = 0x00; /* null terminate the last string */
1748
1749 ep = buffer + 1; /* skip unit byte */
1750
1751 #ifdef PNG_FLOATING_POINT_SUPPORTED
1752 width = png_strtod(png_ptr, ep, &vp);
1753 if (*vp)
1754 {
1755 png_warning(png_ptr, "malformed width string in sCAL chunk");
1756 return;
1757 }
1758 #else
1759 #ifdef PNG_FIXED_POINT_SUPPORTED
1760 swidth = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1761 if (swidth == NULL)
1762 {
1763 png_warning(png_ptr, "Out of memory while processing sCAL chunk width");
1764 return;
1765 }
1766 png_memcpy(swidth, ep, (png_size_t)png_strlen(ep));
1767 #endif
1768 #endif
1769
1770 for (ep = buffer; *ep; ep++)
1771 /* empty loop */ ;
1772 ep++;
1773
1774 #ifdef PNG_FLOATING_POINT_SUPPORTED
1775 height = png_strtod(png_ptr, ep, &vp);
1776 if (*vp)
1777 {
1778 png_warning(png_ptr, "malformed height string in sCAL chunk");
1779 return;
1780 }
1781 #else
1782 #ifdef PNG_FIXED_POINT_SUPPORTED
1783 sheight = (png_charp)png_malloc_warn(png_ptr, png_strlen(ep) + 1);
1784 if (swidth == NULL)
1785 {
1786 png_warning(png_ptr, "Out of memory while processing sCAL chunk height");
1787 return;
1788 }
1789 png_memcpy(sheight, ep, (png_size_t)png_strlen(ep));
1790 #endif
1791 #endif
1792
1793 if (buffer + slength < ep
1794 #ifdef PNG_FLOATING_POINT_SUPPORTED
1795 || width <= 0. || height <= 0.
1796 #endif
1797 )
1798 {
1799 png_warning(png_ptr, "Invalid sCAL data");
1800 png_free(png_ptr, buffer);
1801 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1802 png_free(png_ptr, swidth);
1803 png_free(png_ptr, sheight);
1804 #endif
1805 return;
1806 }
1807
1808
1809 #ifdef PNG_FLOATING_POINT_SUPPORTED
1810 png_set_sCAL(png_ptr, info_ptr, buffer[0], width, height);
1811 #else
1812 #ifdef PNG_FIXED_POINT_SUPPORTED
1813 png_set_sCAL_s(png_ptr, info_ptr, buffer[0], swidth, sheight);
1814 #endif
1815 #endif
1816
1817 png_free(png_ptr, buffer);
1818 #if defined(PNG_FIXED_POINT_SUPPORTED) && !defined(PNG_FLOATING_POINT_SUPPORTED)
1819 png_free(png_ptr, swidth);
1820 png_free(png_ptr, sheight);
1821 #endif
1822 }
1823 #endif
1824
1825 #if defined(PNG_READ_tIME_SUPPORTED)
1826 void /* PRIVATE */
png_handle_tIME(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1827 png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1828 {
1829 png_byte buf[7];
1830 png_time mod_time;
1831
1832 png_debug(1, "in png_handle_tIME\n");
1833
1834 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1835 png_error(png_ptr, "Out of place tIME chunk");
1836 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
1837 {
1838 png_warning(png_ptr, "Duplicate tIME chunk");
1839 png_crc_finish(png_ptr, length);
1840 return;
1841 }
1842
1843 if (png_ptr->mode & PNG_HAVE_IDAT)
1844 png_ptr->mode |= PNG_AFTER_IDAT;
1845
1846 if (length != 7)
1847 {
1848 png_warning(png_ptr, "Incorrect tIME chunk length");
1849 png_crc_finish(png_ptr, length);
1850 return;
1851 }
1852
1853 png_crc_read(png_ptr, buf, 7);
1854 if (png_crc_finish(png_ptr, 0))
1855 return;
1856
1857 mod_time.second = buf[6];
1858 mod_time.minute = buf[5];
1859 mod_time.hour = buf[4];
1860 mod_time.day = buf[3];
1861 mod_time.month = buf[2];
1862 mod_time.year = png_get_uint_16(buf);
1863
1864 png_set_tIME(png_ptr, info_ptr, &mod_time);
1865 }
1866 #endif
1867
1868 #if defined(PNG_READ_tEXt_SUPPORTED)
1869 /* Note: this does not properly handle chunks that are > 64K under DOS */
1870 void /* PRIVATE */
png_handle_tEXt(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1871 png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1872 {
1873 png_textp text_ptr;
1874 png_charp key;
1875 png_charp text;
1876 png_uint_32 skip = 0;
1877 png_size_t slength;
1878 int ret;
1879
1880 png_debug(1, "in png_handle_tEXt\n");
1881
1882 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1883 png_error(png_ptr, "Missing IHDR before tEXt");
1884
1885 if (png_ptr->mode & PNG_HAVE_IDAT)
1886 png_ptr->mode |= PNG_AFTER_IDAT;
1887
1888 #ifdef PNG_MAX_MALLOC_64K
1889 if (length > (png_uint_32)65535L)
1890 {
1891 png_warning(png_ptr, "tEXt chunk too large to fit in memory");
1892 skip = length - (png_uint_32)65535L;
1893 length = (png_uint_32)65535L;
1894 }
1895 #endif
1896
1897 key = (png_charp)png_malloc_warn(png_ptr, length + 1);
1898 if (key == NULL)
1899 {
1900 png_warning(png_ptr, "No memory to process text chunk.");
1901 return;
1902 }
1903 slength = (png_size_t)length;
1904 png_crc_read(png_ptr, (png_bytep)key, slength);
1905
1906 if (png_crc_finish(png_ptr, skip))
1907 {
1908 png_free(png_ptr, key);
1909 return;
1910 }
1911
1912 key[slength] = 0x00;
1913
1914 for (text = key; *text; text++)
1915 /* empty loop to find end of key */ ;
1916
1917 if (text != key + slength)
1918 text++;
1919
1920 text_ptr = (png_textp)png_malloc_warn(png_ptr,
1921 (png_uint_32)png_sizeof(png_text));
1922 if (text_ptr == NULL)
1923 {
1924 png_warning(png_ptr, "Not enough memory to process text chunk.");
1925 png_free(png_ptr, key);
1926 return;
1927 }
1928 text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
1929 text_ptr->key = key;
1930 #ifdef PNG_iTXt_SUPPORTED
1931 text_ptr->lang = NULL;
1932 text_ptr->lang_key = NULL;
1933 text_ptr->itxt_length = 0;
1934 #endif
1935 text_ptr->text = text;
1936 text_ptr->text_length = png_strlen(text);
1937
1938 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
1939
1940 png_free(png_ptr, key);
1941 png_free(png_ptr, text_ptr);
1942 if (ret)
1943 png_warning(png_ptr, "Insufficient memory to process text chunk.");
1944 }
1945 #endif
1946
1947 #if defined(PNG_READ_zTXt_SUPPORTED)
1948 /* note: this does not correctly handle chunks that are > 64K under DOS */
1949 void /* PRIVATE */
png_handle_zTXt(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)1950 png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
1951 {
1952 png_textp text_ptr;
1953 png_charp chunkdata;
1954 png_charp text;
1955 int comp_type;
1956 int ret;
1957 png_size_t slength, prefix_len, data_len;
1958
1959 png_debug(1, "in png_handle_zTXt\n");
1960 if (!(png_ptr->mode & PNG_HAVE_IHDR))
1961 png_error(png_ptr, "Missing IHDR before zTXt");
1962
1963 if (png_ptr->mode & PNG_HAVE_IDAT)
1964 png_ptr->mode |= PNG_AFTER_IDAT;
1965
1966 #ifdef PNG_MAX_MALLOC_64K
1967 /* We will no doubt have problems with chunks even half this size, but
1968 there is no hard and fast rule to tell us where to stop. */
1969 if (length > (png_uint_32)65535L)
1970 {
1971 png_warning(png_ptr,"zTXt chunk too large to fit in memory");
1972 png_crc_finish(png_ptr, length);
1973 return;
1974 }
1975 #endif
1976
1977 chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
1978 if (chunkdata == NULL)
1979 {
1980 png_warning(png_ptr,"Out of memory processing zTXt chunk.");
1981 return;
1982 }
1983 slength = (png_size_t)length;
1984 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
1985 if (png_crc_finish(png_ptr, 0))
1986 {
1987 png_free(png_ptr, chunkdata);
1988 return;
1989 }
1990
1991 chunkdata[slength] = 0x00;
1992
1993 for (text = chunkdata; *text; text++)
1994 /* empty loop */ ;
1995
1996 /* zTXt must have some text after the chunkdataword */
1997 if (text == chunkdata + slength - 1)
1998 {
1999 png_warning(png_ptr, "Truncated zTXt chunk");
2000 png_free(png_ptr, chunkdata);
2001 return;
2002 }
2003 else
2004 {
2005 comp_type = *(++text);
2006 if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
2007 {
2008 png_warning(png_ptr, "Unknown compression type in zTXt chunk");
2009 comp_type = PNG_TEXT_COMPRESSION_zTXt;
2010 }
2011 text++; /* skip the compression_method byte */
2012 }
2013 prefix_len = text - chunkdata;
2014
2015 chunkdata = (png_charp)png_decompress_chunk(png_ptr, comp_type, chunkdata,
2016 (png_size_t)length, prefix_len, &data_len);
2017
2018 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2019 (png_uint_32)png_sizeof(png_text));
2020 if (text_ptr == NULL)
2021 {
2022 png_warning(png_ptr,"Not enough memory to process zTXt chunk.");
2023 png_free(png_ptr, chunkdata);
2024 return;
2025 }
2026 text_ptr->compression = comp_type;
2027 text_ptr->key = chunkdata;
2028 #ifdef PNG_iTXt_SUPPORTED
2029 text_ptr->lang = NULL;
2030 text_ptr->lang_key = NULL;
2031 text_ptr->itxt_length = 0;
2032 #endif
2033 text_ptr->text = chunkdata + prefix_len;
2034 text_ptr->text_length = data_len;
2035
2036 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2037
2038 png_free(png_ptr, text_ptr);
2039 png_free(png_ptr, chunkdata);
2040 if (ret)
2041 png_error(png_ptr, "Insufficient memory to store zTXt chunk.");
2042 }
2043 #endif
2044
2045 #if defined(PNG_READ_iTXt_SUPPORTED)
2046 /* note: this does not correctly handle chunks that are > 64K under DOS */
2047 void /* PRIVATE */
png_handle_iTXt(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)2048 png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2049 {
2050 png_textp text_ptr;
2051 png_charp chunkdata;
2052 png_charp key, lang, text, lang_key;
2053 int comp_flag;
2054 int comp_type = 0;
2055 int ret;
2056 png_size_t slength, prefix_len, data_len;
2057
2058 png_debug(1, "in png_handle_iTXt\n");
2059
2060 if (!(png_ptr->mode & PNG_HAVE_IHDR))
2061 png_error(png_ptr, "Missing IHDR before iTXt");
2062
2063 if (png_ptr->mode & PNG_HAVE_IDAT)
2064 png_ptr->mode |= PNG_AFTER_IDAT;
2065
2066 #ifdef PNG_MAX_MALLOC_64K
2067 /* We will no doubt have problems with chunks even half this size, but
2068 there is no hard and fast rule to tell us where to stop. */
2069 if (length > (png_uint_32)65535L)
2070 {
2071 png_warning(png_ptr,"iTXt chunk too large to fit in memory");
2072 png_crc_finish(png_ptr, length);
2073 return;
2074 }
2075 #endif
2076
2077 chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
2078 if (chunkdata == NULL)
2079 {
2080 png_warning(png_ptr, "No memory to process iTXt chunk.");
2081 return;
2082 }
2083 slength = (png_size_t)length;
2084 png_crc_read(png_ptr, (png_bytep)chunkdata, slength);
2085 if (png_crc_finish(png_ptr, 0))
2086 {
2087 png_free(png_ptr, chunkdata);
2088 return;
2089 }
2090
2091 chunkdata[slength] = 0x00;
2092
2093 for (lang = chunkdata; *lang; lang++)
2094 /* empty loop */ ;
2095 lang++; /* skip NUL separator */
2096
2097 /* iTXt must have a language tag (possibly empty), two compression bytes,
2098 translated keyword (possibly empty), and possibly some text after the
2099 keyword */
2100
2101 if (lang >= chunkdata + slength - 3)
2102 {
2103 png_warning(png_ptr, "Truncated iTXt chunk");
2104 png_free(png_ptr, chunkdata);
2105 return;
2106 }
2107 else
2108 {
2109 comp_flag = *lang++;
2110 comp_type = *lang++;
2111 }
2112
2113 for (lang_key = lang; *lang_key; lang_key++)
2114 /* empty loop */ ;
2115 lang_key++; /* skip NUL separator */
2116
2117 for (text = lang_key; *text; text++)
2118 /* empty loop */ ;
2119 text++; /* skip NUL separator */
2120 if (text >= chunkdata + slength)
2121 {
2122 png_warning(png_ptr, "Malformed iTXt chunk");
2123 png_free(png_ptr, chunkdata);
2124 return;
2125 }
2126
2127 prefix_len = text - chunkdata;
2128
2129 key=chunkdata;
2130 if (comp_flag)
2131 chunkdata = png_decompress_chunk(png_ptr, comp_type, chunkdata,
2132 (size_t)length, prefix_len, &data_len);
2133 else
2134 data_len=png_strlen(chunkdata + prefix_len);
2135 text_ptr = (png_textp)png_malloc_warn(png_ptr,
2136 (png_uint_32)png_sizeof(png_text));
2137 if (text_ptr == NULL)
2138 {
2139 png_warning(png_ptr,"Not enough memory to process iTXt chunk.");
2140 png_free(png_ptr, chunkdata);
2141 return;
2142 }
2143 text_ptr->compression = (int)comp_flag + 1;
2144 text_ptr->lang_key = chunkdata+(lang_key-key);
2145 text_ptr->lang = chunkdata+(lang-key);
2146 text_ptr->itxt_length = data_len;
2147 text_ptr->text_length = 0;
2148 text_ptr->key = chunkdata;
2149 text_ptr->text = chunkdata + prefix_len;
2150
2151 ret=png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
2152
2153 png_free(png_ptr, text_ptr);
2154 png_free(png_ptr, chunkdata);
2155 if (ret)
2156 png_error(png_ptr, "Insufficient memory to store iTXt chunk.");
2157 }
2158 #endif
2159
2160 /* This function is called when we haven't found a handler for a
2161 chunk. If there isn't a problem with the chunk itself (ie bad
2162 chunk name, CRC, or a critical chunk), the chunk is silently ignored
2163 -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
2164 case it will be saved away to be written out later. */
2165 void /* PRIVATE */
png_handle_unknown(png_structp png_ptr,png_infop info_ptr,png_uint_32 length)2166 png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
2167 {
2168 png_uint_32 skip = 0;
2169
2170 png_debug(1, "in png_handle_unknown\n");
2171
2172 if (png_ptr->mode & PNG_HAVE_IDAT)
2173 {
2174 #ifdef PNG_USE_LOCAL_ARRAYS
2175 PNG_CONST PNG_IDAT;
2176 #endif
2177 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) /* not an IDAT */
2178 png_ptr->mode |= PNG_AFTER_IDAT;
2179 }
2180
2181 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
2182
2183 if (!(png_ptr->chunk_name[0] & 0x20))
2184 {
2185 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2186 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2187 PNG_HANDLE_CHUNK_ALWAYS
2188 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2189 && png_ptr->read_user_chunk_fn == NULL
2190 #endif
2191 )
2192 #endif
2193 png_chunk_error(png_ptr, "unknown critical chunk");
2194 }
2195
2196 #if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
2197 if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) ||
2198 (png_ptr->read_user_chunk_fn != NULL))
2199 {
2200 #ifdef PNG_MAX_MALLOC_64K
2201 if (length > (png_uint_32)65535L)
2202 {
2203 png_warning(png_ptr, "unknown chunk too large to fit in memory");
2204 skip = length - (png_uint_32)65535L;
2205 length = (png_uint_32)65535L;
2206 }
2207 #endif
2208 png_strncpy((png_charp)png_ptr->unknown_chunk.name,
2209 (png_charp)png_ptr->chunk_name,
2210 png_sizeof((png_charp)png_ptr->chunk_name));
2211 png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
2212 png_ptr->unknown_chunk.size = (png_size_t)length;
2213 png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length);
2214 #if defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2215 if(png_ptr->read_user_chunk_fn != NULL)
2216 {
2217 /* callback to user unknown chunk handler */
2218 int ret;
2219 ret = (*(png_ptr->read_user_chunk_fn))
2220 (png_ptr, &png_ptr->unknown_chunk);
2221 if (ret < 0)
2222 png_chunk_error(png_ptr, "error in user chunk");
2223 if (ret == 0)
2224 {
2225 if (!(png_ptr->chunk_name[0] & 0x20))
2226 if(png_handle_as_unknown(png_ptr, png_ptr->chunk_name) !=
2227 PNG_HANDLE_CHUNK_ALWAYS)
2228 png_chunk_error(png_ptr, "unknown critical chunk");
2229 png_set_unknown_chunks(png_ptr, info_ptr,
2230 &png_ptr->unknown_chunk, 1);
2231 }
2232 }
2233 #else
2234 png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
2235 #endif
2236 png_free(png_ptr, png_ptr->unknown_chunk.data);
2237 png_ptr->unknown_chunk.data = NULL;
2238 }
2239 else
2240 #endif
2241 skip = length;
2242
2243 png_crc_finish(png_ptr, skip);
2244
2245 #if !defined(PNG_READ_USER_CHUNKS_SUPPORTED)
2246 info_ptr = info_ptr; /* quiet compiler warnings about unused info_ptr */
2247 #endif
2248 }
2249
2250 /* This function is called to verify that a chunk name is valid.
2251 This function can't have the "critical chunk check" incorporated
2252 into it, since in the future we will need to be able to call user
2253 functions to handle unknown critical chunks after we check that
2254 the chunk name itself is valid. */
2255
2256 #define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
2257
2258 void /* PRIVATE */
png_check_chunk_name(png_structp png_ptr,png_bytep chunk_name)2259 png_check_chunk_name(png_structp png_ptr, png_bytep chunk_name)
2260 {
2261 png_debug(1, "in png_check_chunk_name\n");
2262 if (isnonalpha(chunk_name[0]) || isnonalpha(chunk_name[1]) ||
2263 isnonalpha(chunk_name[2]) || isnonalpha(chunk_name[3]))
2264 {
2265 png_chunk_error(png_ptr, "invalid chunk type");
2266 }
2267 }
2268
2269 /* Combines the row recently read in with the existing pixels in the
2270 row. This routine takes care of alpha and transparency if requested.
2271 This routine also handles the two methods of progressive display
2272 of interlaced images, depending on the mask value.
2273 The mask value describes which pixels are to be combined with
2274 the row. The pattern always repeats every 8 pixels, so just 8
2275 bits are needed. A one indicates the pixel is to be combined,
2276 a zero indicates the pixel is to be skipped. This is in addition
2277 to any alpha or transparency value associated with the pixel. If
2278 you want all pixels to be combined, pass 0xff (255) in mask. */
2279
2280 /* Optimized C version of utilities to read a PNG file
2281 *
2282 * Based on code contributed by Nirav Chhatrapati, Intel Corp., 1998.
2283 * Interface to libpng contributed by Gilles Vollant, 1999.
2284 * GNU C port by Greg Roelofs, 1999-2001.
2285 *
2286 */
2287
2288 #if defined(PNG_OPTIMIZED_CODE_SUPPORTED)
2289 #if !defined(PNG_HAVE_MMX_COMBINE_ROW)
2290
2291 /*===========================================================================*/
2292 /* */
2293 /* P N G _ C O M B I N E _ R O W */
2294 /* */
2295 /*===========================================================================*/
2296
2297
2298 #define BPP2 2
2299 #define BPP3 3 /* bytes per pixel (a.k.a. pixel_bytes) */
2300 #define BPP4 4
2301 #define BPP6 6 /* (defined only to help avoid cut-and-paste errors) */
2302 #define BPP8 8
2303
2304 /* Combines the row recently read in with the previous row.
2305 This routine takes care of alpha and transparency if requested.
2306 This routine also handles the two methods of progressive display
2307 of interlaced images, depending on the mask value.
2308 The mask value describes which pixels are to be combined with
2309 the row. The pattern always repeats every 8 pixels, so just 8
2310 bits are needed. A one indicates the pixel is to be combined; a
2311 zero indicates the pixel is to be skipped. This is in addition
2312 to any alpha or transparency value associated with the pixel.
2313 If you want all pixels to be combined, pass 0xff (255) in mask. */
2314
2315 /* Use this routine for the x86 platform - it uses a faster MMX routine
2316 if the machine supports MMX. */
2317
2318 void /* PRIVATE */
png_combine_row(png_structp png_ptr,png_bytep row,int mask)2319 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
2320 {
2321
2322 #if defined(PNG_USE_LOCAL_ARRAYS)
2323 static PNG_CONST int FARDATA png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
2324 static PNG_CONST int FARDATA png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2325 static PNG_CONST int FARDATA png_pass_width[7] = {8, 4, 4, 2, 2, 1, 1};
2326 #endif
2327
2328 png_debug(1, "in png_combine_row (pngrutil.c OPTIMIZED)\n");
2329
2330 if (mask == 0xff)
2331 {
2332 png_debug(2,"mask == 0xff: doing single png_memcpy()\n");
2333 png_memcpy(row, png_ptr->row_buf + 1,
2334 (png_size_t)PNG_ROWBYTES(png_ptr->row_info.pixel_depth,png_ptr->width));
2335 }
2336 else /* (png_combine_row() is never called with mask == 0) */
2337 {
2338 switch (png_ptr->row_info.pixel_depth)
2339 {
2340 /* most common case: combining 24-bit RGB */
2341 case 24: /* png_ptr->row_info.pixel_depth */
2342 {
2343 png_bytep srcptr;
2344 png_bytep dstptr;
2345
2346 {
2347 register png_uint_32 i;
2348 png_uint_32 initial_val = BPP3 * png_pass_start[png_ptr->pass];
2349 /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
2350 register int stride = BPP3 * png_pass_inc[png_ptr->pass];
2351 /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
2352 register int rep_bytes = BPP3 * png_pass_width[png_ptr->pass];
2353 /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
2354 png_uint_32 len = png_ptr->width &~7; /* reduce to mult of 8 */
2355 int diff = (int) (png_ptr->width & 7); /* amount lost */
2356 register png_uint_32 final_val = BPP3 * len; /* GRR bugfix */
2357
2358 srcptr = png_ptr->row_buf + 1 + initial_val;
2359 dstptr = row + initial_val;
2360
2361 for (i = initial_val; i < final_val; i += stride)
2362 {
2363 png_memcpy(dstptr, srcptr, rep_bytes);
2364 srcptr += stride;
2365 dstptr += stride;
2366 }
2367 if (diff) /* number of leftover pixels: 3 for pngtest */
2368 {
2369 final_val += diff*BPP3;
2370 for (; i < final_val; i += stride)
2371 {
2372 if (rep_bytes > (int)(final_val-i))
2373 rep_bytes = (int)(final_val-i);
2374 png_memcpy(dstptr, srcptr, rep_bytes);
2375 srcptr += stride;
2376 dstptr += stride;
2377 }
2378 }
2379 } /* end of else (_mmx_supported) */
2380
2381 break;
2382 } /* end 24 bpp */
2383
2384 case 32: /* png_ptr->row_info.pixel_depth */
2385 {
2386 png_bytep srcptr;
2387 png_bytep dstptr;
2388
2389 {
2390 register png_uint_32 i;
2391 png_uint_32 initial_val = BPP4 * png_pass_start[png_ptr->pass];
2392 /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
2393 register int stride = BPP4 * png_pass_inc[png_ptr->pass];
2394 /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
2395 register int rep_bytes = BPP4 * png_pass_width[png_ptr->pass];
2396 /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
2397 png_uint_32 len = png_ptr->width &~7; /* reduce to mult of 8 */
2398 int diff = (int) (png_ptr->width & 7); /* amount lost */
2399 register png_uint_32 final_val = BPP4 * len; /* GRR bugfix */
2400
2401 srcptr = png_ptr->row_buf + 1 + initial_val;
2402 dstptr = row + initial_val;
2403
2404 for (i = initial_val; i < final_val; i += stride)
2405 {
2406 png_memcpy(dstptr, srcptr, rep_bytes);
2407 srcptr += stride;
2408 dstptr += stride;
2409 }
2410 if (diff) /* number of leftover pixels: 3 for pngtest */
2411 {
2412 final_val += diff*BPP4;
2413 for (; i < final_val; i += stride)
2414 {
2415 if (rep_bytes > (int)(final_val-i))
2416 rep_bytes = (int)(final_val-i);
2417 png_memcpy(dstptr, srcptr, rep_bytes);
2418 srcptr += stride;
2419 dstptr += stride;
2420 }
2421 }
2422 }
2423
2424 break;
2425 } /* end 32 bpp */
2426
2427 case 8: /* png_ptr->row_info.pixel_depth */
2428 {
2429 png_bytep srcptr;
2430 png_bytep dstptr;
2431 {
2432 register png_uint_32 i;
2433 png_uint_32 initial_val = png_pass_start[png_ptr->pass];
2434 /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
2435 register int stride = png_pass_inc[png_ptr->pass];
2436 /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
2437 register int rep_bytes = png_pass_width[png_ptr->pass];
2438 /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
2439 png_uint_32 len = png_ptr->width &~7; /* reduce to mult of 8 */
2440 int diff = (int) (png_ptr->width & 7); /* amount lost */
2441 register png_uint_32 final_val = len; /* GRR bugfix */
2442
2443 srcptr = png_ptr->row_buf + 1 + initial_val;
2444 dstptr = row + initial_val;
2445
2446 for (i = initial_val; i < final_val; i += stride)
2447 {
2448 png_memcpy(dstptr, srcptr, rep_bytes);
2449 srcptr += stride;
2450 dstptr += stride;
2451 }
2452 if (diff) /* number of leftover pixels: 3 for pngtest */
2453 {
2454 final_val += diff /* *BPP1 */ ;
2455 for (; i < final_val; i += stride)
2456 {
2457 if (rep_bytes > (int)(final_val-i))
2458 rep_bytes = (int)(final_val-i);
2459 png_memcpy(dstptr, srcptr, rep_bytes);
2460 srcptr += stride;
2461 dstptr += stride;
2462 }
2463 }
2464 }
2465
2466 break;
2467 } /* end 8 bpp */
2468
2469 case 1: /* png_ptr->row_info.pixel_depth */
2470 {
2471 png_bytep sp;
2472 png_bytep dp;
2473 int s_inc, s_start, s_end;
2474 int m;
2475 int shift;
2476 png_uint_32 i;
2477
2478 sp = png_ptr->row_buf + 1;
2479 dp = row;
2480 m = 0x80;
2481 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2482 if (png_ptr->transformations & PNG_PACKSWAP)
2483 {
2484 s_start = 0;
2485 s_end = 7;
2486 s_inc = 1;
2487 }
2488 else
2489 #endif
2490 {
2491 s_start = 7;
2492 s_end = 0;
2493 s_inc = -1;
2494 }
2495
2496 shift = s_start;
2497
2498 for (i = 0; i < png_ptr->width; i++)
2499 {
2500 if (m & mask)
2501 {
2502 int value;
2503
2504 value = (*sp >> shift) & 0x1;
2505 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
2506 *dp |= (png_byte)(value << shift);
2507 }
2508
2509 if (shift == s_end)
2510 {
2511 shift = s_start;
2512 sp++;
2513 dp++;
2514 }
2515 else
2516 shift += s_inc;
2517
2518 if (m == 1)
2519 m = 0x80;
2520 else
2521 m >>= 1;
2522 }
2523 break;
2524 } /* end 1 bpp */
2525
2526 case 2: /* png_ptr->row_info.pixel_depth */
2527 {
2528 png_bytep sp;
2529 png_bytep dp;
2530 int s_start, s_end, s_inc;
2531 int m;
2532 int shift;
2533 png_uint_32 i;
2534 int value;
2535
2536 sp = png_ptr->row_buf + 1;
2537 dp = row;
2538 m = 0x80;
2539 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2540 if (png_ptr->transformations & PNG_PACKSWAP)
2541 {
2542 s_start = 0;
2543 s_end = 6;
2544 s_inc = 2;
2545 }
2546 else
2547 #endif
2548 {
2549 s_start = 6;
2550 s_end = 0;
2551 s_inc = -2;
2552 }
2553
2554 shift = s_start;
2555
2556 for (i = 0; i < png_ptr->width; i++)
2557 {
2558 if (m & mask)
2559 {
2560 value = (*sp >> shift) & 0x3;
2561 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
2562 *dp |= (png_byte)(value << shift);
2563 }
2564
2565 if (shift == s_end)
2566 {
2567 shift = s_start;
2568 sp++;
2569 dp++;
2570 }
2571 else
2572 shift += s_inc;
2573 if (m == 1)
2574 m = 0x80;
2575 else
2576 m >>= 1;
2577 }
2578 break;
2579 } /* end 2 bpp */
2580
2581 case 4: /* png_ptr->row_info.pixel_depth */
2582 {
2583 png_bytep sp;
2584 png_bytep dp;
2585 int s_start, s_end, s_inc;
2586 int m;
2587 int shift;
2588 png_uint_32 i;
2589 int value;
2590
2591 sp = png_ptr->row_buf + 1;
2592 dp = row;
2593 m = 0x80;
2594 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2595 if (png_ptr->transformations & PNG_PACKSWAP)
2596 {
2597 s_start = 0;
2598 s_end = 4;
2599 s_inc = 4;
2600 }
2601 else
2602 #endif
2603 {
2604 s_start = 4;
2605 s_end = 0;
2606 s_inc = -4;
2607 }
2608 shift = s_start;
2609
2610 for (i = 0; i < png_ptr->width; i++)
2611 {
2612 if (m & mask)
2613 {
2614 value = (*sp >> shift) & 0xf;
2615 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
2616 *dp |= (png_byte)(value << shift);
2617 }
2618
2619 if (shift == s_end)
2620 {
2621 shift = s_start;
2622 sp++;
2623 dp++;
2624 }
2625 else
2626 shift += s_inc;
2627 if (m == 1)
2628 m = 0x80;
2629 else
2630 m >>= 1;
2631 }
2632 break;
2633 } /* end 4 bpp */
2634
2635 case 16: /* png_ptr->row_info.pixel_depth */
2636 {
2637 png_bytep srcptr;
2638 png_bytep dstptr;
2639
2640 {
2641 register png_uint_32 i;
2642 png_uint_32 initial_val = BPP2 * png_pass_start[png_ptr->pass];
2643 /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
2644 register int stride = BPP2 * png_pass_inc[png_ptr->pass];
2645 /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
2646 register int rep_bytes = BPP2 * png_pass_width[png_ptr->pass];
2647 /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
2648 png_uint_32 len = png_ptr->width &~7; /* reduce to mult of 8 */
2649 int diff = (int) (png_ptr->width & 7); /* amount lost */
2650 register png_uint_32 final_val = BPP2 * len; /* GRR bugfix */
2651
2652 srcptr = png_ptr->row_buf + 1 + initial_val;
2653 dstptr = row + initial_val;
2654
2655 for (i = initial_val; i < final_val; i += stride)
2656 {
2657 png_memcpy(dstptr, srcptr, rep_bytes);
2658 srcptr += stride;
2659 dstptr += stride;
2660 }
2661 if (diff) /* number of leftover pixels: 3 for pngtest */
2662 {
2663 final_val += diff*BPP2;
2664 for (; i < final_val; i += stride)
2665 {
2666 if (rep_bytes > (int)(final_val-i))
2667 rep_bytes = (int)(final_val-i);
2668 png_memcpy(dstptr, srcptr, rep_bytes);
2669 srcptr += stride;
2670 dstptr += stride;
2671 }
2672 }
2673 } /* end of else (_mmx_supported) */
2674
2675 break;
2676 } /* end 16 bpp */
2677
2678
2679
2680 case 48: /* png_ptr->row_info.pixel_depth */
2681 {
2682 png_bytep srcptr;
2683 png_bytep dstptr;
2684 {
2685 register png_uint_32 i;
2686 png_uint_32 initial_val = BPP6 * png_pass_start[png_ptr->pass];
2687 /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
2688 register int stride = BPP6 * png_pass_inc[png_ptr->pass];
2689 /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
2690 register int rep_bytes = BPP6 * png_pass_width[png_ptr->pass];
2691 /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
2692 png_uint_32 len = png_ptr->width &~7; /* reduce to mult of 8 */
2693 int diff = (int) (png_ptr->width & 7); /* amount lost */
2694 register png_uint_32 final_val = BPP6 * len; /* GRR bugfix */
2695
2696 srcptr = png_ptr->row_buf + 1 + initial_val;
2697 dstptr = row + initial_val;
2698
2699 for (i = initial_val; i < final_val; i += stride)
2700 {
2701 png_memcpy(dstptr, srcptr, rep_bytes);
2702 srcptr += stride;
2703 dstptr += stride;
2704 }
2705 if (diff) /* number of leftover pixels: 3 for pngtest */
2706 {
2707 final_val += diff*BPP6;
2708 for (; i < final_val; i += stride)
2709 {
2710 if (rep_bytes > (int)(final_val-i))
2711 rep_bytes = (int)(final_val-i);
2712 png_memcpy(dstptr, srcptr, rep_bytes);
2713 srcptr += stride;
2714 dstptr += stride;
2715 }
2716 }
2717 }
2718 break;
2719 } /* end 48 bpp */
2720
2721 case 64: /* png_ptr->row_info.pixel_depth */
2722 {
2723 png_bytep srcptr;
2724 png_bytep dstptr;
2725 register png_uint_32 i;
2726 png_uint_32 initial_val = BPP8 * png_pass_start[png_ptr->pass];
2727 /* png.c: png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; */
2728 register int stride = BPP8 * png_pass_inc[png_ptr->pass];
2729 /* png.c: png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; */
2730 register int rep_bytes = BPP8 * png_pass_width[png_ptr->pass];
2731 /* png.c: png_pass_width[] = {8, 4, 4, 2, 2, 1, 1}; */
2732 png_uint_32 len = png_ptr->width &~7; /* reduce to mult of 8 */
2733 int diff = (int) (png_ptr->width & 7); /* amount lost */
2734 register png_uint_32 final_val = BPP8 * len; /* GRR bugfix */
2735
2736 srcptr = png_ptr->row_buf + 1 + initial_val;
2737 dstptr = row + initial_val;
2738
2739 for (i = initial_val; i < final_val; i += stride)
2740 {
2741 png_memcpy(dstptr, srcptr, rep_bytes);
2742 srcptr += stride;
2743 dstptr += stride;
2744 }
2745 if (diff) /* number of leftover pixels: 3 for pngtest */
2746 {
2747 final_val += diff*BPP8;
2748 for (; i < final_val; i += stride)
2749 {
2750 if (rep_bytes > (int)(final_val-i))
2751 rep_bytes = (int)(final_val-i);
2752 png_memcpy(dstptr, srcptr, rep_bytes);
2753 srcptr += stride;
2754 dstptr += stride;
2755 }
2756 }
2757
2758 break;
2759 } /* end 64 bpp */
2760
2761 default: /* png_ptr->row_info.pixel_depth != 1,2,4,8,16,24,32,48,64 */
2762 {
2763 /* this should never happen */
2764 png_warning(png_ptr, "Invalid row_info.pixel_depth in pngrutil");
2765 break;
2766 }
2767 } /* end switch (png_ptr->row_info.pixel_depth) */
2768
2769 } /* end if (non-trivial mask) */
2770
2771 } /* end png_combine_row() */
2772 #endif /* PNG_HAVE_MMX_COMBINE_ROW */
2773
2774
2775
2776 /*===========================================================================*/
2777 /* */
2778 /* P N G _ D O _ R E A D _ I N T E R L A C E */
2779 /* */
2780 /*===========================================================================*/
2781
2782 #if defined(PNG_READ_INTERLACING_SUPPORTED)
2783 #if !defined(PNG_HAVE_MMX_READ_INTERLACE)
2784
2785 /* png_do_read_interlace() is called after any 16-bit to 8-bit conversion
2786 * has taken place. [GRR: what other steps come before and/or after?]
2787 */
2788
2789 void /* PRIVATE */
png_do_read_interlace(png_structp png_ptr)2790 png_do_read_interlace(png_structp png_ptr)
2791 {
2792 #if defined(PNG_USE_LOCAL_ARRAYS)
2793 static PNG_CONST int FARDATA png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
2794 #endif
2795 png_row_infop row_info = &(png_ptr->row_info);
2796 png_bytep row = png_ptr->row_buf + 1;
2797 int pass = png_ptr->pass;
2798 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2799 png_uint_32 transformations = png_ptr->transformations;
2800 #endif
2801 png_debug(1,"in png_do_read_interlace (pngrutil.c OPTIMIZED)\n");
2802
2803 if (row != NULL && row_info != NULL)
2804 {
2805 png_uint_32 final_width;
2806
2807 final_width = row_info->width * png_pass_inc[pass];
2808
2809 switch (row_info->pixel_depth)
2810 {
2811 case 1:
2812 {
2813 png_bytep sp, dp;
2814 int sshift, dshift;
2815 int s_start, s_end, s_inc;
2816 png_byte v;
2817 png_uint_32 i;
2818 int j;
2819
2820 sp = row + (png_size_t)((row_info->width - 1) >> 3);
2821 dp = row + (png_size_t)((final_width - 1) >> 3);
2822 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2823 if (transformations & PNG_PACKSWAP)
2824 {
2825 sshift = (int)((row_info->width + 7) & 7);
2826 dshift = (int)((final_width + 7) & 7);
2827 s_start = 7;
2828 s_end = 0;
2829 s_inc = -1;
2830 }
2831 else
2832 #endif
2833 {
2834 sshift = 7 - (int)((row_info->width + 7) & 7);
2835 dshift = 7 - (int)((final_width + 7) & 7);
2836 s_start = 0;
2837 s_end = 7;
2838 s_inc = 1;
2839 }
2840
2841 for (i = row_info->width; i; i--)
2842 {
2843 v = (png_byte)((*sp >> sshift) & 0x1);
2844 for (j = 0; j < png_pass_inc[pass]; j++)
2845 {
2846 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
2847 *dp |= (png_byte)(v << dshift);
2848 if (dshift == s_end)
2849 {
2850 dshift = s_start;
2851 dp--;
2852 }
2853 else
2854 dshift += s_inc;
2855 }
2856 if (sshift == s_end)
2857 {
2858 sshift = s_start;
2859 sp--;
2860 }
2861 else
2862 sshift += s_inc;
2863 }
2864 break;
2865 }
2866
2867 case 2:
2868 {
2869 png_bytep sp, dp;
2870 int sshift, dshift;
2871 int s_start, s_end, s_inc;
2872 png_uint_32 i;
2873
2874 sp = row + (png_size_t)((row_info->width - 1) >> 2);
2875 dp = row + (png_size_t)((final_width - 1) >> 2);
2876 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2877 if (transformations & PNG_PACKSWAP)
2878 {
2879 sshift = (png_size_t)(((row_info->width + 3) & 3) << 1);
2880 dshift = (png_size_t)(((final_width + 3) & 3) << 1);
2881 s_start = 6;
2882 s_end = 0;
2883 s_inc = -2;
2884 }
2885 else
2886 #endif
2887 {
2888 sshift = (png_size_t)((3 - ((row_info->width + 3) & 3)) << 1);
2889 dshift = (png_size_t)((3 - ((final_width + 3) & 3)) << 1);
2890 s_start = 0;
2891 s_end = 6;
2892 s_inc = 2;
2893 }
2894
2895 for (i = row_info->width; i; i--)
2896 {
2897 png_byte v;
2898 int j;
2899
2900 v = (png_byte)((*sp >> sshift) & 0x3);
2901 for (j = 0; j < png_pass_inc[pass]; j++)
2902 {
2903 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
2904 *dp |= (png_byte)(v << dshift);
2905 if (dshift == s_end)
2906 {
2907 dshift = s_start;
2908 dp--;
2909 }
2910 else
2911 dshift += s_inc;
2912 }
2913 if (sshift == s_end)
2914 {
2915 sshift = s_start;
2916 sp--;
2917 }
2918 else
2919 sshift += s_inc;
2920 }
2921 break;
2922 }
2923
2924 case 4:
2925 {
2926 png_bytep sp, dp;
2927 int sshift, dshift;
2928 int s_start, s_end, s_inc;
2929 png_uint_32 i;
2930
2931 sp = row + (png_size_t)((row_info->width - 1) >> 1);
2932 dp = row + (png_size_t)((final_width - 1) >> 1);
2933 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
2934 if (transformations & PNG_PACKSWAP)
2935 {
2936 sshift = (png_size_t)(((row_info->width + 1) & 1) << 2);
2937 dshift = (png_size_t)(((final_width + 1) & 1) << 2);
2938 s_start = 4;
2939 s_end = 0;
2940 s_inc = -4;
2941 }
2942 else
2943 #endif
2944 {
2945 sshift = (png_size_t)((1 - ((row_info->width + 1) & 1)) << 2);
2946 dshift = (png_size_t)((1 - ((final_width + 1) & 1)) << 2);
2947 s_start = 0;
2948 s_end = 4;
2949 s_inc = 4;
2950 }
2951
2952 for (i = row_info->width; i; i--)
2953 {
2954 png_byte v;
2955 int j;
2956
2957 v = (png_byte)((*sp >> sshift) & 0xf);
2958 for (j = 0; j < png_pass_inc[pass]; j++)
2959 {
2960 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
2961 *dp |= (png_byte)(v << dshift);
2962 if (dshift == s_end)
2963 {
2964 dshift = s_start;
2965 dp--;
2966 }
2967 else
2968 dshift += s_inc;
2969 }
2970 if (sshift == s_end)
2971 {
2972 sshift = s_start;
2973 sp--;
2974 }
2975 else
2976 sshift += s_inc;
2977 }
2978 break;
2979 }
2980
2981 /*====================================================================*/
2982
2983 default: /* 8-bit or larger (this is where the routine is modified) */
2984 {
2985 png_bytep sptr, dp;
2986 png_uint_32 i;
2987 png_size_t pixel_bytes;
2988 int width = (int)row_info->width;
2989
2990 pixel_bytes = (row_info->pixel_depth >> 3);
2991
2992 /* point sptr at the last pixel in the pre-expanded row: */
2993 sptr = row + (width - 1) * pixel_bytes;
2994
2995 /* point dp at the last pixel position in the expanded row: */
2996 dp = row + (final_width - 1) * pixel_bytes;
2997
2998 /* MMX not supported: use modified C code - takes advantage
2999 * of inlining of png_memcpy for a constant */
3000 /* GRR 19991007: does it? or should pixel_bytes in each
3001 * block be replaced with immediate value (e.g., 1)? */
3002 /* GRR 19991017: replaced with constants in each case */
3003 {
3004 if (pixel_bytes == 1)
3005 {
3006 for (i = width; i; i--)
3007 {
3008 int j;
3009 for (j = 0; j < png_pass_inc[pass]; j++)
3010 {
3011 *dp-- = *sptr;
3012 }
3013 --sptr;
3014 }
3015 }
3016 else if (pixel_bytes == 3)
3017 {
3018 for (i = width; i; i--)
3019 {
3020 png_byte v[8];
3021 int j;
3022 png_memcpy(v, sptr, 3);
3023 for (j = 0; j < png_pass_inc[pass]; j++)
3024 {
3025 png_memcpy(dp, v, 3);
3026 dp -= 3;
3027 }
3028 sptr -= 3;
3029 }
3030 }
3031 else if (pixel_bytes == 2)
3032 {
3033 for (i = width; i; i--)
3034 {
3035 png_byte v[8];
3036 int j;
3037 png_memcpy(v, sptr, 2);
3038 for (j = 0; j < png_pass_inc[pass]; j++)
3039 {
3040 png_memcpy(dp, v, 2);
3041 dp -= 2;
3042 }
3043 sptr -= 2;
3044 }
3045 }
3046 else if (pixel_bytes == 4)
3047 {
3048 for (i = width; i; i--)
3049 {
3050 png_byte v[8];
3051 int j;
3052 png_memcpy(v, sptr, 4);
3053 for (j = 0; j < png_pass_inc[pass]; j++)
3054 {
3055 #if defined(PNG_DEBUG) && defined(PNG_1_0_X)
3056 if (dp < row || dp+3 > row+png_ptr->row_buf_size)
3057 {
3058 printf("dp out of bounds: row=%d, dp=%d, rp=%d\n",
3059 row, dp, row+png_ptr->row_buf_size);
3060 printf("row_buf=%d\n",png_ptr->row_buf_size);
3061 }
3062 #endif
3063 png_memcpy(dp, v, 4);
3064 dp -= 4;
3065 }
3066 sptr -= 4;
3067 }
3068 }
3069 else if (pixel_bytes == 6)
3070 {
3071 for (i = width; i; i--)
3072 {
3073 png_byte v[8];
3074 int j;
3075 png_memcpy(v, sptr, 6);
3076 for (j = 0; j < png_pass_inc[pass]; j++)
3077 {
3078 png_memcpy(dp, v, 6);
3079 dp -= 6;
3080 }
3081 sptr -= 6;
3082 }
3083 }
3084 else if (pixel_bytes == 8)
3085 {
3086 for (i = width; i; i--)
3087 {
3088 png_byte v[8];
3089 int j;
3090 png_memcpy(v, sptr, 8);
3091 for (j = 0; j < png_pass_inc[pass]; j++)
3092 {
3093 png_memcpy(dp, v, 8);
3094 dp -= 8;
3095 }
3096 sptr -= 8;
3097 }
3098 }
3099 else /* GRR: should never be reached */
3100 {
3101 for (i = width; i; i--)
3102 {
3103 png_byte v[8];
3104 int j;
3105 png_memcpy(v, sptr, pixel_bytes);
3106 for (j = 0; j < png_pass_inc[pass]; j++)
3107 {
3108 png_memcpy(dp, v, pixel_bytes);
3109 dp -= pixel_bytes;
3110 }
3111 sptr -= pixel_bytes;
3112 }
3113 }
3114
3115 }
3116 break;
3117 }
3118 } /* end switch (row_info->pixel_depth) */
3119
3120 row_info->width = final_width;
3121
3122 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
3123 }
3124
3125 } /* end png_do_read_interlace() */
3126
3127 #endif /* PNG_HAVE_MMX_READ_INTERLACE */
3128 #endif /* PNG_READ_INTERLACING_SUPPORTED */
3129
3130
3131
3132 #if !defined(PNG_HAVE_MMX_READ_FILTER_ROW)
3133 /*===========================================================================*/
3134 /* */
3135 /* P N G _ R E A D _ F I L T E R _ R O W */
3136 /* */
3137 /*===========================================================================*/
3138
3139
3140 /* Optimized png_read_filter_row routines */
3141
3142 void /* PRIVATE */
png_read_filter_row(png_structp png_ptr,png_row_infop row_info,png_bytep row,png_bytep prev_row,int filter)3143 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep
3144 row, png_bytep prev_row, int filter)
3145 {
3146 #if defined(PNG_DEBUG)
3147 char filnm[10];
3148 #endif
3149
3150
3151 #if defined(PNG_DEBUG)
3152 png_debug(1, "in png_read_filter_row (pngrutil.c OPTIMIZED)\n");
3153 switch (filter)
3154 {
3155 case 0:
3156 png_snprintf(filnm, 10, "none");
3157 break;
3158
3159 case 1:
3160 png_snprintf(filnm, 10, "sub-%s",
3161 "x86");
3162 break;
3163
3164 case 2:
3165 png_snprintf(filnm, 10, "up-%s",
3166 "x86");
3167 break;
3168
3169 case 3:
3170 png_snprintf(filnm, 10, "avg-%s",
3171 "x86");
3172 break;
3173
3174 case 4:
3175 png_snprintf(filnm, 10, "Paeth-%s",
3176 "x86");
3177 break;
3178
3179 default:
3180 png_snprintf(filnm, 10, "unknown");
3181 break;
3182 }
3183 png_debug2(0, "row_number=%5ld, %10s, ", png_ptr->row_number, filnm);
3184 png_debug1(0, "row=0x%08lx, ", (unsigned long)row);
3185 png_debug2(0, "pixdepth=%2d, bytes=%d, ", (int)row_info->pixel_depth,
3186 (int)((row_info->pixel_depth + 7) >> 3));
3187 png_debug1(0,"rowbytes=%8ld\n", row_info->rowbytes);
3188 #endif /* PNG_DEBUG */
3189
3190 switch (filter)
3191 {
3192 case PNG_FILTER_VALUE_NONE:
3193 break;
3194
3195 case PNG_FILTER_VALUE_SUB:
3196 {
3197 png_uint_32 i;
3198 png_uint_32 istop = row_info->rowbytes;
3199 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3200 png_bytep rp = row + bpp;
3201 png_bytep lp = row;
3202
3203 for (i = bpp; i < istop; i++)
3204 {
3205 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
3206 rp++;
3207 }
3208 }
3209 break;
3210
3211 case PNG_FILTER_VALUE_UP:
3212 {
3213 png_uint_32 i;
3214 png_uint_32 istop = row_info->rowbytes;
3215 png_bytep rp = row;
3216 png_bytep pp = prev_row;
3217
3218 for (i = 0; i < istop; ++i)
3219 {
3220 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3221 rp++;
3222 }
3223 }
3224 break;
3225
3226 case PNG_FILTER_VALUE_AVG:
3227 {
3228 png_uint_32 i;
3229 png_bytep rp = row;
3230 png_bytep pp = prev_row;
3231 png_bytep lp = row;
3232 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3233 png_uint_32 istop = row_info->rowbytes - bpp;
3234
3235 for (i = 0; i < bpp; i++)
3236 {
3237 *rp = (png_byte)(((int)(*rp) +
3238 ((int)(*pp++) >> 1)) & 0xff);
3239 rp++;
3240 }
3241
3242 for (i = 0; i < istop; i++)
3243 {
3244 *rp = (png_byte)(((int)(*rp) +
3245 ((int)(*pp++ + *lp++) >> 1)) & 0xff);
3246 rp++;
3247 }
3248 }
3249 break;
3250
3251 case PNG_FILTER_VALUE_PAETH:
3252 {
3253 png_uint_32 i;
3254 png_bytep rp = row;
3255 png_bytep pp = prev_row;
3256 png_bytep lp = row;
3257 png_bytep cp = prev_row;
3258 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3259 png_uint_32 istop = row_info->rowbytes - bpp;
3260
3261 for (i = 0; i < bpp; i++)
3262 {
3263 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3264 rp++;
3265 }
3266
3267 for (i = 0; i < istop; i++) /* use leftover rp,pp */
3268 {
3269 int a, b, c, pa, pb, pc, p;
3270
3271 a = *lp++;
3272 b = *pp++;
3273 c = *cp++;
3274
3275 p = b - c;
3276 pc = a - c;
3277
3278 #if defined(PNG_USE_ABS)
3279 pa = abs(p);
3280 pb = abs(pc);
3281 pc = abs(p + pc);
3282 #else
3283 pa = p < 0 ? -p : p;
3284 pb = pc < 0 ? -pc : pc;
3285 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3286 #endif
3287
3288 /*
3289 if (pa <= pb && pa <= pc)
3290 p = a;
3291 else if (pb <= pc)
3292 p = b;
3293 else
3294 p = c;
3295 */
3296
3297 p = (pa <= pb && pa <= pc) ? a : (pb <= pc) ? b : c;
3298
3299 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
3300 rp++;
3301 }
3302 }
3303 break;
3304
3305 default:
3306 png_warning(png_ptr, "Ignoring bad row-filter type");
3307 *row=0;
3308 break;
3309 }
3310 }
3311
3312 #endif /* PNG_HAVE_MMX_READ_FILTER_ROW */
3313 #endif /* PNG_OPTIMIZED_CODE_SUPPORTED */
3314
3315 #if !defined(PNG_USE_PNGGCCRD) && !defined(PNG_USE_PNGVCRD)
3316 #if !defined(PNG_OPTIMIZED_CODE_SUPPORTED)
3317 /* Use the unoptimized original C code. This might be removed from a future
3318 * version of libpng if testing proves it to be worthless. */
3319 void /* PRIVATE */
png_combine_row(png_structp png_ptr,png_bytep row,int mask)3320 png_combine_row(png_structp png_ptr, png_bytep row, int mask)
3321 {
3322 png_debug(1,"in png_combine_row NOT OPTIMIZED\n");
3323 if (mask == 0xff)
3324 {
3325 png_memcpy(row, png_ptr->row_buf + 1,
3326 PNG_ROWBYTES(png_ptr->row_info.pixel_depth, png_ptr->width));
3327 }
3328 else
3329 {
3330 switch (png_ptr->row_info.pixel_depth)
3331 {
3332 case 1:
3333 {
3334 png_bytep sp = png_ptr->row_buf + 1;
3335 png_bytep dp = row;
3336 int s_inc, s_start, s_end;
3337 int m = 0x80;
3338 int shift;
3339 png_uint_32 i;
3340 png_uint_32 row_width = png_ptr->width;
3341
3342 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
3343 if (png_ptr->transformations & PNG_PACKSWAP)
3344 {
3345 s_start = 0;
3346 s_end = 7;
3347 s_inc = 1;
3348 }
3349 else
3350 #endif
3351 {
3352 s_start = 7;
3353 s_end = 0;
3354 s_inc = -1;
3355 }
3356
3357 shift = s_start;
3358
3359 for (i = 0; i < row_width; i++)
3360 {
3361 if (m & mask)
3362 {
3363 int value;
3364
3365 value = (*sp >> shift) & 0x01;
3366 *dp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
3367 *dp |= (png_byte)(value << shift);
3368 }
3369
3370 if (shift == s_end)
3371 {
3372 shift = s_start;
3373 sp++;
3374 dp++;
3375 }
3376 else
3377 shift += s_inc;
3378
3379 if (m == 1)
3380 m = 0x80;
3381 else
3382 m >>= 1;
3383 }
3384 break;
3385 }
3386 case 2:
3387 {
3388 png_bytep sp = png_ptr->row_buf + 1;
3389 png_bytep dp = row;
3390 int s_start, s_end, s_inc;
3391 int m = 0x80;
3392 int shift;
3393 png_uint_32 i;
3394 png_uint_32 row_width = png_ptr->width;
3395 int value;
3396
3397 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
3398 if (png_ptr->transformations & PNG_PACKSWAP)
3399 {
3400 s_start = 0;
3401 s_end = 6;
3402 s_inc = 2;
3403 }
3404 else
3405 #endif
3406 {
3407 s_start = 6;
3408 s_end = 0;
3409 s_inc = -2;
3410 }
3411
3412 shift = s_start;
3413
3414 for (i = 0; i < row_width; i++)
3415 {
3416 if (m & mask)
3417 {
3418 value = (*sp >> shift) & 0x03;
3419 *dp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
3420 *dp |= (png_byte)(value << shift);
3421 }
3422
3423 if (shift == s_end)
3424 {
3425 shift = s_start;
3426 sp++;
3427 dp++;
3428 }
3429 else
3430 shift += s_inc;
3431 if (m == 1)
3432 m = 0x80;
3433 else
3434 m >>= 1;
3435 }
3436 break;
3437 }
3438 case 4:
3439 {
3440 png_bytep sp = png_ptr->row_buf + 1;
3441 png_bytep dp = row;
3442 int s_start, s_end, s_inc;
3443 int m = 0x80;
3444 int shift;
3445 png_uint_32 i;
3446 png_uint_32 row_width = png_ptr->width;
3447 int value;
3448
3449 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
3450 if (png_ptr->transformations & PNG_PACKSWAP)
3451 {
3452 s_start = 0;
3453 s_end = 4;
3454 s_inc = 4;
3455 }
3456 else
3457 #endif
3458 {
3459 s_start = 4;
3460 s_end = 0;
3461 s_inc = -4;
3462 }
3463 shift = s_start;
3464
3465 for (i = 0; i < row_width; i++)
3466 {
3467 if (m & mask)
3468 {
3469 value = (*sp >> shift) & 0xf;
3470 *dp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
3471 *dp |= (png_byte)(value << shift);
3472 }
3473
3474 if (shift == s_end)
3475 {
3476 shift = s_start;
3477 sp++;
3478 dp++;
3479 }
3480 else
3481 shift += s_inc;
3482 if (m == 1)
3483 m = 0x80;
3484 else
3485 m >>= 1;
3486 }
3487 break;
3488 }
3489 default:
3490 {
3491 png_bytep sp = png_ptr->row_buf + 1;
3492 png_bytep dp = row;
3493 png_size_t pixel_bytes = (png_ptr->row_info.pixel_depth >> 3);
3494 png_uint_32 i;
3495 png_uint_32 row_width = png_ptr->width;
3496 png_byte m = 0x80;
3497
3498
3499 for (i = 0; i < row_width; i++)
3500 {
3501 if (m & mask)
3502 {
3503 png_memcpy(dp, sp, pixel_bytes);
3504 }
3505
3506 sp += pixel_bytes;
3507 dp += pixel_bytes;
3508
3509 if (m == 1)
3510 m = 0x80;
3511 else
3512 m >>= 1;
3513 }
3514 break;
3515 }
3516 }
3517 }
3518 }
3519
3520 #ifdef PNG_READ_INTERLACING_SUPPORTED
3521 /* OLD pre-1.0.9 interface:
3522 void png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
3523 png_uint_32 transformations)
3524 */
3525 void /* PRIVATE */
png_do_read_interlace(png_structp png_ptr)3526 png_do_read_interlace(png_structp png_ptr)
3527 {
3528 png_row_infop row_info = &(png_ptr->row_info);
3529 png_bytep row = png_ptr->row_buf + 1;
3530 int pass = png_ptr->pass;
3531 png_uint_32 transformations = png_ptr->transformations;
3532 #ifdef PNG_USE_LOCAL_ARRAYS
3533 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3534 /* offset to next interlace block */
3535 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3536 #endif
3537
3538 png_debug(1,"in png_do_read_interlace (pngrutil.c NOT OPTIMIZED)\n");
3539 if (row != NULL && row_info != NULL)
3540 {
3541 png_uint_32 final_width;
3542
3543 final_width = row_info->width * png_pass_inc[pass];
3544
3545 switch (row_info->pixel_depth)
3546 {
3547 case 1:
3548 {
3549 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 3);
3550 png_bytep dp = row + (png_size_t)((final_width - 1) >> 3);
3551 int sshift, dshift;
3552 int s_start, s_end, s_inc;
3553 int jstop = png_pass_inc[pass];
3554 png_byte v;
3555 png_uint_32 i;
3556 int j;
3557
3558 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
3559 if (transformations & PNG_PACKSWAP)
3560 {
3561 sshift = (int)((row_info->width + 7) & 0x07);
3562 dshift = (int)((final_width + 7) & 0x07);
3563 s_start = 7;
3564 s_end = 0;
3565 s_inc = -1;
3566 }
3567 else
3568 #endif
3569 {
3570 sshift = 7 - (int)((row_info->width + 7) & 0x07);
3571 dshift = 7 - (int)((final_width + 7) & 0x07);
3572 s_start = 0;
3573 s_end = 7;
3574 s_inc = 1;
3575 }
3576
3577 for (i = 0; i < row_info->width; i++)
3578 {
3579 v = (png_byte)((*sp >> sshift) & 0x01);
3580 for (j = 0; j < jstop; j++)
3581 {
3582 *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
3583 *dp |= (png_byte)(v << dshift);
3584 if (dshift == s_end)
3585 {
3586 dshift = s_start;
3587 dp--;
3588 }
3589 else
3590 dshift += s_inc;
3591 }
3592 if (sshift == s_end)
3593 {
3594 sshift = s_start;
3595 sp--;
3596 }
3597 else
3598 sshift += s_inc;
3599 }
3600 break;
3601 }
3602 case 2:
3603 {
3604 png_bytep sp = row + (png_uint_32)((row_info->width - 1) >> 2);
3605 png_bytep dp = row + (png_uint_32)((final_width - 1) >> 2);
3606 int sshift, dshift;
3607 int s_start, s_end, s_inc;
3608 int jstop = png_pass_inc[pass];
3609 png_uint_32 i;
3610
3611 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
3612 if (transformations & PNG_PACKSWAP)
3613 {
3614 sshift = (int)(((row_info->width + 3) & 0x03) << 1);
3615 dshift = (int)(((final_width + 3) & 0x03) << 1);
3616 s_start = 6;
3617 s_end = 0;
3618 s_inc = -2;
3619 }
3620 else
3621 #endif
3622 {
3623 sshift = (int)((3 - ((row_info->width + 3) & 0x03)) << 1);
3624 dshift = (int)((3 - ((final_width + 3) & 0x03)) << 1);
3625 s_start = 0;
3626 s_end = 6;
3627 s_inc = 2;
3628 }
3629
3630 for (i = 0; i < row_info->width; i++)
3631 {
3632 png_byte v;
3633 int j;
3634
3635 v = (png_byte)((*sp >> sshift) & 0x03);
3636 for (j = 0; j < jstop; j++)
3637 {
3638 *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
3639 *dp |= (png_byte)(v << dshift);
3640 if (dshift == s_end)
3641 {
3642 dshift = s_start;
3643 dp--;
3644 }
3645 else
3646 dshift += s_inc;
3647 }
3648 if (sshift == s_end)
3649 {
3650 sshift = s_start;
3651 sp--;
3652 }
3653 else
3654 sshift += s_inc;
3655 }
3656 break;
3657 }
3658 case 4:
3659 {
3660 png_bytep sp = row + (png_size_t)((row_info->width - 1) >> 1);
3661 png_bytep dp = row + (png_size_t)((final_width - 1) >> 1);
3662 int sshift, dshift;
3663 int s_start, s_end, s_inc;
3664 png_uint_32 i;
3665 int jstop = png_pass_inc[pass];
3666
3667 #if defined(PNG_READ_PACKSWAP_SUPPORTED)
3668 if (transformations & PNG_PACKSWAP)
3669 {
3670 sshift = (int)(((row_info->width + 1) & 0x01) << 2);
3671 dshift = (int)(((final_width + 1) & 0x01) << 2);
3672 s_start = 4;
3673 s_end = 0;
3674 s_inc = -4;
3675 }
3676 else
3677 #endif
3678 {
3679 sshift = (int)((1 - ((row_info->width + 1) & 0x01)) << 2);
3680 dshift = (int)((1 - ((final_width + 1) & 0x01)) << 2);
3681 s_start = 0;
3682 s_end = 4;
3683 s_inc = 4;
3684 }
3685
3686 for (i = 0; i < row_info->width; i++)
3687 {
3688 png_byte v = (png_byte)((*sp >> sshift) & 0xf);
3689 int j;
3690
3691 for (j = 0; j < jstop; j++)
3692 {
3693 *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
3694 *dp |= (png_byte)(v << dshift);
3695 if (dshift == s_end)
3696 {
3697 dshift = s_start;
3698 dp--;
3699 }
3700 else
3701 dshift += s_inc;
3702 }
3703 if (sshift == s_end)
3704 {
3705 sshift = s_start;
3706 sp--;
3707 }
3708 else
3709 sshift += s_inc;
3710 }
3711 break;
3712 }
3713 default:
3714 {
3715 png_size_t pixel_bytes = (row_info->pixel_depth >> 3);
3716 png_bytep sp = row + (png_size_t)(row_info->width - 1) * pixel_bytes;
3717 png_bytep dp = row + (png_size_t)(final_width - 1) * pixel_bytes;
3718
3719 int jstop = png_pass_inc[pass];
3720 png_uint_32 i;
3721
3722 for (i = 0; i < row_info->width; i++)
3723 {
3724 png_byte v[8];
3725 int j;
3726
3727 png_memcpy(v, sp, pixel_bytes);
3728 for (j = 0; j < jstop; j++)
3729 {
3730 png_memcpy(dp, v, pixel_bytes);
3731 dp -= pixel_bytes;
3732 }
3733 sp -= pixel_bytes;
3734 }
3735 break;
3736 }
3737 }
3738 row_info->width = final_width;
3739 row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,final_width);
3740 }
3741 #if !defined(PNG_READ_PACKSWAP_SUPPORTED)
3742 transformations = transformations; /* silence compiler warning */
3743 #endif
3744 }
3745 #endif /* PNG_READ_INTERLACING_SUPPORTED */
3746
3747 void /* PRIVATE */
png_read_filter_row(png_structp png_ptr,png_row_infop row_info,png_bytep row,png_bytep prev_row,int filter)3748 png_read_filter_row(png_structp png_ptr, png_row_infop row_info, png_bytep row,
3749 png_bytep prev_row, int filter)
3750 {
3751 png_debug(1, "in png_read_filter_row (NOT OPTIMIZED)\n");
3752 png_debug2(2,"row = %lu, filter = %d\n", png_ptr->row_number, filter);
3753 switch (filter)
3754 {
3755 case PNG_FILTER_VALUE_NONE:
3756 break;
3757 case PNG_FILTER_VALUE_SUB:
3758 {
3759 png_uint_32 i;
3760 png_uint_32 istop = row_info->rowbytes;
3761 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3762 png_bytep rp = row + bpp;
3763 png_bytep lp = row;
3764
3765 for (i = bpp; i < istop; i++)
3766 {
3767 *rp = (png_byte)(((int)(*rp) + (int)(*lp++)) & 0xff);
3768 rp++;
3769 }
3770 break;
3771 }
3772 case PNG_FILTER_VALUE_UP:
3773 {
3774 png_uint_32 i;
3775 png_uint_32 istop = row_info->rowbytes;
3776 png_bytep rp = row;
3777 png_bytep pp = prev_row;
3778
3779 for (i = 0; i < istop; i++)
3780 {
3781 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3782 rp++;
3783 }
3784 break;
3785 }
3786 case PNG_FILTER_VALUE_AVG:
3787 {
3788 png_uint_32 i;
3789 png_bytep rp = row;
3790 png_bytep pp = prev_row;
3791 png_bytep lp = row;
3792 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3793 png_uint_32 istop = row_info->rowbytes - bpp;
3794
3795 for (i = 0; i < bpp; i++)
3796 {
3797 *rp = (png_byte)(((int)(*rp) +
3798 ((int)(*pp++) / 2 )) & 0xff);
3799 rp++;
3800 }
3801
3802 for (i = 0; i < istop; i++)
3803 {
3804 *rp = (png_byte)(((int)(*rp) +
3805 (int)(*pp++ + *lp++) / 2 ) & 0xff);
3806 rp++;
3807 }
3808 break;
3809 }
3810 case PNG_FILTER_VALUE_PAETH:
3811 {
3812 png_uint_32 i;
3813 png_bytep rp = row;
3814 png_bytep pp = prev_row;
3815 png_bytep lp = row;
3816 png_bytep cp = prev_row;
3817 png_uint_32 bpp = (row_info->pixel_depth + 7) >> 3;
3818 png_uint_32 istop=row_info->rowbytes - bpp;
3819
3820 for (i = 0; i < bpp; i++)
3821 {
3822 *rp = (png_byte)(((int)(*rp) + (int)(*pp++)) & 0xff);
3823 rp++;
3824 }
3825
3826 for (i = 0; i < istop; i++) /* use leftover rp,pp */
3827 {
3828 int a, b, c, pa, pb, pc, p;
3829
3830 a = *lp++;
3831 b = *pp++;
3832 c = *cp++;
3833
3834 p = b - c;
3835 pc = a - c;
3836
3837 #ifdef PNG_USE_ABS
3838 pa = abs(p);
3839 pb = abs(pc);
3840 pc = abs(p + pc);
3841 #else
3842 pa = p < 0 ? -p : p;
3843 pb = pc < 0 ? -pc : pc;
3844 pc = (p + pc) < 0 ? -(p + pc) : p + pc;
3845 #endif
3846
3847 /*
3848 if (pa <= pb && pa <= pc)
3849 p = a;
3850 else if (pb <= pc)
3851 p = b;
3852 else
3853 p = c;
3854 */
3855
3856 p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
3857
3858 *rp = (png_byte)(((int)(*rp) + p) & 0xff);
3859 rp++;
3860 }
3861 break;
3862 }
3863 default:
3864 png_warning(png_ptr, "Ignoring bad adaptive filter type");
3865 *row=0;
3866 break;
3867 }
3868 }
3869 #endif /* !PNG_OPTIMIZED_CODE_SUPPORTED */
3870 #endif /* !PNG_USE_PNGGCCRD && !PNG_USE_PNGVCRD */
3871
3872 void /* PRIVATE */
png_read_finish_row(png_structp png_ptr)3873 png_read_finish_row(png_structp png_ptr)
3874 {
3875 #ifdef PNG_USE_LOCAL_ARRAYS
3876 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
3877
3878 /* start of interlace block */
3879 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
3880
3881 /* offset to next interlace block */
3882 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
3883
3884 /* start of interlace block in the y direction */
3885 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
3886
3887 /* offset to next interlace block in the y direction */
3888 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
3889 #endif
3890
3891 png_debug(1, "in png_read_finish_row\n");
3892 png_ptr->row_number++;
3893 if (png_ptr->row_number < png_ptr->num_rows)
3894 return;
3895
3896 if (png_ptr->interlaced)
3897 {
3898 png_ptr->row_number = 0;
3899 png_memset_check(png_ptr, png_ptr->prev_row, 0,
3900 png_ptr->rowbytes + 1);
3901 do
3902 {
3903 png_ptr->pass++;
3904 if (png_ptr->pass >= 7)
3905 break;
3906 png_ptr->iwidth = (png_ptr->width +
3907 png_pass_inc[png_ptr->pass] - 1 -
3908 png_pass_start[png_ptr->pass]) /
3909 png_pass_inc[png_ptr->pass];
3910
3911 png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth,
3912 png_ptr->iwidth) + 1;
3913
3914 if (!(png_ptr->transformations & PNG_INTERLACE))
3915 {
3916 png_ptr->num_rows = (png_ptr->height +
3917 png_pass_yinc[png_ptr->pass] - 1 -
3918 png_pass_ystart[png_ptr->pass]) /
3919 png_pass_yinc[png_ptr->pass];
3920 if (!(png_ptr->num_rows))
3921 continue;
3922 }
3923 else /* if (png_ptr->transformations & PNG_INTERLACE) */
3924 break;
3925 } while (png_ptr->iwidth == 0);
3926
3927 if (png_ptr->pass < 7)
3928 return;
3929 }
3930
3931 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
3932 {
3933 #ifdef PNG_USE_LOCAL_ARRAYS
3934 PNG_CONST PNG_IDAT;
3935 #endif
3936 char extra;
3937 int ret;
3938
3939 png_ptr->zstream.next_out = (Byte *)&extra;
3940 png_ptr->zstream.avail_out = (uInt)1;
3941 for(;;)
3942 {
3943 if (!(png_ptr->zstream.avail_in))
3944 {
3945 while (!png_ptr->idat_size)
3946 {
3947 png_byte chunk_length[4];
3948
3949 png_crc_finish(png_ptr, 0);
3950
3951 png_read_data(png_ptr, chunk_length, 4);
3952 png_ptr->idat_size = png_get_uint_31(png_ptr, chunk_length);
3953 png_reset_crc(png_ptr);
3954 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
3955 if (png_memcmp(png_ptr->chunk_name, (png_bytep)png_IDAT, 4))
3956 png_error(png_ptr, "Not enough image data");
3957
3958 }
3959 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
3960 png_ptr->zstream.next_in = png_ptr->zbuf;
3961 if (png_ptr->zbuf_size > png_ptr->idat_size)
3962 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
3963 png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
3964 png_ptr->idat_size -= png_ptr->zstream.avail_in;
3965 }
3966 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
3967 if (ret == Z_STREAM_END)
3968 {
3969 if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
3970 png_ptr->idat_size)
3971 png_warning(png_ptr, "Extra compressed data");
3972 png_ptr->mode |= PNG_AFTER_IDAT;
3973 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3974 break;
3975 }
3976 if (ret != Z_OK)
3977 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
3978 "Decompression Error");
3979
3980 if (!(png_ptr->zstream.avail_out))
3981 {
3982 png_warning(png_ptr, "Extra compressed data.");
3983 png_ptr->mode |= PNG_AFTER_IDAT;
3984 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
3985 break;
3986 }
3987
3988 }
3989 png_ptr->zstream.avail_out = 0;
3990 }
3991
3992 if (png_ptr->idat_size || png_ptr->zstream.avail_in)
3993 png_warning(png_ptr, "Extra compression data");
3994
3995 inflateReset(&png_ptr->zstream);
3996
3997 png_ptr->mode |= PNG_AFTER_IDAT;
3998 }
3999
4000 void /* PRIVATE */
png_read_start_row(png_structp png_ptr)4001 png_read_start_row(png_structp png_ptr)
4002 {
4003 #ifdef PNG_USE_LOCAL_ARRAYS
4004 /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
4005
4006 /* start of interlace block */
4007 PNG_CONST int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
4008
4009 /* offset to next interlace block */
4010 PNG_CONST int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
4011
4012 /* start of interlace block in the y direction */
4013 PNG_CONST int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
4014
4015 /* offset to next interlace block in the y direction */
4016 PNG_CONST int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
4017 #endif
4018
4019 int max_pixel_depth;
4020 png_uint_32 row_bytes;
4021
4022 png_debug(1, "in png_read_start_row\n");
4023 png_ptr->zstream.avail_in = 0;
4024 png_init_read_transformations(png_ptr);
4025 if (png_ptr->interlaced)
4026 {
4027 if (!(png_ptr->transformations & PNG_INTERLACE))
4028 png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
4029 png_pass_ystart[0]) / png_pass_yinc[0];
4030 else
4031 png_ptr->num_rows = png_ptr->height;
4032
4033 png_ptr->iwidth = (png_ptr->width +
4034 png_pass_inc[png_ptr->pass] - 1 -
4035 png_pass_start[png_ptr->pass]) /
4036 png_pass_inc[png_ptr->pass];
4037
4038 row_bytes = PNG_ROWBYTES(png_ptr->pixel_depth,png_ptr->iwidth) + 1;
4039
4040 png_ptr->irowbytes = (png_size_t)row_bytes;
4041 if((png_uint_32)png_ptr->irowbytes != row_bytes)
4042 png_error(png_ptr, "Rowbytes overflow in png_read_start_row");
4043 }
4044 else
4045 {
4046 png_ptr->num_rows = png_ptr->height;
4047 png_ptr->iwidth = png_ptr->width;
4048 png_ptr->irowbytes = png_ptr->rowbytes + 1;
4049 }
4050 max_pixel_depth = png_ptr->pixel_depth;
4051
4052 #if defined(PNG_READ_PACK_SUPPORTED)
4053 if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
4054 max_pixel_depth = 8;
4055 #endif
4056
4057 #if defined(PNG_READ_EXPAND_SUPPORTED)
4058 if (png_ptr->transformations & PNG_EXPAND)
4059 {
4060 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
4061 {
4062 if (png_ptr->num_trans)
4063 max_pixel_depth = 32;
4064 else
4065 max_pixel_depth = 24;
4066 }
4067 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
4068 {
4069 if (max_pixel_depth < 8)
4070 max_pixel_depth = 8;
4071 if (png_ptr->num_trans)
4072 max_pixel_depth *= 2;
4073 }
4074 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
4075 {
4076 if (png_ptr->num_trans)
4077 {
4078 max_pixel_depth *= 4;
4079 max_pixel_depth /= 3;
4080 }
4081 }
4082 }
4083 #endif
4084
4085 #if defined(PNG_READ_FILLER_SUPPORTED)
4086 if (png_ptr->transformations & (PNG_FILLER))
4087 {
4088 if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
4089 max_pixel_depth = 32;
4090 else if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
4091 {
4092 if (max_pixel_depth <= 8)
4093 max_pixel_depth = 16;
4094 else
4095 max_pixel_depth = 32;
4096 }
4097 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
4098 {
4099 if (max_pixel_depth <= 32)
4100 max_pixel_depth = 32;
4101 else
4102 max_pixel_depth = 64;
4103 }
4104 }
4105 #endif
4106
4107 #if defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
4108 if (png_ptr->transformations & PNG_GRAY_TO_RGB)
4109 {
4110 if (
4111 #if defined(PNG_READ_EXPAND_SUPPORTED)
4112 (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
4113 #endif
4114 #if defined(PNG_READ_FILLER_SUPPORTED)
4115 (png_ptr->transformations & (PNG_FILLER)) ||
4116 #endif
4117 png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
4118 {
4119 if (max_pixel_depth <= 16)
4120 max_pixel_depth = 32;
4121 else
4122 max_pixel_depth = 64;
4123 }
4124 else
4125 {
4126 if (max_pixel_depth <= 8)
4127 {
4128 if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4129 max_pixel_depth = 32;
4130 else
4131 max_pixel_depth = 24;
4132 }
4133 else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
4134 max_pixel_depth = 64;
4135 else
4136 max_pixel_depth = 48;
4137 }
4138 }
4139 #endif
4140
4141 #if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
4142 defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
4143 if(png_ptr->transformations & PNG_USER_TRANSFORM)
4144 {
4145 int user_pixel_depth=png_ptr->user_transform_depth*
4146 png_ptr->user_transform_channels;
4147 if(user_pixel_depth > max_pixel_depth)
4148 max_pixel_depth=user_pixel_depth;
4149 }
4150 #endif
4151
4152 /* align the width on the next larger 8 pixels. Mainly used
4153 for interlacing */
4154 row_bytes = ((png_ptr->width + 7) & ~((png_uint_32)7));
4155 /* calculate the maximum bytes needed, adding a byte and a pixel
4156 for safety's sake */
4157 row_bytes = PNG_ROWBYTES(max_pixel_depth,row_bytes) +
4158 1 + ((max_pixel_depth + 7) >> 3);
4159 #ifdef PNG_MAX_MALLOC_64K
4160 if (row_bytes > (png_uint_32)65536L)
4161 png_error(png_ptr, "This image requires a row greater than 64KB");
4162 #endif
4163 png_ptr->big_row_buf = (png_bytep)png_malloc(png_ptr, row_bytes+64);
4164 png_ptr->row_buf = png_ptr->big_row_buf+32;
4165 #if defined(PNG_DEBUG) && defined(PNG_USE_PNGGCCRD) && defined(PNG_1_0_X)
4166 png_ptr->row_buf_size = row_bytes;
4167 #endif
4168
4169 #ifdef PNG_MAX_MALLOC_64K
4170 if ((png_uint_32)png_ptr->rowbytes + 1 > (png_uint_32)65536L)
4171 png_error(png_ptr, "This image requires a row greater than 64KB");
4172 #endif
4173 if ((png_uint_32)png_ptr->rowbytes > (png_uint_32)(PNG_SIZE_MAX - 1))
4174 png_error(png_ptr, "Row has too many bytes to allocate in memory.");
4175 png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)(
4176 png_ptr->rowbytes + 1));
4177
4178 png_memset_check(png_ptr, png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
4179
4180 png_debug1(3, "width = %lu,\n", png_ptr->width);
4181 png_debug1(3, "height = %lu,\n", png_ptr->height);
4182 png_debug1(3, "iwidth = %lu,\n", png_ptr->iwidth);
4183 png_debug1(3, "num_rows = %lu\n", png_ptr->num_rows);
4184 png_debug1(3, "rowbytes = %lu,\n", png_ptr->rowbytes);
4185 png_debug1(3, "irowbytes = %lu,\n", png_ptr->irowbytes);
4186
4187 png_ptr->flags |= PNG_FLAG_ROW_INIT;
4188 }
4189 #endif /* PNG_READ_SUPPORTED */
4190