]> git.saurik.com Git - wxWidgets.git/blame - src/png/pngread.c
wxToolTip for MSW implementation (it has several problems right now, but it
[wxWidgets.git] / src / png / pngread.c
CommitLineData
c801d85f
KB
1
2/* pngread.c - read a PNG file
3 *
4 * libpng 1.0.1
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
9 * March 15, 1998
10 *
11 * This file contains routines that an application calls directly to
12 * read a PNG file or stream.
13 */
14
15#define PNG_INTERNAL
1f0299c1 16#include "../png/png.h"
c801d85f
KB
17
18/* Create a PNG structure for reading, and allocate any memory needed. */
19png_structp
20png_create_read_struct(png_const_charp user_png_ver, voidp error_ptr,
21 png_error_ptr error_fn, png_error_ptr warn_fn)
22{
23 png_structp png_ptr;
24#ifdef USE_FAR_KEYWORD
25 jmp_buf jmpbuf;
26#endif
27 png_debug(1, "in png_create_read_struct\n");
28 if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
29 {
30 return (png_structp)NULL;
31 }
32#ifdef USE_FAR_KEYWORD
33 if (setjmp(jmpbuf))
34#else
35 if (setjmp(png_ptr->jmpbuf))
36#endif
37 {
38 png_free(png_ptr, png_ptr->zbuf);
39 png_destroy_struct(png_ptr);
40 return (png_structp)NULL;
41 }
42#ifdef USE_FAR_KEYWORD
43 png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
44#endif
45 png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
46
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.
51 */
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'))
54 {
55 png_error(png_ptr,
56 "Incompatible libpng version in application and library");
57 }
58
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;
66
67 switch (inflateInit(&png_ptr->zstream))
68 {
69 case Z_OK: /* Do nothing */ break;
70 case Z_MEM_ERROR:
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");
74 }
75
76 png_ptr->zstream.next_out = png_ptr->zbuf;
77 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
78
79 png_set_read_fn(png_ptr, NULL, NULL);
80
81 return (png_ptr);
82}
83
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. */
87void
88png_read_init(png_structp png_ptr)
89{
90 jmp_buf tmp_jmp; /* to save current jump buffer */
91
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));
95
96 /* reset all variables to 0 */
97 png_memset(png_ptr, 0, sizeof (png_struct));
98
99 /* restore jump buffer */
100 png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
101
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;
109
110 switch (inflateInit(&png_ptr->zstream))
111 {
112 case Z_OK: /* Do nothing */ break;
113 case Z_MEM_ERROR:
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");
117 }
118
119 png_ptr->zstream.next_out = png_ptr->zbuf;
120 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
121
122 png_set_read_fn(png_ptr, NULL, NULL);
123}
124
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.
132 */
133void
134png_read_info(png_structp png_ptr, png_infop info_ptr)
135{
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)
140 {
141 png_size_t num_checked = png_ptr->sig_bytes,
142 num_to_check = 8 - num_checked;
143
144 png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
145 png_ptr->sig_bytes = 8;
146
147 if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
148 {
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");
152 else
153 png_error(png_ptr, "PNG file corrupted by ASCII conversion");
154 }
155 }
156
157 for(;;)
158 {
159 png_byte chunk_length[4];
160 png_uint_32 length;
161
162 png_read_data(png_ptr, chunk_length, 4);
163 length = png_get_uint_32(chunk_length);
164
165 png_reset_crc(png_ptr);
166 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
167
168 png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);
169
170 /* This should be a binary subdivision search or a hash for
171 * matching the chunk name rather than a linear search.
172 */
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))
180 {
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");
186
187 png_ptr->idat_size = length;
188 png_ptr->mode |= PNG_HAVE_IDAT;
189 break;
190 }
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);
194#endif
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);
198#endif
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);
202#endif
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);
206#endif
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);
210#endif
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);
214#endif
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);
218#endif
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);
222#endif
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);
226#endif
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);
230#endif
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);
234#endif
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);
238#endif
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);
242#endif
243 else
244 png_handle_unknown(png_ptr, info_ptr, length);
245 }
246}
247
248/* optional call to update the users info_ptr structure */
249void
250png_read_update_info(png_structp png_ptr, png_infop info_ptr)
251{
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);
257}
258
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.
263 */
264void
265png_start_read_image(png_structp png_ptr)
266{
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);
271}
272
273void
274png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
275{
276 int ret;
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);
282
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))
286 {
287 switch (png_ptr->pass)
288 {
289 case 0:
290 if (png_ptr->row_number & 7)
291 {
292 if (dsp_row != NULL)
293 png_combine_row(png_ptr, dsp_row,
294 png_pass_dsp_mask[png_ptr->pass]);
295 png_read_finish_row(png_ptr);
296 return;
297 }
298 break;
299 case 1:
300 if ((png_ptr->row_number & 7) || png_ptr->width < 5)
301 {
302 if (dsp_row != NULL)
303 png_combine_row(png_ptr, dsp_row,
304 png_pass_dsp_mask[png_ptr->pass]);
305 png_read_finish_row(png_ptr);
306 return;
307 }
308 break;
309 case 2:
310 if ((png_ptr->row_number & 7) != 4)
311 {
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);
316 return;
317 }
318 break;
319 case 3:
320 if ((png_ptr->row_number & 3) || png_ptr->width < 3)
321 {
322 if (dsp_row != NULL)
323 png_combine_row(png_ptr, dsp_row,
324 png_pass_dsp_mask[png_ptr->pass]);
325 png_read_finish_row(png_ptr);
326 return;
327 }
328 break;
329 case 4:
330 if ((png_ptr->row_number & 3) != 2)
331 {
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);
336 return;
337 }
338 break;
339 case 5:
340 if ((png_ptr->row_number & 1) || png_ptr->width < 2)
341 {
342 if (dsp_row != NULL)
343 png_combine_row(png_ptr, dsp_row,
344 png_pass_dsp_mask[png_ptr->pass]);
345 png_read_finish_row(png_ptr);
346 return;
347 }
348 break;
349 case 6:
350 if (!(png_ptr->row_number & 1))
351 {
352 png_read_finish_row(png_ptr);
353 return;
354 }
355 break;
356 }
357 }
358#endif
359
360 if (!(png_ptr->mode & PNG_HAVE_IDAT))
361 png_error(png_ptr, "Invalid attempt to read row data");
362
363 png_ptr->zstream.next_out = png_ptr->row_buf;
364 png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
365 do
366 {
367 if (!(png_ptr->zstream.avail_in))
368 {
369 while (!png_ptr->idat_size)
370 {
371 png_byte chunk_length[4];
372
373 png_crc_finish(png_ptr, 0);
374
375 png_read_data(png_ptr, chunk_length, 4);
376 png_ptr->idat_size = png_get_uint_32(chunk_length);
377
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");
382 }
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;
390 }
391 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
392 if (ret == Z_STREAM_END)
393 {
394 if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
395 png_ptr->idat_size)
396 png_error(png_ptr, "Extra compressed data");
397 png_ptr->mode |= PNG_AFTER_IDAT;
398 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
399 break;
400 }
401 if (ret != Z_OK)
402 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
403 "Decompression error");
404
405 } while (png_ptr->zstream.avail_out);
406
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;
412 {
413 png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
414 (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
415 }
416
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]));
420
421 png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
422 png_ptr->rowbytes + 1);
423
424 if (png_ptr->transformations)
425 png_do_read_transformations(png_ptr);
426
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))
431 {
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);
435
436 if (dsp_row != NULL)
437 png_combine_row(png_ptr, dsp_row,
438 png_pass_dsp_mask[png_ptr->pass]);
439 if (row != NULL)
440 png_combine_row(png_ptr, row,
441 png_pass_mask[png_ptr->pass]);
442 }
443 else
444#endif
445 {
446 if (row != NULL)
447 png_combine_row(png_ptr, row, 0xff);
448 if (dsp_row != NULL)
449 png_combine_row(png_ptr, dsp_row, 0xff);
450 }
451 png_read_finish_row(png_ptr);
452
453 if (png_ptr->read_row_fn != NULL)
454 (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
455}
456
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
462 * screen.
463 *
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.
477 */
478
479void
480png_read_rows(png_structp png_ptr, png_bytepp row,
481 png_bytepp display_row, png_uint_32 num_rows)
482{
483 png_uint_32 i;
484 png_bytepp rp;
485 png_bytepp dp;
486
487 png_debug(1, "in png_read_rows\n");
488 /* save jump buffer and error functions */
489 rp = row;
490 dp = display_row;
491 for (i = 0; i < num_rows; i++)
492 {
493 png_bytep rptr;
494 png_bytep dptr;
495
496 if (rp != NULL)
497 rptr = *rp;
498 else
499 rptr = NULL;
500 if (dp != NULL)
501 dptr = *dp;
502 else
503 dptr = NULL;
504 png_read_row(png_ptr, rptr, dptr);
505 if (row != NULL)
506 rp++;
507 if (display_row != NULL)
508 dp++;
509 }
510}
511
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.
521 */
522void
523png_read_image(png_structp png_ptr, png_bytepp image)
524{
525 png_uint_32 i;
526 int pass, j;
527 png_bytepp rp;
528
529 png_debug(1, "in png_read_image\n");
530 /* save jump buffer and error functions */
531 pass = png_set_interlace_handling(png_ptr);
532
533 png_ptr->num_rows = png_ptr->height; /* Make sure this is set correctly */
534
535 for (j = 0; j < pass; j++)
536 {
537 rp = image;
538 for (i = 0; i < png_ptr->height; i++)
539 {
540 png_read_row(png_ptr, *rp, NULL);
541 rp++;
542 }
543 }
544}
545
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.
549 */
550void
551png_read_end(png_structp png_ptr, png_infop info_ptr)
552{
553 png_byte chunk_length[4];
554 png_uint_32 length;
555
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 */
559
560 do
561 {
562 png_read_data(png_ptr, chunk_length, 4);
563 length = png_get_uint_32(chunk_length);
564
565 png_reset_crc(png_ptr);
566 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
567
568 png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);
569
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))
573 {
574 /* Zero length IDATs are legal after the last IDAT has been
575 * read, but not after other chunks have been read.
576 */
577 if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
578 png_error(png_ptr, "Too many IDAT's found");
579 else
580 png_crc_finish(png_ptr, 0);
581 }
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);
589#endif
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);
593#endif
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);
597#endif
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);
601#endif
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);
605#endif
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);
609#endif
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);
613#endif
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);
617#endif
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);
621#endif
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);
625#endif
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);
629#endif
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);
633#endif
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);
637#endif
638 else
639 png_handle_unknown(png_ptr, info_ptr, length);
640 } while (!(png_ptr->mode & PNG_HAVE_IEND));
641}
642
643/* free all memory used by the read */
644void
645png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
646 png_infopp end_info_ptr_ptr)
647{
648 png_structp png_ptr = NULL;
649 png_infop info_ptr = NULL, end_info_ptr = NULL;
650
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;
655
656 if (info_ptr_ptr != NULL)
657 info_ptr = *info_ptr_ptr;
658
659 if (end_info_ptr_ptr != NULL)
660 end_info_ptr = *end_info_ptr_ptr;
661
662 png_read_destroy(png_ptr, info_ptr, end_info_ptr);
663
664 if (info_ptr != NULL)
665 {
666#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
667 png_free(png_ptr, info_ptr->text);
668#endif
669 png_destroy_struct((png_voidp)info_ptr);
670 *info_ptr_ptr = (png_infop)NULL;
671 }
672
673 if (end_info_ptr != NULL)
674 {
675#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
676 png_free(png_ptr, end_info_ptr->text);
677#endif
678 png_destroy_struct((png_voidp)end_info_ptr);
679 *end_info_ptr_ptr = (png_infop)NULL;
680 }
681
682 if (png_ptr != NULL)
683 {
684 png_destroy_struct((png_voidp)png_ptr);
685 *png_ptr_ptr = (png_structp)NULL;
686 }
687}
688
689/* free all memory used by the read (old method) */
690void
691png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)
692{
693 jmp_buf tmp_jmp;
694 png_error_ptr error_fn;
695 png_error_ptr warning_fn;
696 png_voidp error_ptr;
697
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);
702
703 if (end_info_ptr != NULL)
704 png_info_destroy(png_ptr, end_info_ptr);
705
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);
712#endif
713#if defined(PNG_READ_GAMMA_SUPPORTED)
714 png_free(png_ptr, png_ptr->gamma_table);
715#endif
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);
719#endif
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);
727#endif
728#if defined(PNG_READ_GAMMA_SUPPORTED)
729 if (png_ptr->gamma_16_table != NULL)
730 {
731 int i;
732 for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
733 {
734 png_free(png_ptr, png_ptr->gamma_16_table[i]);
735 }
736 }
737#endif
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)
741 {
742 int i;
743 for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
744 {
745 png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
746 }
747 }
748 png_free(png_ptr, png_ptr->gamma_16_from_1);
749 if (png_ptr->gamma_16_to_1 != NULL)
750 {
751 int i;
752 for (i = 0; i < (1 << (8 - png_ptr->gamma_shift)); i++)
753 {
754 png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
755 }
756 }
757 png_free(png_ptr, png_ptr->gamma_16_to_1);
758#endif
759
760 inflateEnd(&png_ptr->zstream);
761#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
762 png_free(png_ptr, png_ptr->save_buffer);
763#endif
764
765 /* Save the important info out of the png_struct, in case it is
766 * being used again.
767 */
768 png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
769
770 error_fn = png_ptr->error_fn;
771 warning_fn = png_ptr->warning_fn;
772 error_ptr = png_ptr->error_ptr;
773
774 png_memset(png_ptr, 0, sizeof (png_struct));
775
776 png_ptr->error_fn = error_fn;
777 png_ptr->warning_fn = warning_fn;
778 png_ptr->error_ptr = error_ptr;
779
780 png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
781}
782
783void
784png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
785{
786 png_ptr->read_row_fn = read_row_fn;
787}