blob: 18ed0420d902781c6ce9811022f173650539ce48 [file] [log] [blame]
Guy Schalnat0d580581995-07-20 02:43:20 -05001
Andreas Dilger47a0c421997-05-16 02:46:07 -05002/* pngread.c - read a PNG file
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003 *
Glenn Randers-Pehrson55e85c22011-11-04 13:34:48 -05004 * Last changed in libpng 1.5.7 [(PENDING RELEASE)]
Glenn Randers-Pehrson64b863c2011-01-04 09:57:06 -06005 * Copyright (c) 1998-2011 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06008 *
Glenn Randers-Pehrsonbfbf8652009-06-26 21:46:52 -05009 * This code is released under the libpng license.
Glenn Randers-Pehrsonc332bbc2009-06-25 13:43:50 -050010 * For conditions of distribution and use, see the disclaimer
Glenn Randers-Pehrson037023b2009-06-24 10:27:36 -050011 * and license in png.h
Glenn Randers-Pehrson3e61d792009-06-24 09:31:28 -050012 *
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060013 * This file contains routines that an application calls directly to
14 * read a PNG file or stream.
15 */
Guy Schalnat0d580581995-07-20 02:43:20 -050016
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -050017#include "pngpriv.h"
John Bowler7875d532011-11-07 22:33:49 -060018#if defined PNG_SIMPLIFIED_READ_SUPPORTED && defined PNG_STDIO_SUPPORTED
19# include <errno.h>
20#endif
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -060021
Glenn Randers-Pehrsonc3cd22b2010-03-08 21:10:25 -060022#ifdef PNG_READ_SUPPORTED
Glenn Randers-Pehrsona93c9422009-04-13 11:41:33 -050023
Andreas Dilger47a0c421997-05-16 02:46:07 -050024/* Create a PNG structure for reading, and allocate any memory needed. */
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -050025PNG_FUNCTION(png_structp,PNGAPI
26png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
27 png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
Guy Schalnat0d580581995-07-20 02:43:20 -050028{
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050029
30#ifdef PNG_USER_MEM_SUPPORTED
31 return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050032 warn_fn, NULL, NULL, NULL));
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050033}
34
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -060035/* Alternate create PNG structure for reading, and allocate any memory
36 * needed.
37 */
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -050038PNG_FUNCTION(png_structp,PNGAPI
39png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -060040 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
Glenn Randers-Pehrson77396b62010-08-02 08:00:10 -050041 png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050042{
43#endif /* PNG_USER_MEM_SUPPORTED */
44
Glenn Randers-Pehrson79134c62009-02-14 10:32:18 -060045#ifdef PNG_SETJMP_SUPPORTED
46 volatile
47#endif
48 png_structp png_ptr;
Glenn Randers-Pehrson62ca98e2009-12-20 15:14:57 -060049 volatile int png_cleanup_needed = 0;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -060050
51#ifdef PNG_SETJMP_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060052#ifdef USE_FAR_KEYWORD
John Bowlere6dc85b2011-04-27 14:47:15 -050053 jmp_buf tmp_jmpbuf;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060054#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -060055#endif
56
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -050057 png_debug(1, "in png_create_read_struct");
Glenn Randers-Pehrsonda009802009-08-15 13:25:47 -050058
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050059#ifdef PNG_USER_MEM_SUPPORTED
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -060060 png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050061 malloc_fn, mem_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050062#else
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -060063 png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050064#endif
Glenn Randers-Pehrson9c0f0942002-02-21 23:14:23 -060065 if (png_ptr == NULL)
Glenn Randers-Pehrson3f549252001-10-27 07:35:13 -050066 return (NULL);
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -050067
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -050068 /* Added at libpng-1.2.6 */
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -060069#ifdef PNG_USER_LIMITS_SUPPORTED
Glenn Randers-Pehrsonef29a5e2009-10-31 19:37:05 -050070 png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
71 png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050072
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -060073# ifdef PNG_USER_CHUNK_CACHE_MAX
74 /* Added at libpng-1.2.43 and 1.4.0 */
Glenn Randers-Pehrsonef29a5e2009-10-31 19:37:05 -050075 png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -060076# endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -050077
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -060078# ifdef PNG_SET_USER_CHUNK_MALLOC_MAX
79 /* Added at libpng-1.2.43 and 1.4.1 */
80 png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
81# endif
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -050082#endif
83
Glenn Randers-Pehrsonf0a8fe02009-04-14 08:28:15 -050084#ifdef PNG_SETJMP_SUPPORTED
85/* Applications that neglect to set up their own setjmp() and then
Glenn Randers-Pehrsonefc4b692011-11-07 23:31:34 -060086 * encounter a png_error() will longjmp here. Since the jmpbuf is
87 * then meaningless we abort instead of returning.
88 */
Glenn Randers-Pehrsonf0a8fe02009-04-14 08:28:15 -050089#ifdef USE_FAR_KEYWORD
John Bowlere6dc85b2011-04-27 14:47:15 -050090 if (setjmp(tmp_jmpbuf))
Glenn Randers-Pehrsonf0a8fe02009-04-14 08:28:15 -050091#else
Glenn Randers-Pehrsonf4ea2242009-11-20 21:38:24 -060092 if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */
Glenn Randers-Pehrsonf0a8fe02009-04-14 08:28:15 -050093#endif
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050094 PNG_ABORT();
Glenn Randers-Pehrsonf4ea2242009-11-20 21:38:24 -060095#ifdef USE_FAR_KEYWORD
John Bowlere6dc85b2011-04-27 14:47:15 -050096 png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf));
Glenn Randers-Pehrsonf4ea2242009-11-20 21:38:24 -060097#endif
Glenn Randers-Pehrsona2567be2009-10-19 20:31:31 -050098#endif /* PNG_SETJMP_SUPPORTED */
Glenn Randers-Pehrsonf0a8fe02009-04-14 08:28:15 -050099
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500100#ifdef PNG_USER_MEM_SUPPORTED
101 png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600102#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500103
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600104 png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
Guy Schalnat6d764711995-12-19 03:22:19 -0600105
John Bowler88b77cc2011-05-05 06:49:55 -0500106 /* Call the general version checker (shared with read and write code): */
107 if (!png_user_version_check(png_ptr, user_png_ver))
108 png_cleanup_needed = 1;
Glenn Randers-Pehrson98c9d732000-05-03 21:06:11 -0500109
Glenn Randers-Pehrsona93c9422009-04-13 11:41:33 -0500110 if (!png_cleanup_needed)
111 {
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -0500112 /* Initialize zbuf - compression buffer */
Guy Schalnat0d580581995-07-20 02:43:20 -0500113 png_ptr->zbuf_size = PNG_ZBUF_SIZE;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500114 png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size);
115
Glenn Randers-Pehrsona93c9422009-04-13 11:41:33 -0500116 if (png_ptr->zbuf == NULL)
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600117 png_cleanup_needed = 1;
Glenn Randers-Pehrsona93c9422009-04-13 11:41:33 -0500118 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500119
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600120 png_ptr->zstream.zalloc = png_zalloc;
121 png_ptr->zstream.zfree = png_zfree;
122 png_ptr->zstream.opaque = (voidpf)png_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -0500123
Glenn Randers-Pehrsona93c9422009-04-13 11:41:33 -0500124 if (!png_cleanup_needed)
125 {
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500126 switch (inflateInit(&png_ptr->zstream))
127 {
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500128 case Z_OK:
129 break; /* Do nothing */
130
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500131 case Z_MEM_ERROR:
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500132 png_warning(png_ptr, "zlib memory error");
133 png_cleanup_needed = 1;
134 break;
135
136 case Z_STREAM_ERROR:
137 png_warning(png_ptr, "zlib stream error");
138 png_cleanup_needed = 1;
139 break;
140
141 case Z_VERSION_ERROR:
142 png_warning(png_ptr, "zlib version error");
143 png_cleanup_needed = 1;
144 break;
145
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500146 default: png_warning(png_ptr, "Unknown zlib error");
147 png_cleanup_needed = 1;
148 }
Glenn Randers-Pehrsona93c9422009-04-13 11:41:33 -0500149 }
150
151 if (png_cleanup_needed)
152 {
Glenn Randers-Pehrsonf0a8fe02009-04-14 08:28:15 -0500153 /* Clean up PNG structure and deallocate any memory. */
154 png_free(png_ptr, png_ptr->zbuf);
155 png_ptr->zbuf = NULL;
Glenn Randers-Pehrsona93c9422009-04-13 11:41:33 -0500156#ifdef PNG_USER_MEM_SUPPORTED
Glenn Randers-Pehrsonf0a8fe02009-04-14 08:28:15 -0500157 png_destroy_struct_2((png_voidp)png_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600158 (png_free_ptr)free_fn, (png_voidp)mem_ptr);
Glenn Randers-Pehrsona93c9422009-04-13 11:41:33 -0500159#else
Glenn Randers-Pehrsonf0a8fe02009-04-14 08:28:15 -0500160 png_destroy_struct((png_voidp)png_ptr);
Glenn Randers-Pehrsona93c9422009-04-13 11:41:33 -0500161#endif
Glenn Randers-Pehrsonf0a8fe02009-04-14 08:28:15 -0500162 return (NULL);
Guy Schalnate5a37791996-06-05 15:50:50 -0500163 }
164
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600165 png_ptr->zstream.next_out = png_ptr->zbuf;
166 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
Guy Schalnate5a37791996-06-05 15:50:50 -0500167
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500168 png_set_read_fn(png_ptr, NULL, NULL);
Guy Schalnate5a37791996-06-05 15:50:50 -0500169
Glenn Randers-Pehrsonf0a8fe02009-04-14 08:28:15 -0500170
Guy Schalnate5a37791996-06-05 15:50:50 -0500171 return (png_ptr);
172}
173
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500174
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500175#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600176/* Read the information before the actual image data. This has been
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -0600177 * changed in v0.90 to allow reading a file that already has the magic
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600178 * bytes read from the stream. You can tell libpng how many bytes have
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500179 * been read from the beginning of the stream (up to the maximum of 8)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600180 * via png_set_sig_bytes(), and we will only check the remaining bytes
181 * here. The application can then have access to the signature bytes we
182 * read if it is determined that this isn't a valid PNG file.
183 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500184void PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600185png_read_info(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500186{
Glenn Randers-Pehrsonc81bb8a2009-08-15 22:02:26 -0500187 png_debug(1, "in png_read_info");
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500188
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500189 if (png_ptr == NULL || info_ptr == NULL)
190 return;
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500191
Glenn Randers-Pehrsona5815562010-11-20 21:48:29 -0600192 /* Read and check the PNG file signature. */
193 png_read_sig(png_ptr, info_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -0500194
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500195 for (;;)
Guy Schalnat0d580581995-07-20 02:43:20 -0500196 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500197 png_uint_32 length = png_read_chunk_header(png_ptr);
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500198 png_uint_32 chunk_name = png_ptr->chunk_name;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500199
200 /* This should be a binary subdivision search or a hash for
201 * matching the chunk name rather than a linear search.
202 */
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500203 if (chunk_name == png_IDAT)
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600204 if (png_ptr->mode & PNG_AFTER_IDAT)
205 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500206
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500207 if (chunk_name == png_IHDR)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600208 png_handle_IHDR(png_ptr, info_ptr, length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500209
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500210 else if (chunk_name == png_IEND)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600211 png_handle_IEND(png_ptr, info_ptr, length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500212
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600213#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500214 else if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
215 PNG_HANDLE_CHUNK_AS_DEFAULT)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600216 {
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500217 if (chunk_name == png_IDAT)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600218 png_ptr->mode |= PNG_HAVE_IDAT;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500219
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600220 png_handle_unknown(png_ptr, info_ptr, length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500221
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500222 if (chunk_name == png_PLTE)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600223 png_ptr->mode |= PNG_HAVE_PLTE;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500224
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500225 else if (chunk_name == png_IDAT)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600226 {
227 if (!(png_ptr->mode & PNG_HAVE_IHDR))
228 png_error(png_ptr, "Missing IHDR before IDAT");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500229
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600230 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600231 !(png_ptr->mode & PNG_HAVE_PLTE))
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600232 png_error(png_ptr, "Missing PLTE before IDAT");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500233
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600234 break;
235 }
236 }
237#endif
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500238 else if (chunk_name == png_PLTE)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600239 png_handle_PLTE(png_ptr, info_ptr, length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500240
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500241 else if (chunk_name == png_IDAT)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500242 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500243 if (!(png_ptr->mode & PNG_HAVE_IHDR))
244 png_error(png_ptr, "Missing IHDR before IDAT");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500245
Guy Schalnate5a37791996-06-05 15:50:50 -0500246 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600247 !(png_ptr->mode & PNG_HAVE_PLTE))
Guy Schalnate5a37791996-06-05 15:50:50 -0500248 png_error(png_ptr, "Missing PLTE before IDAT");
249
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500250 png_ptr->idat_size = length;
Guy Schalnate5a37791996-06-05 15:50:50 -0500251 png_ptr->mode |= PNG_HAVE_IDAT;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500252 break;
253 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500254
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500255#ifdef PNG_READ_bKGD_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500256 else if (chunk_name == png_bKGD)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500257 png_handle_bKGD(png_ptr, info_ptr, length);
258#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500259
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500260#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500261 else if (chunk_name == png_cHRM)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500262 png_handle_cHRM(png_ptr, info_ptr, length);
263#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500264
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500265#ifdef PNG_READ_gAMA_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500266 else if (chunk_name == png_gAMA)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500267 png_handle_gAMA(png_ptr, info_ptr, length);
268#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500269
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500270#ifdef PNG_READ_hIST_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500271 else if (chunk_name == png_hIST)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500272 png_handle_hIST(png_ptr, info_ptr, length);
273#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500274
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500275#ifdef PNG_READ_oFFs_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500276 else if (chunk_name == png_oFFs)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500277 png_handle_oFFs(png_ptr, info_ptr, length);
278#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500279
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500280#ifdef PNG_READ_pCAL_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500281 else if (chunk_name == png_pCAL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500282 png_handle_pCAL(png_ptr, info_ptr, length);
283#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500284
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500285#ifdef PNG_READ_sCAL_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500286 else if (chunk_name == png_sCAL)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600287 png_handle_sCAL(png_ptr, info_ptr, length);
288#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500289
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500290#ifdef PNG_READ_pHYs_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500291 else if (chunk_name == png_pHYs)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500292 png_handle_pHYs(png_ptr, info_ptr, length);
293#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500294
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500295#ifdef PNG_READ_sBIT_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500296 else if (chunk_name == png_sBIT)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500297 png_handle_sBIT(png_ptr, info_ptr, length);
298#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500299
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500300#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500301 else if (chunk_name == png_sRGB)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600302 png_handle_sRGB(png_ptr, info_ptr, length);
303#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500304
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500305#ifdef PNG_READ_iCCP_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500306 else if (chunk_name == png_iCCP)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600307 png_handle_iCCP(png_ptr, info_ptr, length);
308#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500309
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500310#ifdef PNG_READ_sPLT_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500311 else if (chunk_name == png_sPLT)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600312 png_handle_sPLT(png_ptr, info_ptr, length);
313#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500314
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500315#ifdef PNG_READ_tEXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500316 else if (chunk_name == png_tEXt)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500317 png_handle_tEXt(png_ptr, info_ptr, length);
318#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500319
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500320#ifdef PNG_READ_tIME_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500321 else if (chunk_name == png_tIME)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500322 png_handle_tIME(png_ptr, info_ptr, length);
323#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500324
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500325#ifdef PNG_READ_tRNS_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500326 else if (chunk_name == png_tRNS)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500327 png_handle_tRNS(png_ptr, info_ptr, length);
328#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500329
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500330#ifdef PNG_READ_zTXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500331 else if (chunk_name == png_zTXt)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500332 png_handle_zTXt(png_ptr, info_ptr, length);
333#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500334
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500335#ifdef PNG_READ_iTXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500336 else if (chunk_name == png_iTXt)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600337 png_handle_iTXt(png_ptr, info_ptr, length);
338#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500339
Guy Schalnat0d580581995-07-20 02:43:20 -0500340 else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600341 png_handle_unknown(png_ptr, info_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500342 }
343}
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500344#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -0500345
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -0500346/* Optional call to update the users info_ptr structure */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500347void PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600348png_read_update_info(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500349{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500350 png_debug(1, "in png_read_update_info");
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500351
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500352 if (png_ptr == NULL)
353 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500354
Glenn Randers-Pehrson3dbfd302011-10-13 17:24:36 -0500355 png_read_start_row(png_ptr);
Glenn Randers-Pehrson4cfdb3c2009-11-26 11:49:37 -0600356
John Bowler4a12f4a2011-04-17 18:34:22 -0500357#ifdef PNG_READ_TRANSFORMS_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600358 png_read_transform_info(png_ptr, info_ptr);
John Bowler4a12f4a2011-04-17 18:34:22 -0500359#else
360 PNG_UNUSED(info_ptr)
361#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500362}
363
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500364#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600365/* Initialize palette, background, etc, after transformations
366 * are set, but before any reading takes place. This allows
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500367 * the user to obtain a gamma-corrected palette, for example.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600368 * If the user doesn't call this, we will do it ourselves.
369 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500370void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600371png_start_read_image(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500372{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500373 png_debug(1, "in png_start_read_image");
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500374
Glenn Randers-Pehrson3dbfd302011-10-13 17:24:36 -0500375 if (png_ptr != NULL)
376 png_read_start_row(png_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -0500377}
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500378#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -0500379
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500380#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500381void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600382png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500383{
384 int ret;
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500385
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500386 png_row_info row_info;
387
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500388 if (png_ptr == NULL)
389 return;
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500390
Glenn Randers-Pehrson6d75d0c2009-08-22 08:45:09 -0500391 png_debug2(1, "in png_read_row (row %lu, pass %d)",
Glenn Randers-Pehrsond2332872010-10-12 19:19:28 -0500392 (unsigned long)png_ptr->row_number, png_ptr->pass);
Glenn Randers-Pehrson6d75d0c2009-08-22 08:45:09 -0500393
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500394 /* png_read_start_row sets the information (in particular iwidth) for this
395 * interlace pass.
396 */
Guy Schalnate5a37791996-06-05 15:50:50 -0500397 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
Guy Schalnat0d580581995-07-20 02:43:20 -0500398 png_read_start_row(png_ptr);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500399
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500400 /* 1.5.6: row_info moved out of png_struct to a local here. */
401 row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
402 row_info.color_type = png_ptr->color_type;
403 row_info.bit_depth = png_ptr->bit_depth;
404 row_info.channels = png_ptr->channels;
405 row_info.pixel_depth = png_ptr->pixel_depth;
406 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
407
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500408 if (png_ptr->row_number == 0 && png_ptr->pass == 0)
409 {
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -0500410 /* Check for transforms that have been set but were defined out */
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500411#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
412 if (png_ptr->transformations & PNG_INVERT_MONO)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500413 png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined");
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500414#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500415
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500416#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
417 if (png_ptr->transformations & PNG_FILLER)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500418 png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined");
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500419#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500420
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600421#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
422 !defined(PNG_READ_PACKSWAP_SUPPORTED)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500423 if (png_ptr->transformations & PNG_PACKSWAP)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500424 png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined");
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500425#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500426
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500427#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
428 if (png_ptr->transformations & PNG_PACK)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500429 png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined");
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500430#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500431
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500432#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
433 if (png_ptr->transformations & PNG_SHIFT)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500434 png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined");
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500435#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500436
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500437#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
438 if (png_ptr->transformations & PNG_BGR)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500439 png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined");
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500440#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500441
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500442#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
443 if (png_ptr->transformations & PNG_SWAP_BYTES)
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500444 png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined");
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500445#endif
446 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500447
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500448#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500449 /* If interlaced and we do not need a new row, combine row and return.
450 * Notice that the pixels we have from previous rows have been transformed
451 * already; we can only combine like with like (transformed or
452 * untransformed) and, because of the libpng API for interlaced images, this
453 * means we must transform before de-interlacing.
454 */
Guy Schalnat0d580581995-07-20 02:43:20 -0500455 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
456 {
457 switch (png_ptr->pass)
458 {
459 case 0:
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600460 if (png_ptr->row_number & 0x07)
Guy Schalnat0d580581995-07-20 02:43:20 -0500461 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500462 if (dsp_row != NULL)
Glenn Randers-Pehrson65c03392011-10-06 21:54:17 -0500463 png_combine_row(png_ptr, dsp_row, 1/*display*/);
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600464 png_read_finish_row(png_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -0500465 return;
466 }
467 break;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500468
Guy Schalnat0d580581995-07-20 02:43:20 -0500469 case 1:
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600470 if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
Guy Schalnat0d580581995-07-20 02:43:20 -0500471 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500472 if (dsp_row != NULL)
Glenn Randers-Pehrson65c03392011-10-06 21:54:17 -0500473 png_combine_row(png_ptr, dsp_row, 1/*display*/);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500474
Guy Schalnat0d580581995-07-20 02:43:20 -0500475 png_read_finish_row(png_ptr);
476 return;
477 }
478 break;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500479
Guy Schalnat0d580581995-07-20 02:43:20 -0500480 case 2:
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600481 if ((png_ptr->row_number & 0x07) != 4)
Guy Schalnat0d580581995-07-20 02:43:20 -0500482 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500483 if (dsp_row != NULL && (png_ptr->row_number & 4))
Glenn Randers-Pehrson65c03392011-10-06 21:54:17 -0500484 png_combine_row(png_ptr, dsp_row, 1/*display*/);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500485
Guy Schalnat0d580581995-07-20 02:43:20 -0500486 png_read_finish_row(png_ptr);
487 return;
488 }
489 break;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500490
Guy Schalnat0d580581995-07-20 02:43:20 -0500491 case 3:
492 if ((png_ptr->row_number & 3) || png_ptr->width < 3)
493 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500494 if (dsp_row != NULL)
Glenn Randers-Pehrson65c03392011-10-06 21:54:17 -0500495 png_combine_row(png_ptr, dsp_row, 1/*display*/);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500496
Guy Schalnat0d580581995-07-20 02:43:20 -0500497 png_read_finish_row(png_ptr);
498 return;
499 }
500 break;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500501
Guy Schalnat0d580581995-07-20 02:43:20 -0500502 case 4:
503 if ((png_ptr->row_number & 3) != 2)
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600504 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500505 if (dsp_row != NULL && (png_ptr->row_number & 2))
Glenn Randers-Pehrson65c03392011-10-06 21:54:17 -0500506 png_combine_row(png_ptr, dsp_row, 1/*display*/);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500507
Guy Schalnat0d580581995-07-20 02:43:20 -0500508 png_read_finish_row(png_ptr);
509 return;
510 }
511 break;
512 case 5:
513 if ((png_ptr->row_number & 1) || png_ptr->width < 2)
514 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500515 if (dsp_row != NULL)
Glenn Randers-Pehrson65c03392011-10-06 21:54:17 -0500516 png_combine_row(png_ptr, dsp_row, 1/*display*/);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500517
Guy Schalnat0d580581995-07-20 02:43:20 -0500518 png_read_finish_row(png_ptr);
519 return;
520 }
521 break;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500522
Glenn Randers-Pehrsonb3edc732010-11-21 14:06:41 -0600523 default:
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600524 case 6:
Guy Schalnat0d580581995-07-20 02:43:20 -0500525 if (!(png_ptr->row_number & 1))
526 {
527 png_read_finish_row(png_ptr);
528 return;
529 }
530 break;
531 }
532 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500533#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500534
Guy Schalnate5a37791996-06-05 15:50:50 -0500535 if (!(png_ptr->mode & PNG_HAVE_IDAT))
536 png_error(png_ptr, "Invalid attempt to read row data");
Guy Schalnat0d580581995-07-20 02:43:20 -0500537
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600538 png_ptr->zstream.next_out = png_ptr->row_buf;
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600539 png_ptr->zstream.avail_out =
540 (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
541 png_ptr->iwidth) + 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500542
Guy Schalnat0d580581995-07-20 02:43:20 -0500543 do
544 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600545 if (!(png_ptr->zstream.avail_in))
Guy Schalnat0d580581995-07-20 02:43:20 -0500546 {
547 while (!png_ptr->idat_size)
548 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600549 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500550
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500551 png_ptr->idat_size = png_read_chunk_header(png_ptr);
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500552 if (png_ptr->chunk_name != png_IDAT)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600553 png_error(png_ptr, "Not enough image data");
Guy Schalnat0d580581995-07-20 02:43:20 -0500554 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600555 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
556 png_ptr->zstream.next_in = png_ptr->zbuf;
Guy Schalnat0d580581995-07-20 02:43:20 -0500557 if (png_ptr->zbuf_size > png_ptr->idat_size)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600558 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500559 png_crc_read(png_ptr, png_ptr->zbuf,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600560 (png_size_t)png_ptr->zstream.avail_in);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600561 png_ptr->idat_size -= png_ptr->zstream.avail_in;
Guy Schalnat0d580581995-07-20 02:43:20 -0500562 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500563
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600564 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500565
Guy Schalnat0d580581995-07-20 02:43:20 -0500566 if (ret == Z_STREAM_END)
567 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600568 if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
Guy Schalnat0d580581995-07-20 02:43:20 -0500569 png_ptr->idat_size)
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500570 png_benign_error(png_ptr, "Extra compressed data");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600571 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnate5a37791996-06-05 15:50:50 -0500572 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600573 break;
Guy Schalnat0d580581995-07-20 02:43:20 -0500574 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500575
Guy Schalnat0d580581995-07-20 02:43:20 -0500576 if (ret != Z_OK)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600577 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600578 "Decompression error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600579
580 } while (png_ptr->zstream.avail_out);
Guy Schalnat0d580581995-07-20 02:43:20 -0500581
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500582 if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
583 {
584 if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
Mans Rullgardd3a94802011-11-03 00:47:55 -0500585 png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500586 png_ptr->prev_row + 1, png_ptr->row_buf[0]);
587 else
588 png_error(png_ptr, "bad adaptive filter value");
589 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500590
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500591 /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
592 * 1.5.6, while the buffer really is this big in current versions of libpng
593 * it may not be in the future, so this was changed just to copy the
594 * interlaced count:
595 */
596 png_memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
Glenn Randers-Pehrsone6474622006-03-04 16:50:47 -0600597
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500598#ifdef PNG_MNG_FEATURES_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500599 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600600 (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -0600601 {
602 /* Intrapixel differencing */
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500603 png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1);
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -0600604 }
605#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500606
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500607
John Bowler4a12f4a2011-04-17 18:34:22 -0500608#ifdef PNG_READ_TRANSFORMS_SUPPORTED
John Bowler9b872f42011-02-12 09:00:16 -0600609 if (png_ptr->transformations)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500610 png_do_read_transformations(png_ptr, &row_info);
John Bowler4a12f4a2011-04-17 18:34:22 -0500611#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500612
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500613 /* The transformed pixel depth should match the depth now in row_info. */
614 if (png_ptr->transformed_pixel_depth == 0)
615 {
616 png_ptr->transformed_pixel_depth = row_info.pixel_depth;
617 if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
618 png_error(png_ptr, "sequential row overflow");
619 }
620
621 else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
622 png_error(png_ptr, "internal sequential row size calculation error");
623
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500624#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -0500625 /* Blow up interlaced rows to full size */
Guy Schalnat0d580581995-07-20 02:43:20 -0500626 if (png_ptr->interlaced &&
627 (png_ptr->transformations & PNG_INTERLACE))
628 {
629 if (png_ptr->pass < 6)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500630 png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
631 png_ptr->transformations);
Guy Schalnat0d580581995-07-20 02:43:20 -0500632
Andreas Dilger47a0c421997-05-16 02:46:07 -0500633 if (dsp_row != NULL)
Glenn Randers-Pehrson65c03392011-10-06 21:54:17 -0500634 png_combine_row(png_ptr, dsp_row, 1/*display*/);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500635
Andreas Dilger47a0c421997-05-16 02:46:07 -0500636 if (row != NULL)
Glenn Randers-Pehrson65c03392011-10-06 21:54:17 -0500637 png_combine_row(png_ptr, row, 0/*row*/);
Guy Schalnat0d580581995-07-20 02:43:20 -0500638 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500639
Guy Schalnat0d580581995-07-20 02:43:20 -0500640 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500641#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500642 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500643 if (row != NULL)
Glenn Randers-Pehrson65c03392011-10-06 21:54:17 -0500644 png_combine_row(png_ptr, row, -1/*ignored*/);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500645
Andreas Dilger47a0c421997-05-16 02:46:07 -0500646 if (dsp_row != NULL)
Glenn Randers-Pehrson65c03392011-10-06 21:54:17 -0500647 png_combine_row(png_ptr, dsp_row, -1/*ignored*/);
Guy Schalnat0d580581995-07-20 02:43:20 -0500648 }
649 png_read_finish_row(png_ptr);
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600650
651 if (png_ptr->read_row_fn != NULL)
652 (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
Guy Schalnat0d580581995-07-20 02:43:20 -0500653}
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500654#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -0500655
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500656#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500657/* Read one or more rows of image data. If the image is interlaced,
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600658 * and png_set_interlace_handling() has been called, the rows need to
659 * contain the contents of the rows from the previous pass. If the
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500660 * image has alpha or transparency, and png_handle_alpha()[*] has been
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600661 * called, the rows contents must be initialized to the contents of the
662 * screen.
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600663 *
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600664 * "row" holds the actual image, and pixels are placed in it
665 * as they arrive. If the image is displayed after each pass, it will
666 * appear to "sparkle" in. "display_row" can be used to display a
667 * "chunky" progressive image, with finer detail added as it becomes
668 * available. If you do not want this "chunky" display, you may pass
669 * NULL for display_row. If you do not want the sparkle display, and
670 * you have not called png_handle_alpha(), you may pass NULL for rows.
671 * If you have called png_handle_alpha(), and the image has either an
672 * alpha channel or a transparency chunk, you must provide a buffer for
673 * rows. In this case, you do not have to provide a display_row buffer
674 * also, but you may. If the image is not interlaced, or if you have
675 * not called png_set_interlace_handling(), the display_row buffer will
676 * be ignored, so pass NULL to it.
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500677 *
Glenn Randers-Pehrsonc3d51c12006-03-02 07:23:18 -0600678 * [*] png_handle_alpha() does not exist yet, as of this version of libpng
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600679 */
Guy Schalnat6d764711995-12-19 03:22:19 -0600680
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500681void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600682png_read_rows(png_structp png_ptr, png_bytepp row,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600683 png_bytepp display_row, png_uint_32 num_rows)
Guy Schalnat0d580581995-07-20 02:43:20 -0500684{
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600685 png_uint_32 i;
686 png_bytepp rp;
687 png_bytepp dp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500688
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500689 png_debug(1, "in png_read_rows");
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500690
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500691 if (png_ptr == NULL)
692 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500693
Guy Schalnat0f716451995-11-28 11:22:13 -0600694 rp = row;
695 dp = display_row;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500696 if (rp != NULL && dp != NULL)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500697 for (i = 0; i < num_rows; i++)
698 {
699 png_bytep rptr = *rp++;
700 png_bytep dptr = *dp++;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600701
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500702 png_read_row(png_ptr, rptr, dptr);
703 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500704
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500705 else if (rp != NULL)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500706 for (i = 0; i < num_rows; i++)
707 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500708 png_bytep rptr = *rp;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500709 png_read_row(png_ptr, rptr, NULL);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500710 rp++;
711 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500712
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500713 else if (dp != NULL)
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500714 for (i = 0; i < num_rows; i++)
715 {
716 png_bytep dptr = *dp;
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500717 png_read_row(png_ptr, NULL, dptr);
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500718 dp++;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500719 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500720}
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500721#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -0500722
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500723#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500724/* Read the entire image. If the image has an alpha channel or a tRNS
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500725 * chunk, and you have called png_handle_alpha()[*], you will need to
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600726 * initialize the image to the current image that PNG will be overlaying.
727 * We set the num_rows again here, in case it was incorrectly set in
728 * png_read_start_row() by a call to png_read_update_info() or
729 * png_start_read_image() if png_set_interlace_handling() wasn't called
730 * prior to either of these functions like it should have been. You can
731 * only call this function once. If you desire to have an image for
732 * each pass of a interlaced image, use png_read_rows() instead.
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500733 *
Glenn Randers-Pehrsonc3d51c12006-03-02 07:23:18 -0600734 * [*] png_handle_alpha() does not exist yet, as of this version of libpng
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600735 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500736void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600737png_read_image(png_structp png_ptr, png_bytepp image)
Guy Schalnat0d580581995-07-20 02:43:20 -0500738{
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500739 png_uint_32 i, image_height;
Guy Schalnat0d580581995-07-20 02:43:20 -0500740 int pass, j;
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600741 png_bytepp rp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500742
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500743 png_debug(1, "in png_read_image");
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500744
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500745 if (png_ptr == NULL)
746 return;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500747
748#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500749 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
750 {
751 pass = png_set_interlace_handling(png_ptr);
752 /* And make sure transforms are initialized. */
753 png_start_read_image(png_ptr);
754 }
755 else
756 {
Glenn Randers-Pehrsone15a96b2011-01-14 15:47:37 -0600757 if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE))
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500758 {
Glenn Randers-Pehrson29034c52010-07-29 17:58:49 -0500759 /* Caller called png_start_read_image or png_read_update_info without
760 * first turning on the PNG_INTERLACE transform. We can fix this here,
761 * but the caller should do it!
762 */
763 png_warning(png_ptr, "Interlace handling should be turned on when "
764 "using png_read_image");
765 /* Make sure this is set correctly */
766 png_ptr->num_rows = png_ptr->height;
Glenn Randers-Pehrson31aee0d2010-07-29 17:39:14 -0500767 }
768
769 /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in
770 * the above error case.
771 */
772 pass = png_set_interlace_handling(png_ptr);
773 }
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500774#else
775 if (png_ptr->interlaced)
776 png_error(png_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600777 "Cannot read interlaced image -- interlace handler disabled");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500778
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500779 pass = 1;
780#endif
781
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500782 image_height=png_ptr->height;
Guy Schalnate5a37791996-06-05 15:50:50 -0500783
Guy Schalnat0d580581995-07-20 02:43:20 -0500784 for (j = 0; j < pass; j++)
785 {
786 rp = image;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500787 for (i = 0; i < image_height; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500788 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -0500789 png_read_row(png_ptr, *rp, NULL);
Guy Schalnat0d580581995-07-20 02:43:20 -0500790 rp++;
791 }
792 }
793}
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500794#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -0500795
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500796#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
Andreas Dilger47a0c421997-05-16 02:46:07 -0500797/* Read the end of the PNG file. Will not read past the end of the
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600798 * file, will verify the end is accurate, and will read any comments
799 * or time information at the end of the file, if info is not NULL.
800 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500801void PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600802png_read_end(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500803{
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500804 png_debug(1, "in png_read_end");
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500805
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500806 if (png_ptr == NULL)
807 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500808
Andreas Dilger47a0c421997-05-16 02:46:07 -0500809 png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
Guy Schalnat0d580581995-07-20 02:43:20 -0500810
811 do
812 {
Glenn Randers-Pehrson895a9c92008-07-25 08:51:18 -0500813 png_uint_32 length = png_read_chunk_header(png_ptr);
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500814 png_uint_32 chunk_name = png_ptr->chunk_name;
Guy Schalnat0d580581995-07-20 02:43:20 -0500815
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500816 if (chunk_name == png_IHDR)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600817 png_handle_IHDR(png_ptr, info_ptr, length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500818
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500819 else if (chunk_name == png_IEND)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600820 png_handle_IEND(png_ptr, info_ptr, length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500821
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600822#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500823 else if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
824 PNG_HANDLE_CHUNK_AS_DEFAULT)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600825 {
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500826 if (chunk_name == png_IDAT)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600827 {
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500828 if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500829 png_benign_error(png_ptr, "Too many IDATs found");
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600830 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600831 png_handle_unknown(png_ptr, info_ptr, length);
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500832 if (chunk_name == png_PLTE)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600833 png_ptr->mode |= PNG_HAVE_PLTE;
834 }
835#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500836
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500837 else if (chunk_name == png_IDAT)
Guy Schalnat0d580581995-07-20 02:43:20 -0500838 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500839 /* Zero length IDATs are legal after the last IDAT has been
840 * read, but not after other chunks have been read.
841 */
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500842 if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500843 png_benign_error(png_ptr, "Too many IDATs found");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500844
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500845 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500846 }
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500847 else if (chunk_name == png_PLTE)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500848 png_handle_PLTE(png_ptr, info_ptr, length);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500849
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500850#ifdef PNG_READ_bKGD_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500851 else if (chunk_name == png_bKGD)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500852 png_handle_bKGD(png_ptr, info_ptr, length);
853#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500854
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500855#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500856 else if (chunk_name == png_cHRM)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500857 png_handle_cHRM(png_ptr, info_ptr, length);
858#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500859
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500860#ifdef PNG_READ_gAMA_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500861 else if (chunk_name == png_gAMA)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500862 png_handle_gAMA(png_ptr, info_ptr, length);
863#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500864
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500865#ifdef PNG_READ_hIST_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500866 else if (chunk_name == png_hIST)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500867 png_handle_hIST(png_ptr, info_ptr, length);
868#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500869
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500870#ifdef PNG_READ_oFFs_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500871 else if (chunk_name == png_oFFs)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500872 png_handle_oFFs(png_ptr, info_ptr, length);
873#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500874
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500875#ifdef PNG_READ_pCAL_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500876 else if (chunk_name == png_pCAL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500877 png_handle_pCAL(png_ptr, info_ptr, length);
878#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500879
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500880#ifdef PNG_READ_sCAL_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500881 else if (chunk_name == png_sCAL)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600882 png_handle_sCAL(png_ptr, info_ptr, length);
883#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500884
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500885#ifdef PNG_READ_pHYs_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500886 else if (chunk_name == png_pHYs)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500887 png_handle_pHYs(png_ptr, info_ptr, length);
888#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500889
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500890#ifdef PNG_READ_sBIT_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500891 else if (chunk_name == png_sBIT)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500892 png_handle_sBIT(png_ptr, info_ptr, length);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500893#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500894
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500895#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500896 else if (chunk_name == png_sRGB)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600897 png_handle_sRGB(png_ptr, info_ptr, length);
898#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500899
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500900#ifdef PNG_READ_iCCP_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500901 else if (chunk_name == png_iCCP)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600902 png_handle_iCCP(png_ptr, info_ptr, length);
903#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500904
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500905#ifdef PNG_READ_sPLT_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500906 else if (chunk_name == png_sPLT)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600907 png_handle_sPLT(png_ptr, info_ptr, length);
908#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500909
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500910#ifdef PNG_READ_tEXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500911 else if (chunk_name == png_tEXt)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600912 png_handle_tEXt(png_ptr, info_ptr, length);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500913#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500914
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500915#ifdef PNG_READ_tIME_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500916 else if (chunk_name == png_tIME)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500917 png_handle_tIME(png_ptr, info_ptr, length);
918#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500919
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500920#ifdef PNG_READ_tRNS_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500921 else if (chunk_name == png_tRNS)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500922 png_handle_tRNS(png_ptr, info_ptr, length);
923#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500924
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500925#ifdef PNG_READ_zTXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500926 else if (chunk_name == png_zTXt)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600927 png_handle_zTXt(png_ptr, info_ptr, length);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500928#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500929
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500930#ifdef PNG_READ_iTXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500931 else if (chunk_name == png_iTXt)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600932 png_handle_iTXt(png_ptr, info_ptr, length);
933#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500934
Guy Schalnat0d580581995-07-20 02:43:20 -0500935 else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600936 png_handle_unknown(png_ptr, info_ptr, length);
937 } while (!(png_ptr->mode & PNG_HAVE_IEND));
Guy Schalnat0d580581995-07-20 02:43:20 -0500938}
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -0500939#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
Guy Schalnat0d580581995-07-20 02:43:20 -0500940
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -0500941/* Free all memory used by the read */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500942void PNGAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500943png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600944 png_infopp end_info_ptr_ptr)
Guy Schalnate5a37791996-06-05 15:50:50 -0500945{
946 png_structp png_ptr = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600947 png_infop info_ptr = NULL, end_info_ptr = NULL;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500948#ifdef PNG_USER_MEM_SUPPORTED
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500949 png_free_ptr free_fn = NULL;
950 png_voidp mem_ptr = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600951#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500952
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -0500953 png_debug(1, "in png_destroy_read_struct");
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500954
Andreas Dilger47a0c421997-05-16 02:46:07 -0500955 if (png_ptr_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500956 png_ptr = *png_ptr_ptr;
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500957 if (png_ptr == NULL)
958 return;
959
960#ifdef PNG_USER_MEM_SUPPORTED
961 free_fn = png_ptr->free_fn;
962 mem_ptr = png_ptr->mem_ptr;
963#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500964
Andreas Dilger47a0c421997-05-16 02:46:07 -0500965 if (info_ptr_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500966 info_ptr = *info_ptr_ptr;
967
Andreas Dilger47a0c421997-05-16 02:46:07 -0500968 if (end_info_ptr_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600969 end_info_ptr = *end_info_ptr_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -0500970
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600971 png_read_destroy(png_ptr, info_ptr, end_info_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -0500972
Andreas Dilger47a0c421997-05-16 02:46:07 -0500973 if (info_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500974 {
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500975#ifdef PNG_TEXT_SUPPORTED
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600976 png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600977#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500978
979#ifdef PNG_USER_MEM_SUPPORTED
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500980 png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
981 (png_voidp)mem_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500982#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600983 png_destroy_struct((png_voidp)info_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500984#endif
Glenn Randers-Pehrson3f549252001-10-27 07:35:13 -0500985 *info_ptr_ptr = NULL;
Guy Schalnate5a37791996-06-05 15:50:50 -0500986 }
987
Andreas Dilger47a0c421997-05-16 02:46:07 -0500988 if (end_info_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500989 {
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500990#ifdef PNG_READ_TEXT_SUPPORTED
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -0600991 png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -0600992#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500993#ifdef PNG_USER_MEM_SUPPORTED
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -0500994 png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600995 (png_voidp)mem_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500996#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600997 png_destroy_struct((png_voidp)end_info_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500998#endif
Glenn Randers-Pehrson3f549252001-10-27 07:35:13 -0500999 *end_info_ptr_ptr = NULL;
Guy Schalnate5a37791996-06-05 15:50:50 -05001000 }
1001
Andreas Dilger47a0c421997-05-16 02:46:07 -05001002 if (png_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -05001003 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001004#ifdef PNG_USER_MEM_SUPPORTED
Glenn Randers-Pehrson8b6a8892001-05-18 04:54:50 -05001005 png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
1006 (png_voidp)mem_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001007#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001008 png_destroy_struct((png_voidp)png_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001009#endif
Glenn Randers-Pehrson3f549252001-10-27 07:35:13 -05001010 *png_ptr_ptr = NULL;
Guy Schalnate5a37791996-06-05 15:50:50 -05001011 }
1012}
1013
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -05001014/* Free all memory used by the read (old method) */
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001015void /* PRIVATE */
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -06001016png_read_destroy(png_structp png_ptr, png_infop info_ptr,
1017 png_infop end_info_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05001018{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001019#ifdef PNG_SETJMP_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05001020 jmp_buf tmp_jmp;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001021#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001022 png_error_ptr error_fn;
John Bowler88b77cc2011-05-05 06:49:55 -05001023#ifdef PNG_WARNINGS_SUPPORTED
Guy Schalnate5a37791996-06-05 15:50:50 -05001024 png_error_ptr warning_fn;
John Bowler88b77cc2011-05-05 06:49:55 -05001025#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001026 png_voidp error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001027#ifdef PNG_USER_MEM_SUPPORTED
1028 png_free_ptr free_fn;
1029#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001030
Glenn Randers-Pehrson51650b82008-08-05 07:44:42 -05001031 png_debug(1, "in png_read_destroy");
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -05001032
Andreas Dilger47a0c421997-05-16 02:46:07 -05001033 if (info_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001034 png_info_destroy(png_ptr, info_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -05001035
Andreas Dilger47a0c421997-05-16 02:46:07 -05001036 if (end_info_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001037 png_info_destroy(png_ptr, end_info_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -05001038
John Bowler07772cb2011-10-14 18:19:47 -05001039#ifdef PNG_READ_GAMMA_SUPPORTED
1040 png_destroy_gamma_table(png_ptr);
1041#endif
1042
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001043 png_free(png_ptr, png_ptr->zbuf);
Glenn Randers-Pehrson1b8e5672001-08-25 06:46:06 -05001044 png_free(png_ptr, png_ptr->big_row_buf);
Mans Rullgard1c422762011-10-17 16:52:19 -05001045 png_free(png_ptr, png_ptr->big_prev_row);
Glenn Randers-Pehrsonb3ff9682008-07-21 08:05:57 -05001046 png_free(png_ptr, png_ptr->chunkdata);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001047
Glenn Randers-Pehrson3cd7cff2010-04-16 19:27:08 -05001048#ifdef PNG_READ_QUANTIZE_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001049 png_free(png_ptr, png_ptr->palette_lookup);
Glenn Randers-Pehrson3cd7cff2010-04-16 19:27:08 -05001050 png_free(png_ptr, png_ptr->quantize_index);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001051#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001052
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001053 if (png_ptr->free_me & PNG_FREE_PLTE)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -06001054 png_zfree(png_ptr, png_ptr->palette);
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001055 png_ptr->free_me &= ~PNG_FREE_PLTE;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001056
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001057#if defined(PNG_tRNS_SUPPORTED) || \
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001058 defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001059 if (png_ptr->free_me & PNG_FREE_TRNS)
Glenn Randers-Pehrson6abea752009-08-08 16:52:06 -05001060 png_free(png_ptr, png_ptr->trans_alpha);
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001061 png_ptr->free_me &= ~PNG_FREE_TRNS;
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001062#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001063
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001064#ifdef PNG_READ_hIST_SUPPORTED
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001065 if (png_ptr->free_me & PNG_FREE_HIST)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001066 png_free(png_ptr, png_ptr->hist);
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001067 png_ptr->free_me &= ~PNG_FREE_HIST;
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001068#endif
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001069
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001070 inflateEnd(&png_ptr->zstream);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001071
Guy Schalnat6d764711995-12-19 03:22:19 -06001072#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001073 png_free(png_ptr, png_ptr->save_buffer);
Guy Schalnat6d764711995-12-19 03:22:19 -06001074#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001075
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001076#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
1077#ifdef PNG_TEXT_SUPPORTED
1078 png_free(png_ptr, png_ptr->current_text);
1079#endif /* PNG_TEXT_SUPPORTED */
1080#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
1081
Guy Schalnate5a37791996-06-05 15:50:50 -05001082 /* Save the important info out of the png_struct, in case it is
1083 * being used again.
1084 */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001085#ifdef PNG_SETJMP_SUPPORTED
John Bowlere6dc85b2011-04-27 14:47:15 -05001086 png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001087#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001088
1089 error_fn = png_ptr->error_fn;
John Bowler88b77cc2011-05-05 06:49:55 -05001090#ifdef PNG_WARNINGS_SUPPORTED
Guy Schalnate5a37791996-06-05 15:50:50 -05001091 warning_fn = png_ptr->warning_fn;
John Bowler88b77cc2011-05-05 06:49:55 -05001092#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001093 error_ptr = png_ptr->error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001094#ifdef PNG_USER_MEM_SUPPORTED
1095 free_fn = png_ptr->free_fn;
1096#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001097
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001098 png_memset(png_ptr, 0, png_sizeof(png_struct));
Guy Schalnate5a37791996-06-05 15:50:50 -05001099
1100 png_ptr->error_fn = error_fn;
John Bowler88b77cc2011-05-05 06:49:55 -05001101#ifdef PNG_WARNINGS_SUPPORTED
Guy Schalnate5a37791996-06-05 15:50:50 -05001102 png_ptr->warning_fn = warning_fn;
John Bowler88b77cc2011-05-05 06:49:55 -05001103#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001104 png_ptr->error_ptr = error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001105#ifdef PNG_USER_MEM_SUPPORTED
1106 png_ptr->free_fn = free_fn;
1107#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001108
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001109#ifdef PNG_SETJMP_SUPPORTED
John Bowlere6dc85b2011-04-27 14:47:15 -05001110 png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001111#endif
1112
Guy Schalnat0d580581995-07-20 02:43:20 -05001113}
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001114
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001115void PNGAPI
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001116png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
1117{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001118 if (png_ptr == NULL)
1119 return;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001120
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001121 png_ptr->read_row_fn = read_row_fn;
1122}
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001123
Glenn Randers-Pehrson5fea36f2004-07-28 08:20:44 -05001124
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05001125#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001126#ifdef PNG_INFO_IMAGE_SUPPORTED
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001127void PNGAPI
1128png_read_png(png_structp png_ptr, png_infop info_ptr,
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001129 int transforms,
1130 voidp params)
1131{
1132 int row;
1133
John Bowler6a6d79f2011-02-12 08:56:40 -06001134 if (png_ptr == NULL || info_ptr == NULL)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001135 return;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001136
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001137 /* png_read_info() gives us all of the information from the
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001138 * PNG file before the first IDAT (image data chunk).
1139 */
1140 png_read_info(png_ptr, info_ptr);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001141 if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
1142 png_error(png_ptr, "Image is too high to process with png_read_png()");
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001143
1144 /* -------------- image transformations start here ------------------- */
1145
Glenn Randers-Pehrsonaee83b42011-06-18 00:19:54 -05001146#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05001147 /* Tell libpng to strip 16-bit/color files down to 8 bits per color.
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001148 */
Glenn Randers-Pehrsonab63dd02011-06-17 20:04:17 -05001149 if (transforms & PNG_TRANSFORM_SCALE_16)
Glenn Randers-Pehrsonaee83b42011-06-18 00:19:54 -05001150 {
Glenn Randers-Pehrson6da2f2d2011-06-17 23:07:16 -05001151 /* Added at libpng-1.5.4. "strip_16" produces the same result that it
1152 * did in earlier versions, while "scale_16" is now more accurate.
1153 */
Glenn Randers-Pehrsonaee83b42011-06-18 00:19:54 -05001154 png_set_scale_16(png_ptr);
1155 }
Glenn Randers-Pehrsonaee83b42011-06-18 00:19:54 -05001156#endif
1157
1158#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
John Bowler8d261262011-06-18 13:37:11 -05001159 /* If both SCALE and STRIP are required pngrtran will effectively cancel the
1160 * latter by doing SCALE first. This is ok and allows apps not to check for
1161 * which is supported to get the right answer.
1162 */
1163 if (transforms & PNG_TRANSFORM_STRIP_16)
1164 png_set_strip_16(png_ptr);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001165#endif
1166
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001167#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001168 /* Strip alpha bytes from the input data without combining with
1169 * the background (not recommended).
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001170 */
1171 if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001172 png_set_strip_alpha(png_ptr);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001173#endif
1174
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001175#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001176 /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001177 * byte into separate bytes (useful for paletted and grayscale images).
1178 */
1179 if (transforms & PNG_TRANSFORM_PACKING)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001180 png_set_packing(png_ptr);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001181#endif
1182
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001183#ifdef PNG_READ_PACKSWAP_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001184 /* Change the order of packed pixels to least significant bit first
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001185 * (not useful if you are using png_set_packing).
1186 */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001187 if (transforms & PNG_TRANSFORM_PACKSWAP)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001188 png_set_packswap(png_ptr);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001189#endif
1190
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001191#ifdef PNG_READ_EXPAND_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001192 /* Expand paletted colors into true RGB triplets
1193 * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
1194 * Expand paletted or RGB images with transparency to full alpha
1195 * channels so the data will be available as RGBA quartets.
1196 */
1197 if (transforms & PNG_TRANSFORM_EXPAND)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001198 if ((png_ptr->bit_depth < 8) ||
1199 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
1200 (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001201 png_set_expand(png_ptr);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001202#endif
1203
Glenn Randers-Pehrson3cd7cff2010-04-16 19:27:08 -05001204 /* We don't handle background color or gamma transformation or quantizing.
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001205 */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001206
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001207#ifdef PNG_READ_INVERT_SUPPORTED
Glenn Randers-Pehrsond8eb62f2009-05-30 20:19:20 -05001208 /* Invert monochrome files to have 0 as white and 1 as black
Glenn Randers-Pehrson272489d2004-08-04 06:34:52 -05001209 */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001210 if (transforms & PNG_TRANSFORM_INVERT_MONO)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001211 png_set_invert_mono(png_ptr);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001212#endif
1213
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001214#ifdef PNG_READ_SHIFT_SUPPORTED
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001215 /* If you want to shift the pixel values from the range [0,255] or
1216 * [0,65535] to the original [0,7] or [0,31], or whatever range the
1217 * colors were originally in:
1218 */
1219 if ((transforms & PNG_TRANSFORM_SHIFT)
1220 && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
1221 {
1222 png_color_8p sig_bit;
1223
1224 png_get_sBIT(png_ptr, info_ptr, &sig_bit);
1225 png_set_shift(png_ptr, sig_bit);
1226 }
1227#endif
1228
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001229#ifdef PNG_READ_BGR_SUPPORTED
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001230 /* Flip the RGB pixels to BGR (or RGBA to BGRA) */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001231 if (transforms & PNG_TRANSFORM_BGR)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001232 png_set_bgr(png_ptr);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001233#endif
1234
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001235#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001236 /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001237 if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001238 png_set_swap_alpha(png_ptr);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001239#endif
1240
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001241#ifdef PNG_READ_SWAP_SUPPORTED
Glenn Randers-Pehrson55fbff32011-05-17 06:49:32 -05001242 /* Swap bytes of 16-bit files to least significant byte first */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001243 if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001244 png_set_swap(png_ptr);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001245#endif
1246
Glenn Randers-Pehrsonc1a4d642009-10-29 23:29:24 -05001247/* Added at libpng-1.2.41 */
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001248#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001249 /* Invert the alpha channel from opacity to transparency */
Glenn Randers-Pehrson6878eb62009-06-29 16:45:53 -05001250 if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001251 png_set_invert_alpha(png_ptr);
Glenn Randers-Pehrson6878eb62009-06-29 16:45:53 -05001252#endif
1253
Glenn Randers-Pehrsonc1a4d642009-10-29 23:29:24 -05001254/* Added at libpng-1.2.41 */
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -05001255#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001256 /* Expand grayscale image to RGB */
Glenn Randers-Pehrson99708d52009-06-29 17:30:00 -05001257 if (transforms & PNG_TRANSFORM_GRAY_TO_RGB)
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001258 png_set_gray_to_rgb(png_ptr);
Glenn Randers-Pehrson99708d52009-06-29 17:30:00 -05001259#endif
1260
Glenn Randers-Pehrsonef217b72011-06-15 12:58:27 -05001261/* Added at libpng-1.5.4 */
John Bowler96cec0e2011-05-08 22:48:12 -05001262#ifdef PNG_READ_EXPAND_16_SUPPORTED
1263 if (transforms & PNG_TRANSFORM_EXPAND_16)
1264 png_set_expand_16(png_ptr);
1265#endif
1266
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001267 /* We don't handle adding filler bytes */
1268
John Bowler6a6d79f2011-02-12 08:56:40 -06001269 /* We use png_read_image and rely on that for interlace handling, but we also
1270 * call png_read_update_info therefore must turn on interlace handling now:
1271 */
1272 (void)png_set_interlace_handling(png_ptr);
1273
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001274 /* Optional call to gamma correct and add the background to the palette
1275 * and update info structure. REQUIRED if you are expecting libpng to
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001276 * update the palette for you (i.e., you selected such a transform above).
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001277 */
1278 png_read_update_info(png_ptr, info_ptr);
1279
1280 /* -------------- image transformations end here ------------------- */
1281
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -05001282 png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -05001283 if (info_ptr->row_pointers == NULL)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001284 {
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001285 png_uint_32 iptr;
Glenn Randers-Pehrsond9f21ee2009-08-31 10:52:38 -05001286
Glenn Randers-Pehrson0ffb71a2009-02-28 06:08:20 -06001287 info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001288 info_ptr->height * png_sizeof(png_bytep));
Glenn Randers-Pehrsond9f21ee2009-08-31 10:52:38 -05001289 for (iptr=0; iptr<info_ptr->height; iptr++)
1290 info_ptr->row_pointers[iptr] = NULL;
1291
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001292 info_ptr->free_me |= PNG_FREE_ROWS;
Glenn Randers-Pehrsond9f21ee2009-08-31 10:52:38 -05001293
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001294 for (row = 0; row < (int)info_ptr->height; row++)
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001295 info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001296 png_get_rowbytes(png_ptr, info_ptr));
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001297 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001298
1299 png_read_image(png_ptr, info_ptr->row_pointers);
1300 info_ptr->valid |= PNG_INFO_IDAT;
1301
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001302 /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001303 png_read_end(png_ptr, info_ptr);
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001304
Glenn Randers-Pehrsond546f432010-12-04 20:41:36 -06001305 PNG_UNUSED(transforms) /* Quiet compiler warnings */
1306 PNG_UNUSED(params)
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001307
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001308}
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06001309#endif /* PNG_INFO_IMAGE_SUPPORTED */
Glenn Randers-Pehrsondbd40142009-08-31 08:42:02 -05001310#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
John Bowler7875d532011-11-07 22:33:49 -06001311
1312#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
1313/* SIMPLIFIED READ
1314 *
1315 * This code currently relies on the sequential reader, though it could easily
1316 * be made to work with the progressive one.
1317 */
1318/* Do all the *safe* initialization - 'safe' means that png_error won't be
1319 * called, so setting up the jmp_buf is not required.
1320 */
1321static int
1322png_image_read_init(png_imagep image)
1323{
1324 png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image,
1325 png_safe_error, png_safe_warning);
1326
1327 if (png_ptr != NULL)
1328 {
1329 png_infop info_ptr = png_create_info_struct(png_ptr);
1330
1331 if (info_ptr != NULL)
1332 {
1333 png_controlp control = png_malloc_warn(png_ptr, sizeof *control);
1334
1335 if (control != NULL)
1336 {
1337 memset(control, 0, sizeof *control);
1338
1339 control->png_ptr = png_ptr;
1340 control->info_ptr = info_ptr;
1341 control->for_write = 0;
1342
1343 image->opaque = control;
1344 return 1;
1345 }
1346
1347 /* Error clean up */
1348 png_destroy_info_struct(png_ptr, &info_ptr);
1349 }
1350
1351 png_destroy_read_struct(&png_ptr, NULL, NULL);
1352 }
1353
1354 return png_image_error(image, "png_image_read: out of memory");
1355}
1356
1357/* Utility to find the base format of a PNG file from a png_struct. */
1358static png_uint_32
1359png_image_format(png_structp png_ptr, png_infop info_ptr)
1360{
1361 png_uint_32 format = 0;
1362
1363 if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
1364 format |= PNG_FORMAT_FLAG_COLOR;
1365
1366 if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1367 format |= PNG_FORMAT_FLAG_ALPHA;
1368
1369 else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
1370 format |= PNG_FORMAT_FLAG_ALPHA;
1371
1372 if (png_ptr->bit_depth == 16)
1373 format |= PNG_FORMAT_FLAG_LINEAR;
1374
1375 return format;
1376}
1377
1378/* Do the main body of a 'png_image_begin_read' function; read the PNG file
1379 * header and fill in all the information. This is executed in a safe context,
1380 * unlike the init routine above.
1381 */
1382static int
1383png_image_read_header(png_voidp argument)
1384{
1385 png_imagep image = argument;
1386 png_structp png_ptr = image->opaque->png_ptr;
1387 png_infop info_ptr = image->opaque->info_ptr;
1388
1389 png_read_info(png_ptr, info_ptr);
1390
1391 /* Do this the fast way; just read directly out of png_struct. */
1392 image->width = png_ptr->width;
1393 image->height = png_ptr->height;
1394
1395 {
1396 png_uint_32 format = png_image_format(png_ptr, info_ptr);
1397
1398 image->format = format;
1399 image->flags = 0;
1400
1401 /* Now try to work out whether the color data does not match sRGB. */
1402 if ((format & PNG_FORMAT_FLAG_COLOR) != 0 &&
1403 (info_ptr->valid & PNG_INFO_sRGB) == 0)
1404 {
1405 /* gamma is irrelevant because libpng does gamma correction, what
1406 * matters is if the cHRM chunk doesn't match or, in the absence of
1407 * cRHM, if the iCCP profile looks to have different end points.
1408 */
1409 if (info_ptr->valid & PNG_INFO_cHRM)
1410 {
1411 /* TODO: this is a copy'n'paste from pngrutil.c, make a common
1412 * checking function. This checks for a 1% error.
1413 */
1414 /* The cHRM chunk is used in preference to iCCP */
1415 if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) ||
1416 PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) ||
1417 PNG_OUT_OF_RANGE(info_ptr->x_red, 64000, 1000) ||
1418 PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) ||
1419 PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) ||
1420 PNG_OUT_OF_RANGE(info_ptr->y_green, 60000, 1000) ||
1421 PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) ||
1422 PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000))
1423 image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
1424 }
1425
1426 else if (info_ptr->valid & PNG_INFO_iCCP)
1427 {
1428# if 0 /* TODO: IMPLEMENT THIS! */
1429 /* Here if we just have an iCCP chunk. */
1430 if (!png_iCCP_is_sRGB(png_ptr, info_ptr))
1431# endif
1432 image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
1433 }
1434 }
1435 }
1436
1437 return 1;
1438}
1439
1440#ifdef PNG_STDIO_SUPPORTED
1441int PNGAPI
1442png_image_begin_read_from_stdio(png_imagep image, FILE* file)
1443{
1444 if (image != NULL)
1445 {
1446 if (file != NULL)
1447 {
1448 if (png_image_read_init(image))
1449 {
1450 /* This is slightly evil, but png_init_io doesn't do anything other
1451 * than this and we haven't changed the standard IO functions so
1452 * this saves a 'safe' function.
1453 */
1454 image->opaque->png_ptr->io_ptr = file;
1455 return png_safe_execute(image, png_image_read_header, image);
1456 }
1457 }
1458
1459 else
1460 return png_image_error(image,
1461 "png_image_begin_read_from_stdio: invalid argument");
1462 }
1463
1464 return 0;
1465}
1466
1467int PNGAPI
1468png_image_begin_read_from_file(png_imagep image, const char *file_name)
1469{
1470 if (image != NULL)
1471 {
1472 if (file_name != NULL)
1473 {
1474 FILE *fp = fopen(file_name, "rb");
1475
1476 if (fp != NULL)
1477 {
1478 if (png_image_read_init(image))
1479 {
1480 image->opaque->png_ptr->io_ptr = fp;
1481 image->opaque->owned_file = 1;
1482 return png_safe_execute(image, png_image_read_header, image);
1483 }
1484
1485 /* Clean up: just the opened file. */
1486 (void)fclose(fp);
1487 }
1488
1489 else
1490 return png_image_error(image, strerror(errno));
1491 }
1492
1493 else
1494 return png_image_error(image,
1495 "png_image_begin_read_from_file: invalid argument");
1496 }
1497
1498 return 0;
1499}
1500#endif /* PNG_STDIO_SUPPORTED */
1501
1502static void PNGCBAPI
1503png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need)
1504{
1505 if (png_ptr != NULL)
1506 {
1507 png_imagep image = png_ptr->io_ptr;
1508 if (image != NULL)
1509 {
1510 png_controlp cp = image->opaque;
1511 if (cp != NULL)
1512 {
1513 png_const_bytep memory = cp->memory;
1514 png_size_t size = cp->size;
1515
1516 if (memory != NULL && size >= need)
1517 {
1518 memcpy(out, memory, need);
1519 cp->memory = memory + need;
1520 cp->size = size - need;
1521 return;
1522 }
1523
1524 png_error(png_ptr, "read beyond end of data");
1525 }
1526 }
1527
1528 png_error(png_ptr, "invalid memory read");
1529 }
1530}
1531
1532int PNGAPI png_image_begin_read_from_memory(png_imagep image,
1533 png_const_voidp memory, png_size_t size)
1534{
1535 if (image != NULL)
1536 {
1537 if (memory != NULL && size > 0)
1538 {
1539 if (png_image_read_init(image))
1540 {
1541 /* Now set the IO functions to read from the memory buffer and
1542 * store it into io_ptr. Again do this in-place to avoid calling a
1543 * libpng function that requires error handling.
1544 */
1545 image->opaque->memory = memory;
1546 image->opaque->size = size;
1547 image->opaque->png_ptr->io_ptr = image;
1548 image->opaque->png_ptr->read_data_fn = png_image_memory_read;
1549
1550 return png_safe_execute(image, png_image_read_header, image);
1551 }
1552 }
1553
1554 else
1555 return png_image_error(image,
1556 "png_image_begin_read_from_memory: invalid argument");
1557 }
1558
1559 return 0;
1560}
1561
1562/* Arguments to png_image_finish_read: */
1563typedef struct
1564{
1565 /* Arguments: */
1566 png_imagep image;
1567 png_voidp buffer;
1568 png_int_32 row_stride;
1569 png_colorp background;
1570 /* Local variables: */
1571 png_bytep local_row;
1572 png_bytep first_row;
1573 ptrdiff_t row_bytes; /* unsigned arithmetic step between rows */
1574} png_image_read_control;
1575
1576/* Just the row reading part of png_image_read. */
1577static int
1578png_image_read_composite(png_voidp argument)
1579{
1580 png_image_read_control *display = argument;
1581 png_imagep image = display->image;
1582 png_structp png_ptr = image->opaque->png_ptr;
1583 png_byte interlace_type = png_ptr->interlaced;
1584 int passes;
1585
1586 switch (interlace_type)
1587 {
1588 case PNG_INTERLACE_NONE:
1589 passes = 1;
1590 break;
1591
1592 case PNG_INTERLACE_ADAM7:
1593 passes = PNG_INTERLACE_ADAM7_PASSES;
1594 break;
1595
1596 default:
1597 png_error(png_ptr, "unknown interlace type");
1598 }
1599
1600 {
1601 png_uint_32 height = image->height;
1602 png_uint_32 width = image->width;
1603 unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
1604 int pass;
1605
1606 for (pass = 0; pass < passes; ++pass)
1607 {
1608 png_bytep row = display->first_row;
1609 unsigned int startx, stepx, stepy;
1610 png_uint_32 y;
1611
1612 if (interlace_type == PNG_INTERLACE_ADAM7)
1613 {
1614 /* The row may be empty for a short image: */
1615 if (PNG_PASS_COLS(width, pass) == 0)
1616 continue;
1617
1618 startx = PNG_PASS_START_COL(pass);
1619 stepx = PNG_PASS_COL_OFFSET(pass);
1620 y = PNG_PASS_START_ROW(pass);
1621 stepy = PNG_PASS_COL_OFFSET(pass);
1622 }
1623
1624 else
1625 {
1626 y = 0;
1627 startx = 0;
1628 stepx = stepy = 1;
1629 }
1630
1631 for (; y<height; y += stepy)
1632 if (interlace_type == PNG_INTERLACE_NONE ||
1633 PNG_ROW_IN_INTERLACE_PASS(y, pass))
1634 {
1635 png_bytep inrow = display->local_row;
1636 png_bytep outrow = row;
1637 png_uint_32 x;
1638
1639 /* Read the row, which is packed: */
1640 png_read_row(png_ptr, inrow, NULL);
1641
1642 /* Now do the composition on each pixel in this row. */
1643 for (x = startx; x<width; x += stepx, outrow += stepx*channels)
1644 {
1645 png_byte alpha = inrow[channels];
1646
1647 if (alpha > 0) /* else no change to the output */
1648 {
1649 unsigned int c;
1650
1651 for (c=0; c<channels; ++c)
1652 {
1653 png_uint_32 component = inrow[c];
1654
1655 if (alpha < 255) /* else just use component */
1656 {
1657 /* This is PNG_OPTIMIZED_ALPHA, the component value
1658 * is a linear 8-bit value. Combine this with the
1659 * current outrow[c] value which is sRGB encoded.
1660 * Arithmetic here is 16-bits to preserve the output
1661 * values correctly.
1662 */
1663 component *= 257*255; /* =65535 */
1664 component += (255-alpha)*png_sRGB_table[outrow[c]];
1665
1666 /* So 'component' is scaled by 255*65535 and is
1667 * therefore appropriate for the above tables.
1668 */
1669 component = PNG_sRGB_FROM_LINEAR(component);
1670 }
1671
1672 outrow[c] = (png_byte)component;
1673 }
1674 }
1675
1676 inrow += channels+1; /* components and alpha channel */
1677 }
1678
1679 row += display->row_bytes;
1680 }
1681 }
1682 }
1683
1684 return 1;
1685}
1686
1687/* The guts of png_image_finish_read as a png_safe_execute callback. */
1688static int
1689png_image_read_end(png_voidp argument)
1690{
1691 png_image_read_control *display = argument;
1692 png_imagep image = display->image;
1693 png_structp png_ptr = image->opaque->png_ptr;
1694 png_infop info_ptr = image->opaque->info_ptr;
1695
1696 png_uint_32 format = image->format;
1697 int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
1698 int do_local_compose = 0;
1699 int passes = 0;
1700
1701 /* Add transforms to ensure the correct output format is produced then check
1702 * that the required implementation support is there. Always expand; always
1703 * need 8 bits minimum, no palette and expanded tRNS.
1704 */
1705 png_set_expand(png_ptr);
1706
1707 /* Now check the format to see if it was modified. */
1708 {
1709 png_uint_32 base_format = png_image_format(png_ptr, info_ptr);
1710 png_uint_32 change = format ^ base_format;
John Bowler3615d032011-11-08 10:38:09 -06001711 png_fixed_point output_gamma;
1712 int mode; /* alpha mode */
John Bowler7875d532011-11-07 22:33:49 -06001713
1714 /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.
1715 */
1716 {
John Bowler3615d032011-11-08 10:38:09 -06001717 png_fixed_point input_gamma_default;
John Bowler7875d532011-11-07 22:33:49 -06001718
1719 if (base_format & PNG_FORMAT_FLAG_LINEAR)
1720 input_gamma_default = PNG_GAMMA_LINEAR;
1721 else
1722 input_gamma_default = PNG_DEFAULT_sRGB;
1723
1724 if (linear)
1725 {
John Bowler3615d032011-11-08 10:38:09 -06001726 mode = PNG_ALPHA_STANDARD; /* associated alpha */
John Bowler7875d532011-11-07 22:33:49 -06001727 output_gamma = PNG_GAMMA_LINEAR;
1728 }
1729
1730 else
1731 {
1732 mode = PNG_ALPHA_PNG;
1733 output_gamma = PNG_DEFAULT_sRGB;
1734 }
1735
John Bowler3615d032011-11-08 10:38:09 -06001736 /* If the input default and output gamma do not match, because sRGB is
1737 * being changed to linear, set the input default now via a dummy call
1738 * to png_set_alpha_mode_fixed.
John Bowler7875d532011-11-07 22:33:49 -06001739 */
John Bowler7875d532011-11-07 22:33:49 -06001740 if (input_gamma_default != output_gamma)
John Bowler3615d032011-11-08 10:38:09 -06001741 png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG,
1742 input_gamma_default);
1743 }
John Bowler7875d532011-11-07 22:33:49 -06001744
John Bowler3615d032011-11-08 10:38:09 -06001745 /* If the bit-depth changes then handle that here. */
1746 if (change & PNG_FORMAT_FLAG_LINEAR)
1747 {
1748 if (linear /*16-bit output*/)
1749 png_set_expand_16(png_ptr);
John Bowler7875d532011-11-07 22:33:49 -06001750
John Bowler3615d032011-11-08 10:38:09 -06001751 else /* 8-bit output */
1752 png_set_scale_16(png_ptr);
John Bowler7875d532011-11-07 22:33:49 -06001753
John Bowler3615d032011-11-08 10:38:09 -06001754 change &= ~PNG_FORMAT_FLAG_LINEAR;
John Bowler7875d532011-11-07 22:33:49 -06001755 }
1756
1757 /* Now the background/alpha channel changes. */
1758 if (change & PNG_FORMAT_FLAG_ALPHA)
1759 {
1760 /* Removing an alpha channel requires composition for the 8-bit
1761 * formats; for the 16-bit it is already done, above, by the
1762 * pre-multiplication and the channel just needs to be stripped.
1763 */
1764 if (base_format & PNG_FORMAT_FLAG_ALPHA)
1765 {
John Bowler3615d032011-11-08 10:38:09 -06001766 /* 16-bit output: just remove the channel */
John Bowler7875d532011-11-07 22:33:49 -06001767 if (linear) /* compose on black (well, pre-multiply) */
1768 png_set_strip_alpha(png_ptr);
1769
John Bowler3615d032011-11-08 10:38:09 -06001770 /* 8-bit output: do an appropriate compose */
John Bowler7875d532011-11-07 22:33:49 -06001771 else if (display->background != NULL)
1772 {
1773 png_color_16 c;
1774
1775 c.index = 0; /*unused*/
1776 c.red = display->background->red;
1777 c.green = display->background->green;
1778 c.blue = display->background->blue;
1779 c.gray = display->background->green;
1780
1781 /* This is always an 8-bit sRGB value, using the 'green' channel
1782 * for gray is much better than calculating the luminance here;
1783 * we can get off-by-one errors in that calculation relative to
1784 * the app expectations and that will show up in transparent
1785 * pixels.
1786 */
1787 png_set_background_fixed(png_ptr, &c,
1788 PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
1789 0/*gamma: not used*/);
1790 }
1791
1792 else /* compose on row: implemented below. */
1793 {
1794 do_local_compose = 1;
1795 /* This leaves the alpha channel in the output, it has to be
1796 * removed by the code below. Set the encoding to the 'OPTIMIZE'
1797 * one so the code only has to hack on the pixels that require
1798 * composition.
1799 */
John Bowler3615d032011-11-08 10:38:09 -06001800 mode = PNG_ALPHA_OPTIMIZED;
John Bowler7875d532011-11-07 22:33:49 -06001801 }
1802 }
1803
1804 else /* output needs an alpha channel */
1805 {
1806 /* This is tricky because it happens before the swap operation has
John Bowlere6fb6912011-11-08 21:35:16 -06001807 * been accomplished however the swap does *not* swap the added
1808 * alpha channel (weird API), so it must be added in the correct
1809 * place.
John Bowler7875d532011-11-07 22:33:49 -06001810 */
John Bowler3615d032011-11-08 10:38:09 -06001811 png_uint_32 filler; /* opaque filler */
John Bowlere6fb6912011-11-08 21:35:16 -06001812 int where;
John Bowler3615d032011-11-08 10:38:09 -06001813
1814 if (linear)
1815 filler = 65535;
1816
1817 else
1818 filler = 255;
1819
John Bowlere6fb6912011-11-08 21:35:16 -06001820# ifdef PNG_FORMAT_AFIRST_SUPPORTED
1821 if (format & PNG_FORMAT_FLAG_AFIRST)
1822 {
1823 where = PNG_FILLER_BEFORE;
1824 change &= ~PNG_FORMAT_FLAG_AFIRST;
1825 }
1826
1827 else
1828# endif
1829 where = PNG_FILLER_AFTER;
1830
1831 png_set_add_alpha(png_ptr, filler, where);
John Bowler7875d532011-11-07 22:33:49 -06001832 }
1833
John Bowlere6fb6912011-11-08 21:35:16 -06001834 /* This stops the (irrelevant) call to swap_alpha below. */
John Bowler7875d532011-11-07 22:33:49 -06001835 change &= ~PNG_FORMAT_FLAG_ALPHA;
1836 }
1837
John Bowler3615d032011-11-08 10:38:09 -06001838 /* Now set the alpha mode correctly; this is always done, even if there is
1839 * no alpha channel in either the input or the output because it correctly
1840 * sets the output gamma.
1841 */
1842 png_set_alpha_mode_fixed(png_ptr, mode, output_gamma);
1843
John Bowler7875d532011-11-07 22:33:49 -06001844 if (change & PNG_FORMAT_FLAG_COLOR)
1845 {
1846 /* gray<->color transformation required. */
1847 if (format & PNG_FORMAT_FLAG_COLOR)
1848 png_set_gray_to_rgb(png_ptr);
1849
1850 else
1851 png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,
1852 PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
1853
1854 change &= ~PNG_FORMAT_FLAG_COLOR;
1855 }
1856
1857# ifdef PNG_FORMAT_BGR_SUPPORTED
John Bowlere6fb6912011-11-08 21:35:16 -06001858 if (change & PNG_FORMAT_FLAG_BGR)
John Bowler7875d532011-11-07 22:33:49 -06001859 {
1860 /* Check only the output format; PNG is never BGR, don't do this if
1861 * the output is gray, but fix up the 'format' value in that case.
1862 */
1863 if (format & PNG_FORMAT_FLAG_COLOR)
1864 png_set_bgr(png_ptr);
1865
1866 else
1867 format &= ~PNG_FORMAT_FLAG_BGR;
1868
1869 change &= ~PNG_FORMAT_FLAG_BGR;
1870 }
1871# endif
1872
1873# ifdef PNG_FORMAT_AFIRST_SUPPORTED
John Bowlere6fb6912011-11-08 21:35:16 -06001874 if (change & PNG_FORMAT_FLAG_AFIRST)
John Bowler7875d532011-11-07 22:33:49 -06001875 {
1876 /* Only relevant if there is an alpha channel - it's particularly
1877 * important to handle this correctly because do_local_compose may
1878 * be set above and then libpng will keep the alpha channel for this
1879 * code to remove.
1880 */
1881 if (format & PNG_FORMAT_FLAG_ALPHA)
1882 png_set_swap_alpha(png_ptr);
1883
1884 else
1885 format &= ~PNG_FORMAT_FLAG_AFIRST;
1886
1887 change &= ~PNG_FORMAT_FLAG_AFIRST;
1888 }
1889# endif
1890
1891 /* If the *output* is 16-bit then we need to check for a byte-swap on this
1892 * architecture.
1893 */
1894 if (linear)
1895 {
1896 PNG_CONST png_uint_16 le = 0x0001;
1897
1898 if (*(png_const_bytep)&le)
1899 png_set_swap(png_ptr);
1900 }
1901
1902 /* If change is not now 0 some transformation is missing - error out. */
1903 if (change)
1904 png_error(png_ptr, "png_read_image: unsupported transformation");
1905 }
1906
1907 /* Update the 'info' structure and make sure the result is as required, first
1908 * make sure to turn on the interlace handling if it will be required
1909 * (because it can't be turned on *after* the call to png_read_update_info!)
1910 */
1911 if (!do_local_compose)
1912 passes = png_set_interlace_handling(png_ptr);
1913
1914 png_read_update_info(png_ptr, info_ptr);
1915
1916 {
1917 png_uint_32 info_format = 0;
1918
1919 if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
1920 info_format |= PNG_FORMAT_FLAG_COLOR;
1921
1922 if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
1923 {
1924 /* This channel may be removed below. */
1925 if (!do_local_compose)
1926 info_format |= PNG_FORMAT_FLAG_ALPHA;
1927 }
1928
1929 else if (do_local_compose) /* internal error */
1930 png_error(png_ptr, "png_image_read: alpha channel lost");
1931
1932 if (info_ptr->bit_depth == 16)
1933 info_format |= PNG_FORMAT_FLAG_LINEAR;
1934
1935# ifdef PNG_FORMAT_BGR_SUPPORTED
1936 if (png_ptr->transformations & PNG_BGR)
1937 info_format |= PNG_FORMAT_FLAG_BGR;
1938# endif
1939
1940# ifdef PNG_FORMAT_AFIRST_SUPPORTED
John Bowlere6fb6912011-11-08 21:35:16 -06001941 if (png_ptr->transformations & PNG_SWAP_ALPHA ||
1942 ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&
1943 (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0))
John Bowler7875d532011-11-07 22:33:49 -06001944 info_format |= PNG_FORMAT_FLAG_AFIRST;
1945# endif
1946
1947 /* This is actually an internal error. */
1948 if (info_format != format)
1949 png_error(png_ptr, "png_read_image: invalid transformations");
1950 }
1951
1952 /* Now read the rows. If do_local_compose is set then it is necessary to use
1953 * a local row buffer. The output will be GA, RGBA or BGRA and must be
1954 * converted to G, RGB or BGR as appropriate. The 'local_row' member of the
1955 * display acts as a flag.
1956 */
1957 {
1958 png_bytep first_row = display->buffer;
1959 ptrdiff_t row_bytes = display->row_stride;
1960
1961 if (linear)
1962 row_bytes *= sizeof (png_uint_16);
1963
1964 /* The following expression is designed to work correctly whether it gives
1965 * a signed or an unsigned result.
1966 */
1967 if (row_bytes < 0)
1968 first_row += (image->height-1) * (-row_bytes);
1969
1970 display->first_row = first_row;
1971 display->row_bytes = row_bytes;
1972 }
1973
1974 if (do_local_compose)
1975 {
1976 int result;
1977 png_bytep row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
1978
1979 display->local_row = row;
1980 result = png_safe_execute(image, png_image_read_composite, display);
1981 display->local_row = NULL;
1982 png_free(png_ptr, row);
1983
1984 return result;
1985 }
1986
1987 else
1988 {
1989 png_alloc_size_t row_bytes = display->row_bytes;
1990
1991 while (--passes >= 0)
1992 {
1993 png_uint_32 y = image->height;
1994 png_bytep row = display->first_row;
1995
1996 while (y-- > 0)
1997 {
1998 png_read_row(png_ptr, row, NULL);
1999 row += row_bytes;
2000 }
2001 }
2002
2003 return 1;
2004 }
2005}
2006
2007int PNGAPI
2008png_image_finish_read(png_imagep image, png_colorp background, void *buffer,
2009 png_int_32 row_stride)
2010{
2011 if (image != NULL)
2012 {
2013 png_uint_32 check;
2014
2015 if (row_stride < 0)
2016 check = -row_stride;
2017
2018 else
2019 check = row_stride;
2020
2021 if (buffer != NULL && check >= PNG_IMAGE_ROW_STRIDE(*image))
2022 {
2023 int result;
2024 png_image_read_control display;
2025
2026 memset(&display, 0, sizeof display);
2027 display.image = image;
2028 display.buffer = buffer;
2029 display.row_stride = row_stride;
2030 display.background = background;
2031 display.local_row = NULL;
2032 result = png_safe_execute(image, png_image_read_end, &display);
2033 png_image_free(image);
2034 return result;
2035 }
2036
2037 else
2038 return png_image_error(image,
2039 "png_image_finish_read: invalid argument");
2040 }
2041
2042 return 0;
2043}
2044
2045#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */
Glenn Randers-Pehrson9c3ab682006-02-20 22:09:05 -06002046#endif /* PNG_READ_SUPPORTED */