blob: b2ced9b9225101115964d42202684040d9b60783 [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-Pehrson2ad31ae2000-12-15 08:54:42 -06004 * libpng 1.0.9beta5 - December 15, 2000
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06005 * For conditions of distribution and use, see copyright notice in png.h
Glenn Randers-Pehrsonf5ed0e12000-11-18 18:19:14 -06006 * Copyright (c) 1998, 1999, 2000 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05007 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
8 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06009 *
10 * This file contains routines that an application calls directly to
11 * read a PNG file or stream.
12 */
Guy Schalnat0d580581995-07-20 02:43:20 -050013
14#define PNG_INTERNAL
15#include "png.h"
16
Andreas Dilger47a0c421997-05-16 02:46:07 -050017/* Create a PNG structure for reading, and allocate any memory needed. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050018png_structp PNGAPI
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -050019png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060020 png_error_ptr error_fn, png_error_ptr warn_fn)
Guy Schalnat0d580581995-07-20 02:43:20 -050021{
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050022
23#ifdef PNG_USER_MEM_SUPPORTED
24 return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
25 warn_fn, NULL, NULL, NULL));
26}
27
28/* Alternate create PNG structure for reading, and allocate any memory needed. */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050029png_structp PNGAPI
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050030png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
31 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
32 png_malloc_ptr malloc_fn, png_free_ptr free_fn)
33{
34#endif /* PNG_USER_MEM_SUPPORTED */
35
Guy Schalnate5a37791996-06-05 15:50:50 -050036 png_structp png_ptr;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -060037
38#ifdef PNG_SETJMP_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060039#ifdef USE_FAR_KEYWORD
40 jmp_buf jmpbuf;
41#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -060042#endif
43
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050044 int i;
45
Andreas Dilger47a0c421997-05-16 02:46:07 -050046 png_debug(1, "in png_create_read_struct\n");
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050047#ifdef PNG_USER_MEM_SUPPORTED
48 if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
49 (png_malloc_ptr)malloc_fn)) == NULL)
50#else
Guy Schalnate5a37791996-06-05 15:50:50 -050051 if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050052#endif
Guy Schalnate5a37791996-06-05 15:50:50 -050053 {
54 return (png_structp)NULL;
55 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -060056
57#ifdef PNG_SETJMP_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060058#ifdef USE_FAR_KEYWORD
59 if (setjmp(jmpbuf))
60#else
Guy Schalnate5a37791996-06-05 15:50:50 -050061 if (setjmp(png_ptr->jmpbuf))
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060062#endif
Guy Schalnate5a37791996-06-05 15:50:50 -050063 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060064 png_free(png_ptr, png_ptr->zbuf);
Glenn Randers-Pehrson4766a242000-07-17 06:17:09 -050065 png_ptr->zbuf=NULL;
Guy Schalnate5a37791996-06-05 15:50:50 -050066 png_destroy_struct(png_ptr);
67 return (png_structp)NULL;
68 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060069#ifdef USE_FAR_KEYWORD
70 png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
71#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -060072#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050073
74#ifdef PNG_USER_MEM_SUPPORTED
75 png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060076#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -050077
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060078 png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
Guy Schalnat6d764711995-12-19 03:22:19 -060079
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050080 i=0;
81 do
Guy Schalnate5a37791996-06-05 15:50:50 -050082 {
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050083 if(user_png_ver[i] != png_libpng_ver[i])
84 png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
85 } while (png_libpng_ver[i++]);
Guy Schalnate5a37791996-06-05 15:50:50 -050086
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050087 if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
Glenn Randers-Pehrson98c9d732000-05-03 21:06:11 -050088 {
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050089 /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
90 * we must recompile any applications that use any older library version.
91 * For versions after libpng 1.0, we will be compatible, so we need
92 * only check the first digit.
93 */
94 if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
95 (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
96 {
97 png_error(png_ptr,
98 "Incompatible libpng version in application and library");
99 }
100
101 /* Libpng 1.0.6 was not binary compatible, due to insertion of the
102 info_ptr->free_me member. Note to maintainer: this test can be
103 removed from version 2.0.0 and beyond because the previous test
104 would have already rejected it. */
105
Glenn Randers-Pehrsond56aca72000-11-23 11:51:42 -0600106 if (user_png_ver[4] == '6' && user_png_ver[2] == '0' &&
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500107 user_png_ver[0] == '1' && user_png_ver[5] == '\0')
108 {
109 png_error(png_ptr,
110 "Application must be recompiled; version 1.0.6 was incompatible");
111 }
Glenn Randers-Pehrson98c9d732000-05-03 21:06:11 -0500112 }
113
Guy Schalnate5a37791996-06-05 15:50:50 -0500114 /* initialize zbuf - compression buffer */
Guy Schalnat0d580581995-07-20 02:43:20 -0500115 png_ptr->zbuf_size = PNG_ZBUF_SIZE;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600116 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
117 (png_uint_32)png_ptr->zbuf_size);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600118 png_ptr->zstream.zalloc = png_zalloc;
119 png_ptr->zstream.zfree = png_zfree;
120 png_ptr->zstream.opaque = (voidpf)png_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -0500121
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600122 switch (inflateInit(&png_ptr->zstream))
Guy Schalnate5a37791996-06-05 15:50:50 -0500123 {
124 case Z_OK: /* Do nothing */ break;
125 case Z_MEM_ERROR:
126 case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;
127 case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break;
128 default: png_error(png_ptr, "Unknown zlib error");
129 }
130
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600131 png_ptr->zstream.next_out = png_ptr->zbuf;
132 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
Guy Schalnate5a37791996-06-05 15:50:50 -0500133
134 png_set_read_fn(png_ptr, NULL, NULL);
135
Guy Schalnate5a37791996-06-05 15:50:50 -0500136 return (png_ptr);
137}
138
Andreas Dilger47a0c421997-05-16 02:46:07 -0500139/* Initialize PNG structure for reading, and allocate any memory needed.
Glenn Randers-Pehrsond0dce401998-05-09 10:02:29 -0500140 This interface is deprecated in favour of the png_create_read_struct(),
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600141 and it will eventually disappear. */
Glenn Randers-Pehrson98c9d732000-05-03 21:06:11 -0500142#undef png_read_init
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500143void PNGAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500144png_read_init(png_structp png_ptr)
145{
Glenn Randers-Pehrson98c9d732000-05-03 21:06:11 -0500146 /* We only come here via pre-1.0.7-compiled applications */
147 png_read_init_2(png_ptr, "1.0.0", 10000, 10000);
148}
149
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500150void PNGAPI
Glenn Randers-Pehrson98c9d732000-05-03 21:06:11 -0500151png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver,
152 png_size_t png_struct_size, png_size_t png_info_size)
153{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600154#ifdef PNG_SETJMP_SUPPORTED
Guy Schalnate5a37791996-06-05 15:50:50 -0500155 jmp_buf tmp_jmp; /* to save current jump buffer */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600156#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500157
Glenn Randers-Pehrson98c9d732000-05-03 21:06:11 -0500158 int i=0;
159 do
160 {
161 if(user_png_ver[i] != png_libpng_ver[i])
162 {
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500163#ifdef PNG_LEGACY_SUPPORTED
164 png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
165#else
Glenn Randers-Pehrson98c9d732000-05-03 21:06:11 -0500166 png_ptr->error_fn=(png_error_ptr)NULL;
167 png_error(png_ptr,
168 "Application uses deprecated png_read_init() and must be recompiled.");
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500169#endif
Glenn Randers-Pehrson98c9d732000-05-03 21:06:11 -0500170 }
171 } while (png_libpng_ver[i++]);
Glenn Randers-Pehrson98c9d732000-05-03 21:06:11 -0500172
173 if(sizeof(png_struct) > png_struct_size ||
174 sizeof(png_info) > png_info_size)
175 {
176 png_ptr->error_fn=(png_error_ptr)NULL;
177 png_error(png_ptr,
178 "Application and library have different sized structs. Please recompile.");
179 }
180
181 png_debug(1, "in png_read_init_2\n");
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600182
183#ifdef PNG_SETJMP_SUPPORTED
Guy Schalnate5a37791996-06-05 15:50:50 -0500184 /* save jump buffer and error functions */
185 png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600186#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500187
188 /* reset all variables to 0 */
189 png_memset(png_ptr, 0, sizeof (png_struct));
190
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600191#ifdef PNG_SETJMP_SUPPORTED
Guy Schalnate5a37791996-06-05 15:50:50 -0500192 /* restore jump buffer */
193 png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600194#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500195
196 /* initialize zbuf - compression buffer */
197 png_ptr->zbuf_size = PNG_ZBUF_SIZE;
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600198 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
199 (png_uint_32)png_ptr->zbuf_size);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600200 png_ptr->zstream.zalloc = png_zalloc;
201 png_ptr->zstream.zfree = png_zfree;
202 png_ptr->zstream.opaque = (voidpf)png_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -0500203
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600204 switch (inflateInit(&png_ptr->zstream))
Guy Schalnate5a37791996-06-05 15:50:50 -0500205 {
206 case Z_OK: /* Do nothing */ break;
207 case Z_MEM_ERROR:
208 case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break;
209 case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break;
210 default: png_error(png_ptr, "Unknown zlib error");
211 }
212
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600213 png_ptr->zstream.next_out = png_ptr->zbuf;
214 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
Guy Schalnate5a37791996-06-05 15:50:50 -0500215
216 png_set_read_fn(png_ptr, NULL, NULL);
Guy Schalnat0d580581995-07-20 02:43:20 -0500217}
218
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600219/* Read the information before the actual image data. This has been
Glenn Randers-Pehrsonf9f2fe01998-03-15 18:20:23 -0600220 * changed in v0.90 to allow reading a file that already has the magic
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600221 * bytes read from the stream. You can tell libpng how many bytes have
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500222 * been read from the beginning of the stream (up to the maximum of 8)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600223 * via png_set_sig_bytes(), and we will only check the remaining bytes
224 * here. The application can then have access to the signature bytes we
225 * read if it is determined that this isn't a valid PNG file.
226 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500227void PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600228png_read_info(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500229{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500230 png_debug(1, "in png_read_info\n");
231 /* save jump buffer and error functions */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600232 /* If we haven't checked all of the PNG signature bytes, do so now. */
233 if (png_ptr->sig_bytes < 8)
Guy Schalnate5a37791996-06-05 15:50:50 -0500234 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500235 png_size_t num_checked = png_ptr->sig_bytes,
236 num_to_check = 8 - num_checked;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600237
Andreas Dilger47a0c421997-05-16 02:46:07 -0500238 png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600239 png_ptr->sig_bytes = 8;
240
241 if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
242 {
243 if (num_checked < 4 &&
244 png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
245 png_error(png_ptr, "Not a PNG file");
246 else
247 png_error(png_ptr, "PNG file corrupted by ASCII conversion");
248 }
Guy Schalnate5a37791996-06-05 15:50:50 -0500249 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500250
Glenn Randers-Pehrsonea3bcd71998-03-07 14:33:00 -0600251 for(;;)
Guy Schalnat0d580581995-07-20 02:43:20 -0500252 {
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600253#ifdef PNG_USE_LOCAL_ARRAYS
254 PNG_IHDR;
255 PNG_IDAT;
256 PNG_IEND;
257 PNG_PLTE;
258#if defined(PNG_READ_bKGD_SUPPORTED)
259 PNG_bKGD;
260#endif
261#if defined(PNG_READ_cHRM_SUPPORTED)
262 PNG_cHRM;
263#endif
264#if defined(PNG_READ_gAMA_SUPPORTED)
265 PNG_gAMA;
266#endif
267#if defined(PNG_READ_hIST_SUPPORTED)
268 PNG_hIST;
269#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600270#if defined(PNG_READ_iCCP_SUPPORTED)
271 PNG_iCCP;
272#endif
273#if defined(PNG_READ_iTXt_SUPPORTED)
274 PNG_iTXt;
275#endif
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600276#if defined(PNG_READ_oFFs_SUPPORTED)
277 PNG_oFFs;
278#endif
279#if defined(PNG_READ_pCAL_SUPPORTED)
280 PNG_pCAL;
281#endif
282#if defined(PNG_READ_pHYs_SUPPORTED)
283 PNG_pHYs;
284#endif
285#if defined(PNG_READ_sBIT_SUPPORTED)
286 PNG_sBIT;
287#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600288#if defined(PNG_READ_sCAL_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600289 PNG_sCAL;
290#endif
291#if defined(PNG_READ_sPLT_SUPPORTED)
292 PNG_sPLT;
293#endif
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600294#if defined(PNG_READ_sRGB_SUPPORTED)
295 PNG_sRGB;
296#endif
297#if defined(PNG_READ_tEXt_SUPPORTED)
298 PNG_tEXt;
299#endif
300#if defined(PNG_READ_tIME_SUPPORTED)
301 PNG_tIME;
302#endif
303#if defined(PNG_READ_tRNS_SUPPORTED)
304 PNG_tRNS;
305#endif
306#if defined(PNG_READ_zTXt_SUPPORTED)
307 PNG_zTXt;
308#endif
309#endif /* PNG_GLOBAL_ARRAYS */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600310 png_byte chunk_length[4];
311 png_uint_32 length;
Guy Schalnat0d580581995-07-20 02:43:20 -0500312
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600313 png_read_data(png_ptr, chunk_length, 4);
314 length = png_get_uint_32(chunk_length);
315
Guy Schalnat0d580581995-07-20 02:43:20 -0500316 png_reset_crc(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600317 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
318
Glenn Randers-Pehrson4766a242000-07-17 06:17:09 -0500319 png_debug2(0, "Reading %s chunk, length=%lu.\n", png_ptr->chunk_name,
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500320 length);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500321
322 /* This should be a binary subdivision search or a hash for
323 * matching the chunk name rather than a linear search.
324 */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600325 if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
326 png_handle_IHDR(png_ptr, info_ptr, length);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600327 else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
328 png_handle_IEND(png_ptr, info_ptr, length);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600329#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
330 else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
331 {
332 if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
333 png_ptr->mode |= PNG_HAVE_IDAT;
334 png_handle_unknown(png_ptr, info_ptr, length);
335 if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
336 png_ptr->mode |= PNG_HAVE_PLTE;
337 else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
338 {
339 if (!(png_ptr->mode & PNG_HAVE_IHDR))
340 png_error(png_ptr, "Missing IHDR before IDAT");
341 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
342 !(png_ptr->mode & PNG_HAVE_PLTE))
343 png_error(png_ptr, "Missing PLTE before IDAT");
344 break;
345 }
346 }
347#endif
348 else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
349 png_handle_PLTE(png_ptr, info_ptr, length);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600350 else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500351 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500352 if (!(png_ptr->mode & PNG_HAVE_IHDR))
353 png_error(png_ptr, "Missing IHDR before IDAT");
354 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
355 !(png_ptr->mode & PNG_HAVE_PLTE))
356 png_error(png_ptr, "Missing PLTE before IDAT");
357
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500358 png_ptr->idat_size = length;
Guy Schalnate5a37791996-06-05 15:50:50 -0500359 png_ptr->mode |= PNG_HAVE_IDAT;
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500360 break;
361 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500362#if defined(PNG_READ_bKGD_SUPPORTED)
363 else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
364 png_handle_bKGD(png_ptr, info_ptr, length);
365#endif
366#if defined(PNG_READ_cHRM_SUPPORTED)
367 else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
368 png_handle_cHRM(png_ptr, info_ptr, length);
369#endif
370#if defined(PNG_READ_gAMA_SUPPORTED)
371 else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
372 png_handle_gAMA(png_ptr, info_ptr, length);
373#endif
374#if defined(PNG_READ_hIST_SUPPORTED)
375 else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
376 png_handle_hIST(png_ptr, info_ptr, length);
377#endif
378#if defined(PNG_READ_oFFs_SUPPORTED)
379 else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
380 png_handle_oFFs(png_ptr, info_ptr, length);
381#endif
382#if defined(PNG_READ_pCAL_SUPPORTED)
383 else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
384 png_handle_pCAL(png_ptr, info_ptr, length);
385#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600386#if defined(PNG_READ_sCAL_SUPPORTED)
387 else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
388 png_handle_sCAL(png_ptr, info_ptr, length);
389#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500390#if defined(PNG_READ_pHYs_SUPPORTED)
391 else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
392 png_handle_pHYs(png_ptr, info_ptr, length);
393#endif
394#if defined(PNG_READ_sBIT_SUPPORTED)
395 else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
396 png_handle_sBIT(png_ptr, info_ptr, length);
397#endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600398#if defined(PNG_READ_sRGB_SUPPORTED)
399 else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
400 png_handle_sRGB(png_ptr, info_ptr, length);
401#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600402#if defined(PNG_READ_iCCP_SUPPORTED)
403 else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
404 png_handle_iCCP(png_ptr, info_ptr, length);
405#endif
406#if defined(PNG_READ_sPLT_SUPPORTED)
407 else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
408 png_handle_sPLT(png_ptr, info_ptr, length);
409#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500410#if defined(PNG_READ_tEXt_SUPPORTED)
411 else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
412 png_handle_tEXt(png_ptr, info_ptr, length);
413#endif
414#if defined(PNG_READ_tIME_SUPPORTED)
415 else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
416 png_handle_tIME(png_ptr, info_ptr, length);
417#endif
418#if defined(PNG_READ_tRNS_SUPPORTED)
419 else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
420 png_handle_tRNS(png_ptr, info_ptr, length);
421#endif
422#if defined(PNG_READ_zTXt_SUPPORTED)
423 else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
424 png_handle_zTXt(png_ptr, info_ptr, length);
425#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600426#if defined(PNG_READ_iTXt_SUPPORTED)
427 else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
428 png_handle_iTXt(png_ptr, info_ptr, length);
429#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500430 else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600431 png_handle_unknown(png_ptr, info_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500432 }
433}
434
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600435/* optional call to update the users info_ptr structure */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500436void PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600437png_read_update_info(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500438{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500439 png_debug(1, "in png_read_update_info\n");
440 /* save jump buffer and error functions */
Guy Schalnate5a37791996-06-05 15:50:50 -0500441 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500442 png_read_start_row(png_ptr);
Glenn Randers-Pehrson5e5c1e12000-11-10 12:26:19 -0600443 else
444 png_warning(png_ptr,
445 "Ignoring extra png_read_update_info() call; row buffer not reallocated");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600446 png_read_transform_info(png_ptr, info_ptr);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500447}
448
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600449/* Initialize palette, background, etc, after transformations
450 * are set, but before any reading takes place. This allows
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500451 * the user to obtain a gamma-corrected palette, for example.
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600452 * If the user doesn't call this, we will do it ourselves.
453 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500454void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600455png_start_read_image(png_structp png_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500456{
Andreas Dilger47a0c421997-05-16 02:46:07 -0500457 png_debug(1, "in png_start_read_image\n");
458 /* save jump buffer and error functions */
Guy Schalnate5a37791996-06-05 15:50:50 -0500459 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500460 png_read_start_row(png_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -0500461}
462
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500463void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600464png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
Guy Schalnat0d580581995-07-20 02:43:20 -0500465{
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600466#ifdef PNG_USE_LOCAL_ARRAYS
467 PNG_IDAT;
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600468 const int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
469 const int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600470#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500471 int ret;
Glenn Randers-Pehrson4766a242000-07-17 06:17:09 -0500472 png_debug2(1, "in png_read_row (row %lu, pass %d)\n",
Andreas Dilger47a0c421997-05-16 02:46:07 -0500473 png_ptr->row_number, png_ptr->pass);
474 /* save jump buffer and error functions */
Guy Schalnate5a37791996-06-05 15:50:50 -0500475 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
Guy Schalnat0d580581995-07-20 02:43:20 -0500476 png_read_start_row(png_ptr);
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500477 if (png_ptr->row_number == 0 && png_ptr->pass == 0)
478 {
479 /* check for transforms that have been set but were defined out */
480#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
481 if (png_ptr->transformations & PNG_INVERT_MONO)
482 png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined.");
483#endif
484#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
485 if (png_ptr->transformations & PNG_FILLER)
486 png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined.");
487#endif
488#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED)
489 if (png_ptr->transformations & PNG_PACKSWAP)
490 png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined.");
491#endif
492#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
493 if (png_ptr->transformations & PNG_PACK)
494 png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined.");
495#endif
496#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
497 if (png_ptr->transformations & PNG_SHIFT)
498 png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined.");
499#endif
500#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
501 if (png_ptr->transformations & PNG_BGR)
502 png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined.");
503#endif
504#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
505 if (png_ptr->transformations & PNG_SWAP_BYTES)
506 png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined.");
507#endif
508 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500509
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500510#if defined(PNG_READ_INTERLACING_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500511 /* if interlaced and we do not need a new row, combine row and return */
512 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
513 {
514 switch (png_ptr->pass)
515 {
516 case 0:
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600517 if (png_ptr->row_number & 0x07)
Guy Schalnat0d580581995-07-20 02:43:20 -0500518 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500519 if (dsp_row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500520 png_combine_row(png_ptr, dsp_row,
521 png_pass_dsp_mask[png_ptr->pass]);
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600522 png_read_finish_row(png_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -0500523 return;
524 }
525 break;
526 case 1:
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600527 if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
Guy Schalnat0d580581995-07-20 02:43:20 -0500528 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500529 if (dsp_row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500530 png_combine_row(png_ptr, dsp_row,
531 png_pass_dsp_mask[png_ptr->pass]);
532 png_read_finish_row(png_ptr);
533 return;
534 }
535 break;
536 case 2:
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600537 if ((png_ptr->row_number & 0x07) != 4)
Guy Schalnat0d580581995-07-20 02:43:20 -0500538 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500539 if (dsp_row != NULL && (png_ptr->row_number & 4))
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600540 png_combine_row(png_ptr, dsp_row,
Guy Schalnat0d580581995-07-20 02:43:20 -0500541 png_pass_dsp_mask[png_ptr->pass]);
542 png_read_finish_row(png_ptr);
543 return;
544 }
545 break;
546 case 3:
547 if ((png_ptr->row_number & 3) || png_ptr->width < 3)
548 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500549 if (dsp_row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500550 png_combine_row(png_ptr, dsp_row,
551 png_pass_dsp_mask[png_ptr->pass]);
552 png_read_finish_row(png_ptr);
553 return;
554 }
555 break;
556 case 4:
557 if ((png_ptr->row_number & 3) != 2)
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600558 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500559 if (dsp_row != NULL && (png_ptr->row_number & 2))
Guy Schalnat0d580581995-07-20 02:43:20 -0500560 png_combine_row(png_ptr, dsp_row,
561 png_pass_dsp_mask[png_ptr->pass]);
562 png_read_finish_row(png_ptr);
563 return;
564 }
565 break;
566 case 5:
567 if ((png_ptr->row_number & 1) || png_ptr->width < 2)
568 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500569 if (dsp_row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500570 png_combine_row(png_ptr, dsp_row,
571 png_pass_dsp_mask[png_ptr->pass]);
572 png_read_finish_row(png_ptr);
573 return;
574 }
575 break;
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600576 case 6:
Guy Schalnat0d580581995-07-20 02:43:20 -0500577 if (!(png_ptr->row_number & 1))
578 {
579 png_read_finish_row(png_ptr);
580 return;
581 }
582 break;
583 }
584 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500585#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500586
Guy Schalnate5a37791996-06-05 15:50:50 -0500587 if (!(png_ptr->mode & PNG_HAVE_IDAT))
588 png_error(png_ptr, "Invalid attempt to read row data");
Guy Schalnat0d580581995-07-20 02:43:20 -0500589
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600590 png_ptr->zstream.next_out = png_ptr->row_buf;
591 png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
Guy Schalnat0d580581995-07-20 02:43:20 -0500592 do
593 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600594 if (!(png_ptr->zstream.avail_in))
Guy Schalnat0d580581995-07-20 02:43:20 -0500595 {
596 while (!png_ptr->idat_size)
597 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600598 png_byte chunk_length[4];
Guy Schalnat0d580581995-07-20 02:43:20 -0500599
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600600 png_crc_finish(png_ptr, 0);
Guy Schalnat0d580581995-07-20 02:43:20 -0500601
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600602 png_read_data(png_ptr, chunk_length, 4);
603 png_ptr->idat_size = png_get_uint_32(chunk_length);
604
Guy Schalnat0d580581995-07-20 02:43:20 -0500605 png_reset_crc(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600606 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
607 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
608 png_error(png_ptr, "Not enough image data");
Guy Schalnat0d580581995-07-20 02:43:20 -0500609 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600610 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
611 png_ptr->zstream.next_in = png_ptr->zbuf;
Guy Schalnat0d580581995-07-20 02:43:20 -0500612 if (png_ptr->zbuf_size > png_ptr->idat_size)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600613 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500614 png_crc_read(png_ptr, png_ptr->zbuf,
615 (png_size_t)png_ptr->zstream.avail_in);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600616 png_ptr->idat_size -= png_ptr->zstream.avail_in;
Guy Schalnat0d580581995-07-20 02:43:20 -0500617 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600618 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnat0d580581995-07-20 02:43:20 -0500619 if (ret == Z_STREAM_END)
620 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600621 if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
Guy Schalnat0d580581995-07-20 02:43:20 -0500622 png_ptr->idat_size)
Guy Schalnat6d764711995-12-19 03:22:19 -0600623 png_error(png_ptr, "Extra compressed data");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600624 png_ptr->mode |= PNG_AFTER_IDAT;
Guy Schalnate5a37791996-06-05 15:50:50 -0500625 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600626 break;
Guy Schalnat0d580581995-07-20 02:43:20 -0500627 }
628 if (ret != Z_OK)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600629 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
Guy Schalnate5a37791996-06-05 15:50:50 -0500630 "Decompression error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600631
632 } while (png_ptr->zstream.avail_out);
Guy Schalnat0d580581995-07-20 02:43:20 -0500633
Guy Schalnat0d580581995-07-20 02:43:20 -0500634 png_ptr->row_info.color_type = png_ptr->color_type;
635 png_ptr->row_info.width = png_ptr->iwidth;
636 png_ptr->row_info.channels = png_ptr->channels;
637 png_ptr->row_info.bit_depth = png_ptr->bit_depth;
638 png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
Glenn Randers-Pehrson860ab2b1999-10-14 07:43:10 -0500639 png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
640 (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
Guy Schalnat0d580581995-07-20 02:43:20 -0500641
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600642 if(png_ptr->row_buf[0])
Guy Schalnate5a37791996-06-05 15:50:50 -0500643 png_read_filter_row(png_ptr, &(png_ptr->row_info),
644 png_ptr->row_buf + 1, png_ptr->prev_row + 1,
645 (int)(png_ptr->row_buf[0]));
Guy Schalnat0d580581995-07-20 02:43:20 -0500646
Glenn Randers-Pehrsona357b991998-02-08 20:56:40 -0600647 png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
Glenn Randers-Pehrson0f881d61998-02-07 10:20:57 -0600648 png_ptr->rowbytes + 1);
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -0600649
650#if defined(PNG_MNG_FEATURES_SUPPORTED)
651 if((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
652 (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
653 {
654 /* Intrapixel differencing */
655 png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
656 }
657#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500658
659 if (png_ptr->transformations)
660 png_do_read_transformations(png_ptr);
661
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500662#if defined(PNG_READ_INTERLACING_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500663 /* blow up interlaced rows to full size */
664 if (png_ptr->interlaced &&
665 (png_ptr->transformations & PNG_INTERLACE))
666 {
667 if (png_ptr->pass < 6)
668 png_do_read_interlace(&(png_ptr->row_info),
Andreas Dilger47a0c421997-05-16 02:46:07 -0500669 png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
Guy Schalnat0d580581995-07-20 02:43:20 -0500670
Andreas Dilger47a0c421997-05-16 02:46:07 -0500671 if (dsp_row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500672 png_combine_row(png_ptr, dsp_row,
673 png_pass_dsp_mask[png_ptr->pass]);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500674 if (row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500675 png_combine_row(png_ptr, row,
676 png_pass_mask[png_ptr->pass]);
677 }
678 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500679#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500680 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500681 if (row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500682 png_combine_row(png_ptr, row, 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500683 if (dsp_row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500684 png_combine_row(png_ptr, dsp_row, 0xff);
685 }
686 png_read_finish_row(png_ptr);
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600687
688 if (png_ptr->read_row_fn != NULL)
689 (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
Guy Schalnat0d580581995-07-20 02:43:20 -0500690}
691
Andreas Dilger47a0c421997-05-16 02:46:07 -0500692/* Read one or more rows of image data. If the image is interlaced,
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600693 * and png_set_interlace_handling() has been called, the rows need to
694 * contain the contents of the rows from the previous pass. If the
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500695 * image has alpha or transparency, and png_handle_alpha()[*] has been
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600696 * called, the rows contents must be initialized to the contents of the
697 * screen.
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600698 *
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600699 * "row" holds the actual image, and pixels are placed in it
700 * as they arrive. If the image is displayed after each pass, it will
701 * appear to "sparkle" in. "display_row" can be used to display a
702 * "chunky" progressive image, with finer detail added as it becomes
703 * available. If you do not want this "chunky" display, you may pass
704 * NULL for display_row. If you do not want the sparkle display, and
705 * you have not called png_handle_alpha(), you may pass NULL for rows.
706 * If you have called png_handle_alpha(), and the image has either an
707 * alpha channel or a transparency chunk, you must provide a buffer for
708 * rows. In this case, you do not have to provide a display_row buffer
709 * also, but you may. If the image is not interlaced, or if you have
710 * not called png_set_interlace_handling(), the display_row buffer will
711 * be ignored, so pass NULL to it.
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500712 *
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -0600713 * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.9beta5
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600714 */
Guy Schalnat6d764711995-12-19 03:22:19 -0600715
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500716void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600717png_read_rows(png_structp png_ptr, png_bytepp row,
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600718 png_bytepp display_row, png_uint_32 num_rows)
Guy Schalnat0d580581995-07-20 02:43:20 -0500719{
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600720 png_uint_32 i;
721 png_bytepp rp;
722 png_bytepp dp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500723
Andreas Dilger47a0c421997-05-16 02:46:07 -0500724 png_debug(1, "in png_read_rows\n");
725 /* save jump buffer and error functions */
Guy Schalnat0f716451995-11-28 11:22:13 -0600726 rp = row;
727 dp = display_row;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500728 if (rp != NULL && dp != NULL)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500729 for (i = 0; i < num_rows; i++)
730 {
731 png_bytep rptr = *rp++;
732 png_bytep dptr = *dp++;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600733
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500734 png_read_row(png_ptr, rptr, dptr);
735 }
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500736 else if(rp != NULL)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500737 for (i = 0; i < num_rows; i++)
738 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500739 png_bytep rptr = *rp;
740 png_read_row(png_ptr, rptr, NULL);
741 rp++;
742 }
743 else if(dp != NULL)
744 for (i = 0; i < num_rows; i++)
745 {
746 png_bytep dptr = *dp;
747 png_read_row(png_ptr, NULL, dptr);
748 dp++;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500749 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500750}
751
Andreas Dilger47a0c421997-05-16 02:46:07 -0500752/* Read the entire image. If the image has an alpha channel or a tRNS
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500753 * chunk, and you have called png_handle_alpha()[*], you will need to
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600754 * initialize the image to the current image that PNG will be overlaying.
755 * We set the num_rows again here, in case it was incorrectly set in
756 * png_read_start_row() by a call to png_read_update_info() or
757 * png_start_read_image() if png_set_interlace_handling() wasn't called
758 * prior to either of these functions like it should have been. You can
759 * only call this function once. If you desire to have an image for
760 * each pass of a interlaced image, use png_read_rows() instead.
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500761 *
Glenn Randers-Pehrson2ad31ae2000-12-15 08:54:42 -0600762 * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.9beta5
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600763 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500764void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600765png_read_image(png_structp png_ptr, png_bytepp image)
Guy Schalnat0d580581995-07-20 02:43:20 -0500766{
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500767 png_uint_32 i,image_height;
Guy Schalnat0d580581995-07-20 02:43:20 -0500768 int pass, j;
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600769 png_bytepp rp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500770
Andreas Dilger47a0c421997-05-16 02:46:07 -0500771 png_debug(1, "in png_read_image\n");
772 /* save jump buffer and error functions */
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500773
774#ifdef PNG_READ_INTERLACING_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -0500775 pass = png_set_interlace_handling(png_ptr);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500776#else
777 if (png_ptr->interlaced)
778 png_error(png_ptr,
779 "Cannot read interlaced image -- interlace handler disabled.");
780 pass = 1;
781#endif
782
Guy Schalnate5a37791996-06-05 15:50:50 -0500783
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500784 image_height=png_ptr->height;
785 png_ptr->num_rows = image_height; /* Make sure this is set correctly */
Guy Schalnate5a37791996-06-05 15:50:50 -0500786
Guy Schalnat0d580581995-07-20 02:43:20 -0500787 for (j = 0; j < pass; j++)
788 {
789 rp = image;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500790 for (i = 0; i < image_height; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500791 {
792 png_read_row(png_ptr, *rp, NULL);
793 rp++;
794 }
795 }
796}
797
Andreas Dilger47a0c421997-05-16 02:46:07 -0500798/* Read the end of the PNG file. Will not read past the end of the
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600799 * file, will verify the end is accurate, and will read any comments
800 * or time information at the end of the file, if info is not NULL.
801 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500802void PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600803png_read_end(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500804{
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600805 png_byte chunk_length[4];
Guy Schalnat0d580581995-07-20 02:43:20 -0500806 png_uint_32 length;
Guy Schalnat0d580581995-07-20 02:43:20 -0500807
Andreas Dilger47a0c421997-05-16 02:46:07 -0500808 png_debug(1, "in png_read_end\n");
809 /* save jump buffer and error functions */
810 png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
Guy Schalnat0d580581995-07-20 02:43:20 -0500811
812 do
813 {
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600814#ifdef PNG_USE_LOCAL_ARRAYS
815 PNG_IHDR;
816 PNG_IDAT;
817 PNG_IEND;
818 PNG_PLTE;
819#if defined(PNG_READ_bKGD_SUPPORTED)
820 PNG_bKGD;
821#endif
822#if defined(PNG_READ_cHRM_SUPPORTED)
823 PNG_cHRM;
824#endif
825#if defined(PNG_READ_gAMA_SUPPORTED)
826 PNG_gAMA;
827#endif
828#if defined(PNG_READ_hIST_SUPPORTED)
829 PNG_hIST;
830#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600831#if defined(PNG_READ_iCCP_SUPPORTED)
832 PNG_iCCP;
833#endif
834#if defined(PNG_READ_iTXt_SUPPORTED)
835 PNG_iTXt;
836#endif
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600837#if defined(PNG_READ_oFFs_SUPPORTED)
838 PNG_oFFs;
839#endif
840#if defined(PNG_READ_pCAL_SUPPORTED)
841 PNG_pCAL;
842#endif
843#if defined(PNG_READ_pHYs_SUPPORTED)
844 PNG_pHYs;
845#endif
846#if defined(PNG_READ_sBIT_SUPPORTED)
847 PNG_sBIT;
848#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600849#if defined(PNG_READ_sCAL_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600850 PNG_sCAL;
851#endif
852#if defined(PNG_READ_sPLT_SUPPORTED)
853 PNG_sPLT;
854#endif
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600855#if defined(PNG_READ_sRGB_SUPPORTED)
856 PNG_sRGB;
857#endif
858#if defined(PNG_READ_tEXt_SUPPORTED)
859 PNG_tEXt;
860#endif
861#if defined(PNG_READ_tIME_SUPPORTED)
862 PNG_tIME;
863#endif
864#if defined(PNG_READ_tRNS_SUPPORTED)
865 PNG_tRNS;
866#endif
867#if defined(PNG_READ_zTXt_SUPPORTED)
868 PNG_zTXt;
869#endif
870#endif /* PNG_GLOBAL_ARRAYS */
871
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600872 png_read_data(png_ptr, chunk_length, 4);
873 length = png_get_uint_32(chunk_length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500874
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600875 png_reset_crc(png_ptr);
876 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
877
Andreas Dilger47a0c421997-05-16 02:46:07 -0500878 png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);
879
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600880 if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
881 png_handle_IHDR(png_ptr, info_ptr, length);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600882 else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
883 png_handle_IEND(png_ptr, info_ptr, length);
884#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
885 else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
886 {
887 if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
888 {
889 if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
890 png_error(png_ptr, "Too many IDAT's found");
891 }
892 else
893 png_ptr->mode |= PNG_AFTER_IDAT;
894 png_handle_unknown(png_ptr, info_ptr, length);
895 if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
896 png_ptr->mode |= PNG_HAVE_PLTE;
897 }
898#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600899 else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Guy Schalnat0d580581995-07-20 02:43:20 -0500900 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500901 /* Zero length IDATs are legal after the last IDAT has been
902 * read, but not after other chunks have been read.
903 */
Guy Schalnate5a37791996-06-05 15:50:50 -0500904 if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
905 png_error(png_ptr, "Too many IDAT's found");
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500906 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500907 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500908 else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
909 png_handle_PLTE(png_ptr, info_ptr, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500910#if defined(PNG_READ_bKGD_SUPPORTED)
911 else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
912 png_handle_bKGD(png_ptr, info_ptr, length);
913#endif
914#if defined(PNG_READ_cHRM_SUPPORTED)
915 else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
916 png_handle_cHRM(png_ptr, info_ptr, length);
917#endif
918#if defined(PNG_READ_gAMA_SUPPORTED)
919 else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
920 png_handle_gAMA(png_ptr, info_ptr, length);
921#endif
922#if defined(PNG_READ_hIST_SUPPORTED)
923 else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
924 png_handle_hIST(png_ptr, info_ptr, length);
925#endif
926#if defined(PNG_READ_oFFs_SUPPORTED)
927 else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
928 png_handle_oFFs(png_ptr, info_ptr, length);
929#endif
930#if defined(PNG_READ_pCAL_SUPPORTED)
931 else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
932 png_handle_pCAL(png_ptr, info_ptr, length);
933#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600934#if defined(PNG_READ_sCAL_SUPPORTED)
935 else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
936 png_handle_sCAL(png_ptr, info_ptr, length);
937#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500938#if defined(PNG_READ_pHYs_SUPPORTED)
939 else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
940 png_handle_pHYs(png_ptr, info_ptr, length);
941#endif
942#if defined(PNG_READ_sBIT_SUPPORTED)
943 else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
944 png_handle_sBIT(png_ptr, info_ptr, length);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500945#endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600946#if defined(PNG_READ_sRGB_SUPPORTED)
947 else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
948 png_handle_sRGB(png_ptr, info_ptr, length);
949#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600950#if defined(PNG_READ_iCCP_SUPPORTED)
951 else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
952 png_handle_iCCP(png_ptr, info_ptr, length);
953#endif
954#if defined(PNG_READ_sPLT_SUPPORTED)
955 else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
956 png_handle_sPLT(png_ptr, info_ptr, length);
957#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500958#if defined(PNG_READ_tEXt_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600959 else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
960 png_handle_tEXt(png_ptr, info_ptr, length);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500961#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500962#if defined(PNG_READ_tIME_SUPPORTED)
963 else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
964 png_handle_tIME(png_ptr, info_ptr, length);
965#endif
966#if defined(PNG_READ_tRNS_SUPPORTED)
967 else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
968 png_handle_tRNS(png_ptr, info_ptr, length);
969#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500970#if defined(PNG_READ_zTXt_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600971 else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
972 png_handle_zTXt(png_ptr, info_ptr, length);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500973#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600974#if defined(PNG_READ_iTXt_SUPPORTED)
975 else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
976 png_handle_iTXt(png_ptr, info_ptr, length);
977#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500978 else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600979 png_handle_unknown(png_ptr, info_ptr, length);
980 } while (!(png_ptr->mode & PNG_HAVE_IEND));
Guy Schalnat0d580581995-07-20 02:43:20 -0500981}
982
983/* free all memory used by the read */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500984void PNGAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500985png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600986 png_infopp end_info_ptr_ptr)
Guy Schalnate5a37791996-06-05 15:50:50 -0500987{
988 png_structp png_ptr = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600989 png_infop info_ptr = NULL, end_info_ptr = NULL;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500990#ifdef PNG_USER_MEM_SUPPORTED
991 png_free_ptr free_fn = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600992#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500993
Andreas Dilger47a0c421997-05-16 02:46:07 -0500994 png_debug(1, "in png_destroy_read_struct\n");
995 /* save jump buffer and error functions */
996 if (png_ptr_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500997 png_ptr = *png_ptr_ptr;
998
Andreas Dilger47a0c421997-05-16 02:46:07 -0500999 if (info_ptr_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -05001000 info_ptr = *info_ptr_ptr;
1001
Andreas Dilger47a0c421997-05-16 02:46:07 -05001002 if (end_info_ptr_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001003 end_info_ptr = *end_info_ptr_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -05001004
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001005#ifdef PNG_USER_MEM_SUPPORTED
1006 free_fn = png_ptr->free_fn;
1007#endif
1008
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001009 png_read_destroy(png_ptr, info_ptr, end_info_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -05001010
Andreas Dilger47a0c421997-05-16 02:46:07 -05001011 if (info_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -05001012 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001013#if defined(PNG_TEXT_SUPPORTED)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001014 png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001015#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001016
1017#ifdef PNG_USER_MEM_SUPPORTED
1018 png_destroy_struct_2((png_voidp)info_ptr, free_fn);
1019#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001020 png_destroy_struct((png_voidp)info_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001021#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001022 *info_ptr_ptr = (png_infop)NULL;
1023 }
1024
Andreas Dilger47a0c421997-05-16 02:46:07 -05001025 if (end_info_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -05001026 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001027#if defined(PNG_READ_TEXT_SUPPORTED)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001028 png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001029#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001030#ifdef PNG_USER_MEM_SUPPORTED
1031 png_destroy_struct_2((png_voidp)end_info_ptr, free_fn);
1032#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001033 png_destroy_struct((png_voidp)end_info_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001034#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001035 *end_info_ptr_ptr = (png_infop)NULL;
Guy Schalnate5a37791996-06-05 15:50:50 -05001036 }
1037
Andreas Dilger47a0c421997-05-16 02:46:07 -05001038 if (png_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -05001039 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001040#ifdef PNG_USER_MEM_SUPPORTED
1041 png_destroy_struct_2((png_voidp)png_ptr, free_fn);
1042#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001043 png_destroy_struct((png_voidp)png_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001044#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001045 *png_ptr_ptr = (png_structp)NULL;
1046 }
1047}
1048
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001049/* free all memory used by the read (old method) */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001050void PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001051png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05001052{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001053#ifdef PNG_SETJMP_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05001054 jmp_buf tmp_jmp;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001055#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001056 png_error_ptr error_fn;
1057 png_error_ptr warning_fn;
1058 png_voidp error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001059#ifdef PNG_USER_MEM_SUPPORTED
1060 png_free_ptr free_fn;
1061#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001062
Andreas Dilger47a0c421997-05-16 02:46:07 -05001063 png_debug(1, "in png_read_destroy\n");
1064 /* save jump buffer and error functions */
1065 if (info_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001066 png_info_destroy(png_ptr, info_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -05001067
Andreas Dilger47a0c421997-05-16 02:46:07 -05001068 if (end_info_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001069 png_info_destroy(png_ptr, end_info_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -05001070
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001071 png_free(png_ptr, png_ptr->zbuf);
1072 png_free(png_ptr, png_ptr->row_buf);
1073 png_free(png_ptr, png_ptr->prev_row);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001074#if defined(PNG_READ_DITHER_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001075 png_free(png_ptr, png_ptr->palette_lookup);
1076 png_free(png_ptr, png_ptr->dither_index);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001077#endif
1078#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001079 png_free(png_ptr, png_ptr->gamma_table);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001080#endif
1081#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001082 png_free(png_ptr, png_ptr->gamma_from_1);
1083 png_free(png_ptr, png_ptr->gamma_to_1);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001084#endif
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001085#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001086 if (png_ptr->free_me & PNG_FREE_PLTE)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -06001087 png_zfree(png_ptr, png_ptr->palette);
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001088 png_ptr->free_me &= ~PNG_FREE_PLTE;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001089#else
1090 if (png_ptr->flags & PNG_FLAG_FREE_PLTE)
1091 png_zfree(png_ptr, png_ptr->palette);
1092 png_ptr->flags &= ~PNG_FLAG_FREE_PLTE;
1093#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001094#if defined(PNG_tRNS_SUPPORTED) || \
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001095 defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001096#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001097 if (png_ptr->free_me & PNG_FREE_TRNS)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001098 png_free(png_ptr, png_ptr->trans);
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001099 png_ptr->free_me &= ~PNG_FREE_TRNS;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001100#else
1101 if (png_ptr->flags & PNG_FLAG_FREE_TRNS)
1102 png_free(png_ptr, png_ptr->trans);
1103 png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;
1104#endif
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001105#endif
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001106#if defined(PNG_READ_hIST_SUPPORTED)
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001107#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001108 if (png_ptr->free_me & PNG_FREE_HIST)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001109 png_free(png_ptr, png_ptr->hist);
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001110 png_ptr->free_me &= ~PNG_FREE_HIST;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001111#else
1112 if (png_ptr->flags & PNG_FLAG_FREE_HIST)
1113 png_free(png_ptr, png_ptr->hist);
1114 png_ptr->flags &= ~PNG_FLAG_FREE_HIST;
1115#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001116#endif
1117#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001118 if (png_ptr->gamma_16_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05001119 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001120 int i;
1121 int istop = (1 << (8 - png_ptr->gamma_shift));
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001122 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001123 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001124 png_free(png_ptr, png_ptr->gamma_16_table[i]);
Guy Schalnat0d580581995-07-20 02:43:20 -05001125 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001126 png_free(png_ptr, png_ptr->gamma_16_table);
Guy Schalnat0d580581995-07-20 02:43:20 -05001127 }
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001128#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001129 if (png_ptr->gamma_16_from_1 != NULL)
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001130 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001131 int i;
1132 int istop = (1 << (8 - png_ptr->gamma_shift));
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001133 for (i = 0; i < istop; i++)
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001134 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001135 png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001136 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001137 png_free(png_ptr, png_ptr->gamma_16_from_1);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001138 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001139 if (png_ptr->gamma_16_to_1 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05001140 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001141 int i;
1142 int istop = (1 << (8 - png_ptr->gamma_shift));
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001143 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001144 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001145 png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
Guy Schalnat0d580581995-07-20 02:43:20 -05001146 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001147 png_free(png_ptr, png_ptr->gamma_16_to_1);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001148 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001149#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001150#endif
1151#if defined(PNG_TIME_RFC1123_SUPPORTED)
1152 png_free(png_ptr, png_ptr->time_buffer);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001153#endif
Guy Schalnat0f716451995-11-28 11:22:13 -06001154
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001155 inflateEnd(&png_ptr->zstream);
Guy Schalnat6d764711995-12-19 03:22:19 -06001156#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001157 png_free(png_ptr, png_ptr->save_buffer);
Guy Schalnat6d764711995-12-19 03:22:19 -06001158#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001159
1160 /* Save the important info out of the png_struct, in case it is
1161 * being used again.
1162 */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001163#ifdef PNG_SETJMP_SUPPORTED
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001164 png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001165#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001166
1167 error_fn = png_ptr->error_fn;
1168 warning_fn = png_ptr->warning_fn;
1169 error_ptr = png_ptr->error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001170#ifdef PNG_USER_MEM_SUPPORTED
1171 free_fn = png_ptr->free_fn;
1172#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001173
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001174 png_memset(png_ptr, 0, sizeof (png_struct));
Guy Schalnate5a37791996-06-05 15:50:50 -05001175
1176 png_ptr->error_fn = error_fn;
1177 png_ptr->warning_fn = warning_fn;
1178 png_ptr->error_ptr = error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001179#ifdef PNG_USER_MEM_SUPPORTED
1180 png_ptr->free_fn = free_fn;
1181#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001182
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001183#ifdef PNG_SETJMP_SUPPORTED
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001184 png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001185#endif
1186
Guy Schalnat0d580581995-07-20 02:43:20 -05001187}
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001188
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001189void PNGAPI
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001190png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
1191{
1192 png_ptr->read_row_fn = read_row_fn;
1193}
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001194
1195#if defined(PNG_INFO_IMAGE_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001196void PNGAPI
1197png_read_png(png_structp png_ptr, png_infop info_ptr,
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001198 int transforms,
1199 voidp params)
1200{
1201 int row;
1202
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001203#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1204 /* invert the alpha channel from opacity to transparency */
1205 if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
1206 png_set_invert_alpha(png_ptr);
1207#endif
1208
1209 /* The call to png_read_info() gives us all of the information from the
1210 * PNG file before the first IDAT (image data chunk).
1211 */
1212 png_read_info(png_ptr, info_ptr);
1213
1214 /* -------------- image transformations start here ------------------- */
1215
1216#if defined(PNG_READ_16_TO_8_SUPPORTED)
1217 /* tell libpng to strip 16 bit/color files down to 8 bits/color */
1218 if (transforms & PNG_TRANSFORM_STRIP_16)
1219 png_set_strip_16(png_ptr);
1220#endif
1221
1222#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1223 /* Strip alpha bytes from the input data without combining with the
1224 * background (not recommended).
1225 */
1226 if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
1227 png_set_strip_alpha(png_ptr);
1228#endif
1229
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001230#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001231 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
1232 * byte into separate bytes (useful for paletted and grayscale images).
1233 */
1234 if (transforms & PNG_TRANSFORM_PACKING)
1235 png_set_packing(png_ptr);
1236#endif
1237
1238#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1239 /* Change the order of packed pixels to least significant bit first
1240 * (not useful if you are using png_set_packing). */
1241 if (transforms & PNG_TRANSFORM_PACKSWAP)
1242 png_set_packswap(png_ptr);
1243#endif
1244
1245#if defined(PNG_READ_EXPAND_SUPPORTED)
1246 /* Expand paletted colors into true RGB triplets
1247 * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
1248 * Expand paletted or RGB images with transparency to full alpha
1249 * channels so the data will be available as RGBA quartets.
1250 */
1251 if (transforms & PNG_TRANSFORM_EXPAND)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001252 if ((png_ptr->bit_depth < 8) ||
1253 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
1254 (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
1255 png_set_expand(png_ptr);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001256#endif
1257
1258 /* We don't handle background color or gamma transformation or dithering. */
1259
1260#if defined(PNG_READ_INVERT_SUPPORTED)
1261 /* invert monochrome files to have 0 as white and 1 as black */
1262 if (transforms & PNG_TRANSFORM_INVERT_MONO)
1263 png_set_invert_mono(png_ptr);
1264#endif
1265
1266#if defined(PNG_READ_SHIFT_SUPPORTED)
1267 /* If you want to shift the pixel values from the range [0,255] or
1268 * [0,65535] to the original [0,7] or [0,31], or whatever range the
1269 * colors were originally in:
1270 */
1271 if ((transforms & PNG_TRANSFORM_SHIFT)
1272 && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
1273 {
1274 png_color_8p sig_bit;
1275
1276 png_get_sBIT(png_ptr, info_ptr, &sig_bit);
1277 png_set_shift(png_ptr, sig_bit);
1278 }
1279#endif
1280
1281#if defined(PNG_READ_BGR_SUPPORTED)
1282 /* flip the RGB pixels to BGR (or RGBA to BGRA) */
1283 if (transforms & PNG_TRANSFORM_BGR)
1284 png_set_bgr(png_ptr);
1285#endif
1286
1287#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1288 /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
1289 if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
1290 png_set_swap_alpha(png_ptr);
1291#endif
1292
1293#if defined(PNG_READ_SWAP_SUPPORTED)
1294 /* swap bytes of 16 bit files to least significant byte first */
1295 if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
1296 png_set_swap(png_ptr);
1297#endif
1298
1299 /* We don't handle adding filler bytes */
1300
1301 /* Optional call to gamma correct and add the background to the palette
1302 * and update info structure. REQUIRED if you are expecting libpng to
1303 * update the palette for you (ie you selected such a transform above).
1304 */
1305 png_read_update_info(png_ptr, info_ptr);
1306
1307 /* -------------- image transformations end here ------------------- */
1308
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001309#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -05001310 png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001311#endif
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001312 if(info_ptr->row_pointers == NULL)
1313 {
1314 info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001315 info_ptr->height * sizeof(png_bytep));
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001316#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001317 info_ptr->free_me |= PNG_FREE_ROWS;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001318#endif
1319 for (row = 0; row < (int)info_ptr->height; row++)
1320 info_ptr->row_pointers[row] = png_malloc(png_ptr,
1321 png_get_rowbytes(png_ptr, info_ptr));
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001322 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001323
1324 png_read_image(png_ptr, info_ptr->row_pointers);
1325 info_ptr->valid |= PNG_INFO_IDAT;
1326
1327 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
1328 png_read_end(png_ptr, info_ptr);
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001329
1330 if(transforms == 0 || params == (voidp)NULL)
1331 /* quiet compiler warnings */ return;
1332
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001333}
1334#endif