2 /* pngread.c - read a PNG file
5 * For conditions of distribution and use, see copyright notice in png.h
6 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
7 * Copyright (c) 1996, 1997 Andreas Dilger
8 * Copyright (c) 1998, Glenn Randers-Pehrson
11 * This file contains routines that an application calls directly to
12 * read a PNG file or stream.
16 #include "../png/png.h"
18 /* Create a PNG structure for reading, and allocate any memory needed. */
20 png_create_read_struct(png_const_charp user_png_ver
, voidp error_ptr
,
21 png_error_ptr error_fn
, png_error_ptr warn_fn
)
24 #ifdef USE_FAR_KEYWORD
27 png_debug(1, "in png_create_read_struct\n");
28 if ((png_ptr
= (png_structp
)png_create_struct(PNG_STRUCT_PNG
)) == NULL
)
30 return (png_structp
)NULL
;
32 #ifdef USE_FAR_KEYWORD
35 if (setjmp(png_ptr
->jmpbuf
))
38 png_free(png_ptr
, png_ptr
->zbuf
);
39 png_destroy_struct(png_ptr
);
40 return (png_structp
)NULL
;
42 #ifdef USE_FAR_KEYWORD
43 png_memcpy(png_ptr
->jmpbuf
,jmpbuf
,sizeof(jmp_buf));
45 png_set_error_fn(png_ptr
, error_ptr
, error_fn
, warn_fn
);
47 /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
48 * we must recompile any applications that use any older library version.
49 * For versions after libpng 1.0, we will be compatible, so we need
50 * only check the first digit.
52 if (user_png_ver
== NULL
|| user_png_ver
[0] != png_libpng_ver
[0] ||
53 (user_png_ver
[0] == '0' && user_png_ver
[2] < '9'))
56 "Incompatible libpng version in application and library");
59 /* initialize zbuf - compression buffer */
60 png_ptr
->zbuf_size
= PNG_ZBUF_SIZE
;
61 png_ptr
->zbuf
= (png_bytep
)png_malloc(png_ptr
,
62 (png_uint_32
)png_ptr
->zbuf_size
);
63 png_ptr
->zstream
.zalloc
= png_zalloc
;
64 png_ptr
->zstream
.zfree
= png_zfree
;
65 png_ptr
->zstream
.opaque
= (voidpf
)png_ptr
;
67 switch (inflateInit(&png_ptr
->zstream
))
69 case Z_OK
: /* Do nothing */ break;
71 case Z_STREAM_ERROR
: png_error(png_ptr
, "zlib memory error"); break;
72 case Z_VERSION_ERROR
: png_error(png_ptr
, "zlib version error"); break;
73 default: png_error(png_ptr
, "Unknown zlib error");
76 png_ptr
->zstream
.next_out
= png_ptr
->zbuf
;
77 png_ptr
->zstream
.avail_out
= (uInt
)png_ptr
->zbuf_size
;
79 png_set_read_fn(png_ptr
, NULL
, NULL
);
84 /* Initialize PNG structure for reading, and allocate any memory needed.
85 This interface is depreciated in favour of the png_create_read_struct(),
86 and it will eventually disappear. */
88 png_read_init(png_structp png_ptr
)
90 jmp_buf tmp_jmp
; /* to save current jump buffer */
92 png_debug(1, "in png_read_init\n");
93 /* save jump buffer and error functions */
94 png_memcpy(tmp_jmp
, png_ptr
->jmpbuf
, sizeof (jmp_buf));
96 /* reset all variables to 0 */
97 png_memset(png_ptr
, 0, sizeof (png_struct
));
99 /* restore jump buffer */
100 png_memcpy(png_ptr
->jmpbuf
, tmp_jmp
, sizeof (jmp_buf));
102 /* initialize zbuf - compression buffer */
103 png_ptr
->zbuf_size
= PNG_ZBUF_SIZE
;
104 png_ptr
->zbuf
= (png_bytep
)png_malloc(png_ptr
,
105 (png_uint_32
)png_ptr
->zbuf_size
);
106 png_ptr
->zstream
.zalloc
= png_zalloc
;
107 png_ptr
->zstream
.zfree
= png_zfree
;
108 png_ptr
->zstream
.opaque
= (voidpf
)png_ptr
;
110 switch (inflateInit(&png_ptr
->zstream
))
112 case Z_OK
: /* Do nothing */ break;
114 case Z_STREAM_ERROR
: png_error(png_ptr
, "zlib memory"); break;
115 case Z_VERSION_ERROR
: png_error(png_ptr
, "zlib version"); break;
116 default: png_error(png_ptr
, "Unknown zlib error");
119 png_ptr
->zstream
.next_out
= png_ptr
->zbuf
;
120 png_ptr
->zstream
.avail_out
= (uInt
)png_ptr
->zbuf_size
;
122 png_set_read_fn(png_ptr
, NULL
, NULL
);
125 /* Read the information before the actual image data. This has been
126 * changed in v0.90 to allow reading a file that already has the magic
127 * bytes read from the stream. You can tell libpng how many bytes have
128 * been read from the beginning of the stream (up to the maxumum of 8)
129 * via png_set_sig_bytes(), and we will only check the remaining bytes
130 * here. The application can then have access to the signature bytes we
131 * read if it is determined that this isn't a valid PNG file.
134 png_read_info(png_structp png_ptr
, png_infop info_ptr
)
136 png_debug(1, "in png_read_info\n");
137 /* save jump buffer and error functions */
138 /* If we haven't checked all of the PNG signature bytes, do so now. */
139 if (png_ptr
->sig_bytes
< 8)
141 png_size_t num_checked
= png_ptr
->sig_bytes
,
142 num_to_check
= 8 - num_checked
;
144 png_read_data(png_ptr
, &(info_ptr
->signature
[num_checked
]), num_to_check
);
145 png_ptr
->sig_bytes
= 8;
147 if (png_sig_cmp(info_ptr
->signature
, num_checked
, num_to_check
))
149 if (num_checked
< 4 &&
150 png_sig_cmp(info_ptr
->signature
, num_checked
, num_to_check
- 4))
151 png_error(png_ptr
, "Not a PNG file");
153 png_error(png_ptr
, "PNG file corrupted by ASCII conversion");
159 png_byte chunk_length
[4];
162 png_read_data(png_ptr
, chunk_length
, 4);
163 length
= png_get_uint_32(chunk_length
);
165 png_reset_crc(png_ptr
);
166 png_crc_read(png_ptr
, png_ptr
->chunk_name
, 4);
168 png_debug1(0, "Reading %s chunk.\n", png_ptr
->chunk_name
);
170 /* This should be a binary subdivision search or a hash for
171 * matching the chunk name rather than a linear search.
173 if (!png_memcmp(png_ptr
->chunk_name
, png_IHDR
, 4))
174 png_handle_IHDR(png_ptr
, info_ptr
, length
);
175 else if (!png_memcmp(png_ptr
->chunk_name
, png_PLTE
, 4))
176 png_handle_PLTE(png_ptr
, info_ptr
, length
);
177 else if (!png_memcmp(png_ptr
->chunk_name
, png_IEND
, 4))
178 png_handle_IEND(png_ptr
, info_ptr
, length
);
179 else if (!png_memcmp(png_ptr
->chunk_name
, png_IDAT
, 4))
181 if (!(png_ptr
->mode
& PNG_HAVE_IHDR
))
182 png_error(png_ptr
, "Missing IHDR before IDAT");
183 else if (png_ptr
->color_type
== PNG_COLOR_TYPE_PALETTE
&&
184 !(png_ptr
->mode
& PNG_HAVE_PLTE
))
185 png_error(png_ptr
, "Missing PLTE before IDAT");
187 png_ptr
->idat_size
= length
;
188 png_ptr
->mode
|= PNG_HAVE_IDAT
;
191 #if defined(PNG_READ_bKGD_SUPPORTED)
192 else if (!png_memcmp(png_ptr
->chunk_name
, png_bKGD
, 4))
193 png_handle_bKGD(png_ptr
, info_ptr
, length
);
195 #if defined(PNG_READ_cHRM_SUPPORTED)
196 else if (!png_memcmp(png_ptr
->chunk_name
, png_cHRM
, 4))
197 png_handle_cHRM(png_ptr
, info_ptr
, length
);
199 #if defined(PNG_READ_gAMA_SUPPORTED)
200 else if (!png_memcmp(png_ptr
->chunk_name
, png_gAMA
, 4))
201 png_handle_gAMA(png_ptr
, info_ptr
, length
);
203 #if defined(PNG_READ_hIST_SUPPORTED)
204 else if (!png_memcmp(png_ptr
->chunk_name
, png_hIST
, 4))
205 png_handle_hIST(png_ptr
, info_ptr
, length
);
207 #if defined(PNG_READ_oFFs_SUPPORTED)
208 else if (!png_memcmp(png_ptr
->chunk_name
, png_oFFs
, 4))
209 png_handle_oFFs(png_ptr
, info_ptr
, length
);
211 #if defined(PNG_READ_pCAL_SUPPORTED)
212 else if (!png_memcmp(png_ptr
->chunk_name
, png_pCAL
, 4))
213 png_handle_pCAL(png_ptr
, info_ptr
, length
);
215 #if defined(PNG_READ_pHYs_SUPPORTED)
216 else if (!png_memcmp(png_ptr
->chunk_name
, png_pHYs
, 4))
217 png_handle_pHYs(png_ptr
, info_ptr
, length
);
219 #if defined(PNG_READ_sBIT_SUPPORTED)
220 else if (!png_memcmp(png_ptr
->chunk_name
, png_sBIT
, 4))
221 png_handle_sBIT(png_ptr
, info_ptr
, length
);
223 #if defined(PNG_READ_sRGB_SUPPORTED)
224 else if (!png_memcmp(png_ptr
->chunk_name
, png_sRGB
, 4))
225 png_handle_sRGB(png_ptr
, info_ptr
, length
);
227 #if defined(PNG_READ_tEXt_SUPPORTED)
228 else if (!png_memcmp(png_ptr
->chunk_name
, png_tEXt
, 4))
229 png_handle_tEXt(png_ptr
, info_ptr
, length
);
231 #if defined(PNG_READ_tIME_SUPPORTED)
232 else if (!png_memcmp(png_ptr
->chunk_name
, png_tIME
, 4))
233 png_handle_tIME(png_ptr
, info_ptr
, length
);
235 #if defined(PNG_READ_tRNS_SUPPORTED)
236 else if (!png_memcmp(png_ptr
->chunk_name
, png_tRNS
, 4))
237 png_handle_tRNS(png_ptr
, info_ptr
, length
);
239 #if defined(PNG_READ_zTXt_SUPPORTED)
240 else if (!png_memcmp(png_ptr
->chunk_name
, png_zTXt
, 4))
241 png_handle_zTXt(png_ptr
, info_ptr
, length
);
244 png_handle_unknown(png_ptr
, info_ptr
, length
);
248 /* optional call to update the users info_ptr structure */
250 png_read_update_info(png_structp png_ptr
, png_infop info_ptr
)
252 png_debug(1, "in png_read_update_info\n");
253 /* save jump buffer and error functions */
254 if (!(png_ptr
->flags
& PNG_FLAG_ROW_INIT
))
255 png_read_start_row(png_ptr
);
256 png_read_transform_info(png_ptr
, info_ptr
);
259 /* Initialize palette, background, etc, after transformations
260 * are set, but before any reading takes place. This allows
261 * the user to obtail a gamma corrected palette, for example.
262 * If the user doesn't call this, we will do it ourselves.
265 png_start_read_image(png_structp png_ptr
)
267 png_debug(1, "in png_start_read_image\n");
268 /* save jump buffer and error functions */
269 if (!(png_ptr
->flags
& PNG_FLAG_ROW_INIT
))
270 png_read_start_row(png_ptr
);
274 png_read_row(png_structp png_ptr
, png_bytep row
, png_bytep dsp_row
)
277 png_debug2(1, "in png_read_row (row %d, pass %d)\n",
278 png_ptr
->row_number
, png_ptr
->pass
);
279 /* save jump buffer and error functions */
280 if (!(png_ptr
->flags
& PNG_FLAG_ROW_INIT
))
281 png_read_start_row(png_ptr
);
283 #if defined(PNG_READ_INTERLACING_SUPPORTED)
284 /* if interlaced and we do not need a new row, combine row and return */
285 if (png_ptr
->interlaced
&& (png_ptr
->transformations
& PNG_INTERLACE
))
287 switch (png_ptr
->pass
)
290 if (png_ptr
->row_number
& 7)
293 png_combine_row(png_ptr
, dsp_row
,
294 png_pass_dsp_mask
[png_ptr
->pass
]);
295 png_read_finish_row(png_ptr
);
300 if ((png_ptr
->row_number
& 7) || png_ptr
->width
< 5)
303 png_combine_row(png_ptr
, dsp_row
,
304 png_pass_dsp_mask
[png_ptr
->pass
]);
305 png_read_finish_row(png_ptr
);
310 if ((png_ptr
->row_number
& 7) != 4)
312 if (dsp_row
!= NULL
&& (png_ptr
->row_number
& 4))
313 png_combine_row(png_ptr
, dsp_row
,
314 png_pass_dsp_mask
[png_ptr
->pass
]);
315 png_read_finish_row(png_ptr
);
320 if ((png_ptr
->row_number
& 3) || png_ptr
->width
< 3)
323 png_combine_row(png_ptr
, dsp_row
,
324 png_pass_dsp_mask
[png_ptr
->pass
]);
325 png_read_finish_row(png_ptr
);
330 if ((png_ptr
->row_number
& 3) != 2)
332 if (dsp_row
!= NULL
&& (png_ptr
->row_number
& 2))
333 png_combine_row(png_ptr
, dsp_row
,
334 png_pass_dsp_mask
[png_ptr
->pass
]);
335 png_read_finish_row(png_ptr
);
340 if ((png_ptr
->row_number
& 1) || png_ptr
->width
< 2)
343 png_combine_row(png_ptr
, dsp_row
,
344 png_pass_dsp_mask
[png_ptr
->pass
]);
345 png_read_finish_row(png_ptr
);
350 if (!(png_ptr
->row_number
& 1))
352 png_read_finish_row(png_ptr
);
360 if (!(png_ptr
->mode
& PNG_HAVE_IDAT
))
361 png_error(png_ptr
, "Invalid attempt to read row data");
363 png_ptr
->zstream
.next_out
= png_ptr
->row_buf
;
364 png_ptr
->zstream
.avail_out
= (uInt
)png_ptr
->irowbytes
;
367 if (!(png_ptr
->zstream
.avail_in
))
369 while (!png_ptr
->idat_size
)
371 png_byte chunk_length
[4];
373 png_crc_finish(png_ptr
, 0);
375 png_read_data(png_ptr
, chunk_length
, 4);
376 png_ptr
->idat_size
= png_get_uint_32(chunk_length
);
378 png_reset_crc(png_ptr
);
379 png_crc_read(png_ptr
, png_ptr
->chunk_name
, 4);
380 if (png_memcmp(png_ptr
->chunk_name
, png_IDAT
, 4))
381 png_error(png_ptr
, "Not enough image data");
383 png_ptr
->zstream
.avail_in
= (uInt
)png_ptr
->zbuf_size
;
384 png_ptr
->zstream
.next_in
= png_ptr
->zbuf
;
385 if (png_ptr
->zbuf_size
> png_ptr
->idat_size
)
386 png_ptr
->zstream
.avail_in
= (uInt
)png_ptr
->idat_size
;
387 png_crc_read(png_ptr
, png_ptr
->zbuf
,
388 (png_size_t
)png_ptr
->zstream
.avail_in
);
389 png_ptr
->idat_size
-= png_ptr
->zstream
.avail_in
;
391 ret
= inflate(&png_ptr
->zstream
, Z_PARTIAL_FLUSH
);
392 if (ret
== Z_STREAM_END
)
394 if (png_ptr
->zstream
.avail_out
|| png_ptr
->zstream
.avail_in
||
396 png_error(png_ptr
, "Extra compressed data");
397 png_ptr
->mode
|= PNG_AFTER_IDAT
;
398 png_ptr
->flags
|= PNG_FLAG_ZLIB_FINISHED
;
402 png_error(png_ptr
, png_ptr
->zstream
.msg
? png_ptr
->zstream
.msg
:
403 "Decompression error");
405 } while (png_ptr
->zstream
.avail_out
);
407 png_ptr
->row_info
.color_type
= png_ptr
->color_type
;
408 png_ptr
->row_info
.width
= png_ptr
->iwidth
;
409 png_ptr
->row_info
.channels
= png_ptr
->channels
;
410 png_ptr
->row_info
.bit_depth
= png_ptr
->bit_depth
;
411 png_ptr
->row_info
.pixel_depth
= png_ptr
->pixel_depth
;
413 png_ptr
->row_info
.rowbytes
= ((png_ptr
->row_info
.width
*
414 (png_uint_32
)png_ptr
->row_info
.pixel_depth
+ 7) >> 3);
417 png_read_filter_row(png_ptr
, &(png_ptr
->row_info
),
418 png_ptr
->row_buf
+ 1, png_ptr
->prev_row
+ 1,
419 (int)(png_ptr
->row_buf
[0]));
421 png_memcpy_check(png_ptr
, png_ptr
->prev_row
, png_ptr
->row_buf
,
422 png_ptr
->rowbytes
+ 1);
424 if (png_ptr
->transformations
)
425 png_do_read_transformations(png_ptr
);
427 #if defined(PNG_READ_INTERLACING_SUPPORTED)
428 /* blow up interlaced rows to full size */
429 if (png_ptr
->interlaced
&&
430 (png_ptr
->transformations
& PNG_INTERLACE
))
432 if (png_ptr
->pass
< 6)
433 png_do_read_interlace(&(png_ptr
->row_info
),
434 png_ptr
->row_buf
+ 1, png_ptr
->pass
, png_ptr
->transformations
);
437 png_combine_row(png_ptr
, dsp_row
,
438 png_pass_dsp_mask
[png_ptr
->pass
]);
440 png_combine_row(png_ptr
, row
,
441 png_pass_mask
[png_ptr
->pass
]);
447 png_combine_row(png_ptr
, row
, 0xff);
449 png_combine_row(png_ptr
, dsp_row
, 0xff);
451 png_read_finish_row(png_ptr
);
453 if (png_ptr
->read_row_fn
!= NULL
)
454 (*(png_ptr
->read_row_fn
))(png_ptr
, png_ptr
->row_number
, png_ptr
->pass
);
457 /* Read one or more rows of image data. If the image is interlaced,
458 * and png_set_interlace_handling() has been called, the rows need to
459 * contain the contents of the rows from the previous pass. If the
460 * image has alpha or transparency, and png_handle_alpha() has been
461 * called, the rows contents must be initialized to the contents of the
464 * "row" holds the actual image, and pixels are placed in it
465 * as they arrive. If the image is displayed after each pass, it will
466 * appear to "sparkle" in. "display_row" can be used to display a
467 * "chunky" progressive image, with finer detail added as it becomes
468 * available. If you do not want this "chunky" display, you may pass
469 * NULL for display_row. If you do not want the sparkle display, and
470 * you have not called png_handle_alpha(), you may pass NULL for rows.
471 * If you have called png_handle_alpha(), and the image has either an
472 * alpha channel or a transparency chunk, you must provide a buffer for
473 * rows. In this case, you do not have to provide a display_row buffer
474 * also, but you may. If the image is not interlaced, or if you have
475 * not called png_set_interlace_handling(), the display_row buffer will
476 * be ignored, so pass NULL to it.
480 png_read_rows(png_structp png_ptr
, png_bytepp row
,
481 png_bytepp display_row
, png_uint_32 num_rows
)
487 png_debug(1, "in png_read_rows\n");
488 /* save jump buffer and error functions */
491 for (i
= 0; i
< num_rows
; i
++)
504 png_read_row(png_ptr
, rptr
, dptr
);
507 if (display_row
!= NULL
)
512 /* Read the entire image. If the image has an alpha channel or a tRNS
513 * chunk, and you have called png_handle_alpha(), you will need to
514 * initialize the image to the current image that PNG will be overlaying.
515 * We set the num_rows again here, in case it was incorrectly set in
516 * png_read_start_row() by a call to png_read_update_info() or
517 * png_start_read_image() if png_set_interlace_handling() wasn't called
518 * prior to either of these functions like it should have been. You can
519 * only call this function once. If you desire to have an image for
520 * each pass of a interlaced image, use png_read_rows() instead.
523 png_read_image(png_structp png_ptr
, png_bytepp image
)
529 png_debug(1, "in png_read_image\n");
530 /* save jump buffer and error functions */
531 pass
= png_set_interlace_handling(png_ptr
);
533 png_ptr
->num_rows
= png_ptr
->height
; /* Make sure this is set correctly */
535 for (j
= 0; j
< pass
; j
++)
538 for (i
= 0; i
< png_ptr
->height
; i
++)
540 png_read_row(png_ptr
, *rp
, NULL
);
546 /* Read the end of the PNG file. Will not read past the end of the
547 * file, will verify the end is accurate, and will read any comments
548 * or time information at the end of the file, if info is not NULL.
551 png_read_end(png_structp png_ptr
, png_infop info_ptr
)
553 png_byte chunk_length
[4];
556 png_debug(1, "in png_read_end\n");
557 /* save jump buffer and error functions */
558 png_crc_finish(png_ptr
, 0); /* Finish off CRC from last IDAT chunk */
562 png_read_data(png_ptr
, chunk_length
, 4);
563 length
= png_get_uint_32(chunk_length
);
565 png_reset_crc(png_ptr
);
566 png_crc_read(png_ptr
, png_ptr
->chunk_name
, 4);
568 png_debug1(0, "Reading %s chunk.\n", png_ptr
->chunk_name
);
570 if (!png_memcmp(png_ptr
->chunk_name
, png_IHDR
, 4))
571 png_handle_IHDR(png_ptr
, info_ptr
, length
);
572 else if (!png_memcmp(png_ptr
->chunk_name
, png_IDAT
, 4))
574 /* Zero length IDATs are legal after the last IDAT has been
575 * read, but not after other chunks have been read.
577 if (length
> 0 || png_ptr
->mode
& PNG_AFTER_IDAT
)
578 png_error(png_ptr
, "Too many IDAT's found");
580 png_crc_finish(png_ptr
, 0);
582 else if (!png_memcmp(png_ptr
->chunk_name
, png_PLTE
, 4))
583 png_handle_PLTE(png_ptr
, info_ptr
, length
);
584 else if (!png_memcmp(png_ptr
->chunk_name
, png_IEND
, 4))
585 png_handle_IEND(png_ptr
, info_ptr
, length
);
586 #if defined(PNG_READ_bKGD_SUPPORTED)
587 else if (!png_memcmp(png_ptr
->chunk_name
, png_bKGD
, 4))
588 png_handle_bKGD(png_ptr
, info_ptr
, length
);
590 #if defined(PNG_READ_cHRM_SUPPORTED)
591 else if (!png_memcmp(png_ptr
->chunk_name
, png_cHRM
, 4))
592 png_handle_cHRM(png_ptr
, info_ptr
, length
);
594 #if defined(PNG_READ_gAMA_SUPPORTED)
595 else if (!png_memcmp(png_ptr
->chunk_name
, png_gAMA
, 4))
596 png_handle_gAMA(png_ptr
, info_ptr
, length
);
598 #if defined(PNG_READ_hIST_SUPPORTED)
599 else if (!png_memcmp(png_ptr
->chunk_name
, png_hIST
, 4))
600 png_handle_hIST(png_ptr
, info_ptr
, length
);
602 #if defined(PNG_READ_oFFs_SUPPORTED)
603 else if (!png_memcmp(png_ptr
->chunk_name
, png_oFFs
, 4))
604 png_handle_oFFs(png_ptr
, info_ptr
, length
);
606 #if defined(PNG_READ_pCAL_SUPPORTED)
607 else if (!png_memcmp(png_ptr
->chunk_name
, png_pCAL
, 4))
608 png_handle_pCAL(png_ptr
, info_ptr
, length
);
610 #if defined(PNG_READ_pHYs_SUPPORTED)
611 else if (!png_memcmp(png_ptr
->chunk_name
, png_pHYs
, 4))
612 png_handle_pHYs(png_ptr
, info_ptr
, length
);
614 #if defined(PNG_READ_sBIT_SUPPORTED)
615 else if (!png_memcmp(png_ptr
->chunk_name
, png_sBIT
, 4))
616 png_handle_sBIT(png_ptr
, info_ptr
, length
);
618 #if defined(PNG_READ_sRGB_SUPPORTED)
619 else if (!png_memcmp(png_ptr
->chunk_name
, png_sRGB
, 4))
620 png_handle_sRGB(png_ptr
, info_ptr
, length
);
622 #if defined(PNG_READ_tEXt_SUPPORTED)
623 else if (!png_memcmp(png_ptr
->chunk_name
, png_tEXt
, 4))
624 png_handle_tEXt(png_ptr
, info_ptr
, length
);
626 #if defined(PNG_READ_tIME_SUPPORTED)
627 else if (!png_memcmp(png_ptr
->chunk_name
, png_tIME
, 4))
628 png_handle_tIME(png_ptr
, info_ptr
, length
);
630 #if defined(PNG_READ_tRNS_SUPPORTED)
631 else if (!png_memcmp(png_ptr
->chunk_name
, png_tRNS
, 4))
632 png_handle_tRNS(png_ptr
, info_ptr
, length
);
634 #if defined(PNG_READ_zTXt_SUPPORTED)
635 else if (!png_memcmp(png_ptr
->chunk_name
, png_zTXt
, 4))
636 png_handle_zTXt(png_ptr
, info_ptr
, length
);
639 png_handle_unknown(png_ptr
, info_ptr
, length
);
640 } while (!(png_ptr
->mode
& PNG_HAVE_IEND
));
643 /* free all memory used by the read */
645 png_destroy_read_struct(png_structpp png_ptr_ptr
, png_infopp info_ptr_ptr
,
646 png_infopp end_info_ptr_ptr
)
648 png_structp png_ptr
= NULL
;
649 png_infop info_ptr
= NULL
, end_info_ptr
= NULL
;
651 png_debug(1, "in png_destroy_read_struct\n");
652 /* save jump buffer and error functions */
653 if (png_ptr_ptr
!= NULL
)
654 png_ptr
= *png_ptr_ptr
;
656 if (info_ptr_ptr
!= NULL
)
657 info_ptr
= *info_ptr_ptr
;
659 if (end_info_ptr_ptr
!= NULL
)
660 end_info_ptr
= *end_info_ptr_ptr
;
662 png_read_destroy(png_ptr
, info_ptr
, end_info_ptr
);
664 if (info_ptr
!= NULL
)
666 #if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
667 png_free(png_ptr
, info_ptr
->text
);
669 png_destroy_struct((png_voidp
)info_ptr
);
670 *info_ptr_ptr
= (png_infop
)NULL
;
673 if (end_info_ptr
!= NULL
)
675 #if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
676 png_free(png_ptr
, end_info_ptr
->text
);
678 png_destroy_struct((png_voidp
)end_info_ptr
);
679 *end_info_ptr_ptr
= (png_infop
)NULL
;
684 png_destroy_struct((png_voidp
)png_ptr
);
685 *png_ptr_ptr
= (png_structp
)NULL
;
689 /* free all memory used by the read (old method) */
691 png_read_destroy(png_structp png_ptr
, png_infop info_ptr
, png_infop end_info_ptr
)
694 png_error_ptr error_fn
;
695 png_error_ptr warning_fn
;
698 png_debug(1, "in png_read_destroy\n");
699 /* save jump buffer and error functions */
700 if (info_ptr
!= NULL
)
701 png_info_destroy(png_ptr
, info_ptr
);
703 if (end_info_ptr
!= NULL
)
704 png_info_destroy(png_ptr
, end_info_ptr
);
706 png_free(png_ptr
, png_ptr
->zbuf
);
707 png_free(png_ptr
, png_ptr
->row_buf
);
708 png_free(png_ptr
, png_ptr
->prev_row
);
709 #if defined(PNG_READ_DITHER_SUPPORTED)
710 png_free(png_ptr
, png_ptr
->palette_lookup
);
711 png_free(png_ptr
, png_ptr
->dither_index
);
713 #if defined(PNG_READ_GAMMA_SUPPORTED)
714 png_free(png_ptr
, png_ptr
->gamma_table
);
716 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
717 png_free(png_ptr
, png_ptr
->gamma_from_1
);
718 png_free(png_ptr
, png_ptr
->gamma_to_1
);
720 if (png_ptr
->flags
& PNG_FLAG_FREE_PALETTE
)
721 png_zfree(png_ptr
, png_ptr
->palette
);
722 if (png_ptr
->flags
& PNG_FLAG_FREE_TRANS
)
723 png_free(png_ptr
, png_ptr
->trans
);
724 #if defined(PNG_READ_hIST_SUPPORTED)
725 if (png_ptr
->flags
& PNG_FLAG_FREE_HIST
)
726 png_free(png_ptr
, png_ptr
->hist
);
728 #if defined(PNG_READ_GAMMA_SUPPORTED)
729 if (png_ptr
->gamma_16_table
!= NULL
)
732 for (i
= 0; i
< (1 << (8 - png_ptr
->gamma_shift
)); i
++)
734 png_free(png_ptr
, png_ptr
->gamma_16_table
[i
]);
738 #if defined(PNG_READ_BACKGROUND_SUPPORTED)
739 png_free(png_ptr
, png_ptr
->gamma_16_table
);
740 if (png_ptr
->gamma_16_from_1
!= NULL
)
743 for (i
= 0; i
< (1 << (8 - png_ptr
->gamma_shift
)); i
++)
745 png_free(png_ptr
, png_ptr
->gamma_16_from_1
[i
]);
748 png_free(png_ptr
, png_ptr
->gamma_16_from_1
);
749 if (png_ptr
->gamma_16_to_1
!= NULL
)
752 for (i
= 0; i
< (1 << (8 - png_ptr
->gamma_shift
)); i
++)
754 png_free(png_ptr
, png_ptr
->gamma_16_to_1
[i
]);
757 png_free(png_ptr
, png_ptr
->gamma_16_to_1
);
760 inflateEnd(&png_ptr
->zstream
);
761 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
762 png_free(png_ptr
, png_ptr
->save_buffer
);
765 /* Save the important info out of the png_struct, in case it is
768 png_memcpy(tmp_jmp
, png_ptr
->jmpbuf
, sizeof (jmp_buf));
770 error_fn
= png_ptr
->error_fn
;
771 warning_fn
= png_ptr
->warning_fn
;
772 error_ptr
= png_ptr
->error_ptr
;
774 png_memset(png_ptr
, 0, sizeof (png_struct
));
776 png_ptr
->error_fn
= error_fn
;
777 png_ptr
->warning_fn
= warning_fn
;
778 png_ptr
->error_ptr
= error_ptr
;
780 png_memcpy(png_ptr
->jmpbuf
, tmp_jmp
, sizeof (jmp_buf));
784 png_set_read_status_fn(png_structp png_ptr
, png_read_status_ptr read_row_fn
)
786 png_ptr
->read_row_fn
= read_row_fn
;