blob: 98178bd96fb7e7b48f1dc21be6c40bc82154ae01 [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-Pehrsonf6b4f452000-12-01 09:23:06 -06004 * libpng 1.0.9beta4 - December 1, 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);
Guy Schalnat0d580581995-07-20 02:43:20 -0500649
650 if (png_ptr->transformations)
651 png_do_read_transformations(png_ptr);
652
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500653#if defined(PNG_READ_INTERLACING_SUPPORTED)
Guy Schalnat0d580581995-07-20 02:43:20 -0500654 /* blow up interlaced rows to full size */
655 if (png_ptr->interlaced &&
656 (png_ptr->transformations & PNG_INTERLACE))
657 {
658 if (png_ptr->pass < 6)
659 png_do_read_interlace(&(png_ptr->row_info),
Andreas Dilger47a0c421997-05-16 02:46:07 -0500660 png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
Guy Schalnat0d580581995-07-20 02:43:20 -0500661
Andreas Dilger47a0c421997-05-16 02:46:07 -0500662 if (dsp_row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500663 png_combine_row(png_ptr, dsp_row,
664 png_pass_dsp_mask[png_ptr->pass]);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500665 if (row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500666 png_combine_row(png_ptr, row,
667 png_pass_mask[png_ptr->pass]);
668 }
669 else
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500670#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500671 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500672 if (row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500673 png_combine_row(png_ptr, row, 0xff);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500674 if (dsp_row != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -0500675 png_combine_row(png_ptr, dsp_row, 0xff);
676 }
677 png_read_finish_row(png_ptr);
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -0600678
679 if (png_ptr->read_row_fn != NULL)
680 (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
Guy Schalnat0d580581995-07-20 02:43:20 -0500681}
682
Andreas Dilger47a0c421997-05-16 02:46:07 -0500683/* Read one or more rows of image data. If the image is interlaced,
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600684 * and png_set_interlace_handling() has been called, the rows need to
685 * contain the contents of the rows from the previous pass. If the
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500686 * image has alpha or transparency, and png_handle_alpha()[*] has been
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600687 * called, the rows contents must be initialized to the contents of the
688 * screen.
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600689 *
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600690 * "row" holds the actual image, and pixels are placed in it
691 * as they arrive. If the image is displayed after each pass, it will
692 * appear to "sparkle" in. "display_row" can be used to display a
693 * "chunky" progressive image, with finer detail added as it becomes
694 * available. If you do not want this "chunky" display, you may pass
695 * NULL for display_row. If you do not want the sparkle display, and
696 * you have not called png_handle_alpha(), you may pass NULL for rows.
697 * If you have called png_handle_alpha(), and the image has either an
698 * alpha channel or a transparency chunk, you must provide a buffer for
699 * rows. In this case, you do not have to provide a display_row buffer
700 * also, but you may. If the image is not interlaced, or if you have
701 * not called png_set_interlace_handling(), the display_row buffer will
702 * be ignored, so pass NULL to it.
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500703 *
Glenn Randers-Pehrsonf6b4f452000-12-01 09:23:06 -0600704 * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.9beta4
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600705 */
Guy Schalnat6d764711995-12-19 03:22:19 -0600706
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500707void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600708png_read_rows(png_structp png_ptr, png_bytepp row,
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600709 png_bytepp display_row, png_uint_32 num_rows)
Guy Schalnat0d580581995-07-20 02:43:20 -0500710{
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600711 png_uint_32 i;
712 png_bytepp rp;
713 png_bytepp dp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500714
Andreas Dilger47a0c421997-05-16 02:46:07 -0500715 png_debug(1, "in png_read_rows\n");
716 /* save jump buffer and error functions */
Guy Schalnat0f716451995-11-28 11:22:13 -0600717 rp = row;
718 dp = display_row;
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500719 if (rp != NULL && dp != NULL)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500720 for (i = 0; i < num_rows; i++)
721 {
722 png_bytep rptr = *rp++;
723 png_bytep dptr = *dp++;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600724
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500725 png_read_row(png_ptr, rptr, dptr);
726 }
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500727 else if(rp != NULL)
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500728 for (i = 0; i < num_rows; i++)
729 {
Glenn Randers-Pehrson8686fff1998-05-21 09:27:50 -0500730 png_bytep rptr = *rp;
731 png_read_row(png_ptr, rptr, NULL);
732 rp++;
733 }
734 else if(dp != NULL)
735 for (i = 0; i < num_rows; i++)
736 {
737 png_bytep dptr = *dp;
738 png_read_row(png_ptr, NULL, dptr);
739 dp++;
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -0500740 }
Guy Schalnat0d580581995-07-20 02:43:20 -0500741}
742
Andreas Dilger47a0c421997-05-16 02:46:07 -0500743/* Read the entire image. If the image has an alpha channel or a tRNS
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500744 * chunk, and you have called png_handle_alpha()[*], you will need to
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600745 * initialize the image to the current image that PNG will be overlaying.
746 * We set the num_rows again here, in case it was incorrectly set in
747 * png_read_start_row() by a call to png_read_update_info() or
748 * png_start_read_image() if png_set_interlace_handling() wasn't called
749 * prior to either of these functions like it should have been. You can
750 * only call this function once. If you desire to have an image for
751 * each pass of a interlaced image, use png_read_rows() instead.
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500752 *
Glenn Randers-Pehrsonf6b4f452000-12-01 09:23:06 -0600753 * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.9beta4
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600754 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500755void PNGAPI
Guy Schalnat6d764711995-12-19 03:22:19 -0600756png_read_image(png_structp png_ptr, png_bytepp image)
Guy Schalnat0d580581995-07-20 02:43:20 -0500757{
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500758 png_uint_32 i,image_height;
Guy Schalnat0d580581995-07-20 02:43:20 -0500759 int pass, j;
Guy Schalnat4ee97b01996-01-16 01:51:56 -0600760 png_bytepp rp;
Guy Schalnat0d580581995-07-20 02:43:20 -0500761
Andreas Dilger47a0c421997-05-16 02:46:07 -0500762 png_debug(1, "in png_read_image\n");
763 /* save jump buffer and error functions */
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500764
765#ifdef PNG_READ_INTERLACING_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -0500766 pass = png_set_interlace_handling(png_ptr);
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -0500767#else
768 if (png_ptr->interlaced)
769 png_error(png_ptr,
770 "Cannot read interlaced image -- interlace handler disabled.");
771 pass = 1;
772#endif
773
Guy Schalnate5a37791996-06-05 15:50:50 -0500774
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500775 image_height=png_ptr->height;
776 png_ptr->num_rows = image_height; /* Make sure this is set correctly */
Guy Schalnate5a37791996-06-05 15:50:50 -0500777
Guy Schalnat0d580581995-07-20 02:43:20 -0500778 for (j = 0; j < pass; j++)
779 {
780 rp = image;
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500781 for (i = 0; i < image_height; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -0500782 {
783 png_read_row(png_ptr, *rp, NULL);
784 rp++;
785 }
786 }
787}
788
Andreas Dilger47a0c421997-05-16 02:46:07 -0500789/* Read the end of the PNG file. Will not read past the end of the
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600790 * file, will verify the end is accurate, and will read any comments
791 * or time information at the end of the file, if info is not NULL.
792 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500793void PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600794png_read_end(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -0500795{
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600796 png_byte chunk_length[4];
Guy Schalnat0d580581995-07-20 02:43:20 -0500797 png_uint_32 length;
Guy Schalnat0d580581995-07-20 02:43:20 -0500798
Andreas Dilger47a0c421997-05-16 02:46:07 -0500799 png_debug(1, "in png_read_end\n");
800 /* save jump buffer and error functions */
801 png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
Guy Schalnat0d580581995-07-20 02:43:20 -0500802
803 do
804 {
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600805#ifdef PNG_USE_LOCAL_ARRAYS
806 PNG_IHDR;
807 PNG_IDAT;
808 PNG_IEND;
809 PNG_PLTE;
810#if defined(PNG_READ_bKGD_SUPPORTED)
811 PNG_bKGD;
812#endif
813#if defined(PNG_READ_cHRM_SUPPORTED)
814 PNG_cHRM;
815#endif
816#if defined(PNG_READ_gAMA_SUPPORTED)
817 PNG_gAMA;
818#endif
819#if defined(PNG_READ_hIST_SUPPORTED)
820 PNG_hIST;
821#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600822#if defined(PNG_READ_iCCP_SUPPORTED)
823 PNG_iCCP;
824#endif
825#if defined(PNG_READ_iTXt_SUPPORTED)
826 PNG_iTXt;
827#endif
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600828#if defined(PNG_READ_oFFs_SUPPORTED)
829 PNG_oFFs;
830#endif
831#if defined(PNG_READ_pCAL_SUPPORTED)
832 PNG_pCAL;
833#endif
834#if defined(PNG_READ_pHYs_SUPPORTED)
835 PNG_pHYs;
836#endif
837#if defined(PNG_READ_sBIT_SUPPORTED)
838 PNG_sBIT;
839#endif
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600840#if defined(PNG_READ_sCAL_SUPPORTED)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600841 PNG_sCAL;
842#endif
843#if defined(PNG_READ_sPLT_SUPPORTED)
844 PNG_sPLT;
845#endif
Glenn Randers-Pehrson074af5e1999-11-28 23:32:18 -0600846#if defined(PNG_READ_sRGB_SUPPORTED)
847 PNG_sRGB;
848#endif
849#if defined(PNG_READ_tEXt_SUPPORTED)
850 PNG_tEXt;
851#endif
852#if defined(PNG_READ_tIME_SUPPORTED)
853 PNG_tIME;
854#endif
855#if defined(PNG_READ_tRNS_SUPPORTED)
856 PNG_tRNS;
857#endif
858#if defined(PNG_READ_zTXt_SUPPORTED)
859 PNG_zTXt;
860#endif
861#endif /* PNG_GLOBAL_ARRAYS */
862
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600863 png_read_data(png_ptr, chunk_length, 4);
864 length = png_get_uint_32(chunk_length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500865
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600866 png_reset_crc(png_ptr);
867 png_crc_read(png_ptr, png_ptr->chunk_name, 4);
868
Andreas Dilger47a0c421997-05-16 02:46:07 -0500869 png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);
870
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600871 if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
872 png_handle_IHDR(png_ptr, info_ptr, length);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -0600873 else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
874 png_handle_IEND(png_ptr, info_ptr, length);
875#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
876 else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name))
877 {
878 if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
879 {
880 if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
881 png_error(png_ptr, "Too many IDAT's found");
882 }
883 else
884 png_ptr->mode |= PNG_AFTER_IDAT;
885 png_handle_unknown(png_ptr, info_ptr, length);
886 if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
887 png_ptr->mode |= PNG_HAVE_PLTE;
888 }
889#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600890 else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Guy Schalnat0d580581995-07-20 02:43:20 -0500891 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500892 /* Zero length IDATs are legal after the last IDAT has been
893 * read, but not after other chunks have been read.
894 */
Guy Schalnate5a37791996-06-05 15:50:50 -0500895 if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
896 png_error(png_ptr, "Too many IDAT's found");
Glenn Randers-Pehrson4accabb2000-04-14 14:20:47 -0500897 png_crc_finish(png_ptr, length);
Guy Schalnat0d580581995-07-20 02:43:20 -0500898 }
Andreas Dilger47a0c421997-05-16 02:46:07 -0500899 else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
900 png_handle_PLTE(png_ptr, info_ptr, length);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500901#if defined(PNG_READ_bKGD_SUPPORTED)
902 else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
903 png_handle_bKGD(png_ptr, info_ptr, length);
904#endif
905#if defined(PNG_READ_cHRM_SUPPORTED)
906 else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
907 png_handle_cHRM(png_ptr, info_ptr, length);
908#endif
909#if defined(PNG_READ_gAMA_SUPPORTED)
910 else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
911 png_handle_gAMA(png_ptr, info_ptr, length);
912#endif
913#if defined(PNG_READ_hIST_SUPPORTED)
914 else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
915 png_handle_hIST(png_ptr, info_ptr, length);
916#endif
917#if defined(PNG_READ_oFFs_SUPPORTED)
918 else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
919 png_handle_oFFs(png_ptr, info_ptr, length);
920#endif
921#if defined(PNG_READ_pCAL_SUPPORTED)
922 else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
923 png_handle_pCAL(png_ptr, info_ptr, length);
924#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600925#if defined(PNG_READ_sCAL_SUPPORTED)
926 else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4))
927 png_handle_sCAL(png_ptr, info_ptr, length);
928#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500929#if defined(PNG_READ_pHYs_SUPPORTED)
930 else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
931 png_handle_pHYs(png_ptr, info_ptr, length);
932#endif
933#if defined(PNG_READ_sBIT_SUPPORTED)
934 else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
935 png_handle_sBIT(png_ptr, info_ptr, length);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500936#endif
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600937#if defined(PNG_READ_sRGB_SUPPORTED)
938 else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
939 png_handle_sRGB(png_ptr, info_ptr, length);
940#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600941#if defined(PNG_READ_iCCP_SUPPORTED)
942 else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4))
943 png_handle_iCCP(png_ptr, info_ptr, length);
944#endif
945#if defined(PNG_READ_sPLT_SUPPORTED)
946 else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4))
947 png_handle_sPLT(png_ptr, info_ptr, length);
948#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500949#if defined(PNG_READ_tEXt_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600950 else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
951 png_handle_tEXt(png_ptr, info_ptr, length);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500952#endif
Andreas Dilger47a0c421997-05-16 02:46:07 -0500953#if defined(PNG_READ_tIME_SUPPORTED)
954 else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
955 png_handle_tIME(png_ptr, info_ptr, length);
956#endif
957#if defined(PNG_READ_tRNS_SUPPORTED)
958 else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
959 png_handle_tRNS(png_ptr, info_ptr, length);
960#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500961#if defined(PNG_READ_zTXt_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600962 else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
963 png_handle_zTXt(png_ptr, info_ptr, length);
Guy Schalnat51f0eb41995-09-26 05:22:39 -0500964#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600965#if defined(PNG_READ_iTXt_SUPPORTED)
966 else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4))
967 png_handle_iTXt(png_ptr, info_ptr, length);
968#endif
Guy Schalnat0d580581995-07-20 02:43:20 -0500969 else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600970 png_handle_unknown(png_ptr, info_ptr, length);
971 } while (!(png_ptr->mode & PNG_HAVE_IEND));
Guy Schalnat0d580581995-07-20 02:43:20 -0500972}
973
974/* free all memory used by the read */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500975void PNGAPI
Guy Schalnate5a37791996-06-05 15:50:50 -0500976png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600977 png_infopp end_info_ptr_ptr)
Guy Schalnate5a37791996-06-05 15:50:50 -0500978{
979 png_structp png_ptr = NULL;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600980 png_infop info_ptr = NULL, end_info_ptr = NULL;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500981#ifdef PNG_USER_MEM_SUPPORTED
982 png_free_ptr free_fn = NULL;
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600983#endif
Guy Schalnate5a37791996-06-05 15:50:50 -0500984
Andreas Dilger47a0c421997-05-16 02:46:07 -0500985 png_debug(1, "in png_destroy_read_struct\n");
986 /* save jump buffer and error functions */
987 if (png_ptr_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500988 png_ptr = *png_ptr_ptr;
989
Andreas Dilger47a0c421997-05-16 02:46:07 -0500990 if (info_ptr_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -0500991 info_ptr = *info_ptr_ptr;
992
Andreas Dilger47a0c421997-05-16 02:46:07 -0500993 if (end_info_ptr_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600994 end_info_ptr = *end_info_ptr_ptr;
Guy Schalnate5a37791996-06-05 15:50:50 -0500995
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -0500996#ifdef PNG_USER_MEM_SUPPORTED
997 free_fn = png_ptr->free_fn;
998#endif
999
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001000 png_read_destroy(png_ptr, info_ptr, end_info_ptr);
Guy Schalnate5a37791996-06-05 15:50:50 -05001001
Andreas Dilger47a0c421997-05-16 02:46:07 -05001002 if (info_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -05001003 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001004#if defined(PNG_TEXT_SUPPORTED)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001005 png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001006#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001007
1008#ifdef PNG_USER_MEM_SUPPORTED
1009 png_destroy_struct_2((png_voidp)info_ptr, free_fn);
1010#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001011 png_destroy_struct((png_voidp)info_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001012#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001013 *info_ptr_ptr = (png_infop)NULL;
1014 }
1015
Andreas Dilger47a0c421997-05-16 02:46:07 -05001016 if (end_info_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -05001017 {
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001018#if defined(PNG_READ_TEXT_SUPPORTED)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001019 png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);
Glenn Randers-Pehrsonc4a2ae61998-01-16 22:06:18 -06001020#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001021#ifdef PNG_USER_MEM_SUPPORTED
1022 png_destroy_struct_2((png_voidp)end_info_ptr, free_fn);
1023#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001024 png_destroy_struct((png_voidp)end_info_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001025#endif
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001026 *end_info_ptr_ptr = (png_infop)NULL;
Guy Schalnate5a37791996-06-05 15:50:50 -05001027 }
1028
Andreas Dilger47a0c421997-05-16 02:46:07 -05001029 if (png_ptr != NULL)
Guy Schalnate5a37791996-06-05 15:50:50 -05001030 {
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001031#ifdef PNG_USER_MEM_SUPPORTED
1032 png_destroy_struct_2((png_voidp)png_ptr, free_fn);
1033#else
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001034 png_destroy_struct((png_voidp)png_ptr);
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001035#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001036 *png_ptr_ptr = (png_structp)NULL;
1037 }
1038}
1039
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001040/* free all memory used by the read (old method) */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001041void PNGAPI
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001042png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)
Guy Schalnat0d580581995-07-20 02:43:20 -05001043{
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001044#ifdef PNG_SETJMP_SUPPORTED
Guy Schalnat0d580581995-07-20 02:43:20 -05001045 jmp_buf tmp_jmp;
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001046#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001047 png_error_ptr error_fn;
1048 png_error_ptr warning_fn;
1049 png_voidp error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001050#ifdef PNG_USER_MEM_SUPPORTED
1051 png_free_ptr free_fn;
1052#endif
Guy Schalnat0d580581995-07-20 02:43:20 -05001053
Andreas Dilger47a0c421997-05-16 02:46:07 -05001054 png_debug(1, "in png_read_destroy\n");
1055 /* save jump buffer and error functions */
1056 if (info_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001057 png_info_destroy(png_ptr, info_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -05001058
Andreas Dilger47a0c421997-05-16 02:46:07 -05001059 if (end_info_ptr != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001060 png_info_destroy(png_ptr, end_info_ptr);
Guy Schalnat0d580581995-07-20 02:43:20 -05001061
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001062 png_free(png_ptr, png_ptr->zbuf);
1063 png_free(png_ptr, png_ptr->row_buf);
1064 png_free(png_ptr, png_ptr->prev_row);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001065#if defined(PNG_READ_DITHER_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001066 png_free(png_ptr, png_ptr->palette_lookup);
1067 png_free(png_ptr, png_ptr->dither_index);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001068#endif
1069#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001070 png_free(png_ptr, png_ptr->gamma_table);
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001071#endif
1072#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001073 png_free(png_ptr, png_ptr->gamma_from_1);
1074 png_free(png_ptr, png_ptr->gamma_to_1);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001075#endif
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001076#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001077 if (png_ptr->free_me & PNG_FREE_PLTE)
Glenn Randers-Pehrson46f61e21998-01-30 21:45:12 -06001078 png_zfree(png_ptr, png_ptr->palette);
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001079 png_ptr->free_me &= ~PNG_FREE_PLTE;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001080#else
1081 if (png_ptr->flags & PNG_FLAG_FREE_PLTE)
1082 png_zfree(png_ptr, png_ptr->palette);
1083 png_ptr->flags &= ~PNG_FLAG_FREE_PLTE;
1084#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001085#if defined(PNG_tRNS_SUPPORTED) || \
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001086 defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001087#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001088 if (png_ptr->free_me & PNG_FREE_TRNS)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001089 png_free(png_ptr, png_ptr->trans);
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001090 png_ptr->free_me &= ~PNG_FREE_TRNS;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001091#else
1092 if (png_ptr->flags & PNG_FLAG_FREE_TRNS)
1093 png_free(png_ptr, png_ptr->trans);
1094 png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;
1095#endif
Glenn Randers-Pehrson4393a9a1999-09-17 12:27:26 -05001096#endif
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001097#if defined(PNG_READ_hIST_SUPPORTED)
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001098#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001099 if (png_ptr->free_me & PNG_FREE_HIST)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001100 png_free(png_ptr, png_ptr->hist);
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001101 png_ptr->free_me &= ~PNG_FREE_HIST;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001102#else
1103 if (png_ptr->flags & PNG_FLAG_FREE_HIST)
1104 png_free(png_ptr, png_ptr->hist);
1105 png_ptr->flags &= ~PNG_FLAG_FREE_HIST;
1106#endif
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001107#endif
1108#if defined(PNG_READ_GAMMA_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001109 if (png_ptr->gamma_16_table != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05001110 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001111 int i;
1112 int istop = (1 << (8 - png_ptr->gamma_shift));
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001113 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001114 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001115 png_free(png_ptr, png_ptr->gamma_16_table[i]);
Guy Schalnat0d580581995-07-20 02:43:20 -05001116 }
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001117 png_free(png_ptr, png_ptr->gamma_16_table);
Guy Schalnat0d580581995-07-20 02:43:20 -05001118 }
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001119#if defined(PNG_READ_BACKGROUND_SUPPORTED)
Andreas Dilger47a0c421997-05-16 02:46:07 -05001120 if (png_ptr->gamma_16_from_1 != NULL)
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001121 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001122 int i;
1123 int istop = (1 << (8 - png_ptr->gamma_shift));
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001124 for (i = 0; i < istop; i++)
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001125 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001126 png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001127 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001128 png_free(png_ptr, png_ptr->gamma_16_from_1);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001129 }
Andreas Dilger47a0c421997-05-16 02:46:07 -05001130 if (png_ptr->gamma_16_to_1 != NULL)
Guy Schalnat0d580581995-07-20 02:43:20 -05001131 {
Glenn Randers-Pehrson1d963611998-05-02 12:52:25 -05001132 int i;
1133 int istop = (1 << (8 - png_ptr->gamma_shift));
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -05001134 for (i = 0; i < istop; i++)
Guy Schalnat0d580581995-07-20 02:43:20 -05001135 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001136 png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
Guy Schalnat0d580581995-07-20 02:43:20 -05001137 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001138 png_free(png_ptr, png_ptr->gamma_16_to_1);
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001139 }
Guy Schalnat51f0eb41995-09-26 05:22:39 -05001140#endif
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001141#endif
1142#if defined(PNG_TIME_RFC1123_SUPPORTED)
1143 png_free(png_ptr, png_ptr->time_buffer);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001144#endif
Guy Schalnat0f716451995-11-28 11:22:13 -06001145
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001146 inflateEnd(&png_ptr->zstream);
Guy Schalnat6d764711995-12-19 03:22:19 -06001147#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001148 png_free(png_ptr, png_ptr->save_buffer);
Guy Schalnat6d764711995-12-19 03:22:19 -06001149#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001150
1151 /* Save the important info out of the png_struct, in case it is
1152 * being used again.
1153 */
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001154#ifdef PNG_SETJMP_SUPPORTED
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001155 png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001156#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001157
1158 error_fn = png_ptr->error_fn;
1159 warning_fn = png_ptr->warning_fn;
1160 error_ptr = png_ptr->error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001161#ifdef PNG_USER_MEM_SUPPORTED
1162 free_fn = png_ptr->free_fn;
1163#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001164
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001165 png_memset(png_ptr, 0, sizeof (png_struct));
Guy Schalnate5a37791996-06-05 15:50:50 -05001166
1167 png_ptr->error_fn = error_fn;
1168 png_ptr->warning_fn = warning_fn;
1169 png_ptr->error_ptr = error_ptr;
Glenn Randers-Pehrsonf7d1a171998-06-06 15:31:35 -05001170#ifdef PNG_USER_MEM_SUPPORTED
1171 png_ptr->free_fn = free_fn;
1172#endif
Guy Schalnate5a37791996-06-05 15:50:50 -05001173
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001174#ifdef PNG_SETJMP_SUPPORTED
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001175 png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001176#endif
1177
Guy Schalnat0d580581995-07-20 02:43:20 -05001178}
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001179
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001180void PNGAPI
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001181png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
1182{
1183 png_ptr->read_row_fn = read_row_fn;
1184}
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001185
1186#if defined(PNG_INFO_IMAGE_SUPPORTED)
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001187void PNGAPI
1188png_read_png(png_structp png_ptr, png_infop info_ptr,
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001189 int transforms,
1190 voidp params)
1191{
1192 int row;
1193
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001194#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1195 /* invert the alpha channel from opacity to transparency */
1196 if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
1197 png_set_invert_alpha(png_ptr);
1198#endif
1199
1200 /* The call to png_read_info() gives us all of the information from the
1201 * PNG file before the first IDAT (image data chunk).
1202 */
1203 png_read_info(png_ptr, info_ptr);
1204
1205 /* -------------- image transformations start here ------------------- */
1206
1207#if defined(PNG_READ_16_TO_8_SUPPORTED)
1208 /* tell libpng to strip 16 bit/color files down to 8 bits/color */
1209 if (transforms & PNG_TRANSFORM_STRIP_16)
1210 png_set_strip_16(png_ptr);
1211#endif
1212
1213#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1214 /* Strip alpha bytes from the input data without combining with the
1215 * background (not recommended).
1216 */
1217 if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
1218 png_set_strip_alpha(png_ptr);
1219#endif
1220
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001221#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001222 /* Extract multiple pixels with bit depths of 1, 2, and 4 from a single
1223 * byte into separate bytes (useful for paletted and grayscale images).
1224 */
1225 if (transforms & PNG_TRANSFORM_PACKING)
1226 png_set_packing(png_ptr);
1227#endif
1228
1229#if defined(PNG_READ_PACKSWAP_SUPPORTED)
1230 /* Change the order of packed pixels to least significant bit first
1231 * (not useful if you are using png_set_packing). */
1232 if (transforms & PNG_TRANSFORM_PACKSWAP)
1233 png_set_packswap(png_ptr);
1234#endif
1235
1236#if defined(PNG_READ_EXPAND_SUPPORTED)
1237 /* Expand paletted colors into true RGB triplets
1238 * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
1239 * Expand paletted or RGB images with transparency to full alpha
1240 * channels so the data will be available as RGBA quartets.
1241 */
1242 if (transforms & PNG_TRANSFORM_EXPAND)
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001243 if ((png_ptr->bit_depth < 8) ||
1244 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
1245 (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
1246 png_set_expand(png_ptr);
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001247#endif
1248
1249 /* We don't handle background color or gamma transformation or dithering. */
1250
1251#if defined(PNG_READ_INVERT_SUPPORTED)
1252 /* invert monochrome files to have 0 as white and 1 as black */
1253 if (transforms & PNG_TRANSFORM_INVERT_MONO)
1254 png_set_invert_mono(png_ptr);
1255#endif
1256
1257#if defined(PNG_READ_SHIFT_SUPPORTED)
1258 /* If you want to shift the pixel values from the range [0,255] or
1259 * [0,65535] to the original [0,7] or [0,31], or whatever range the
1260 * colors were originally in:
1261 */
1262 if ((transforms & PNG_TRANSFORM_SHIFT)
1263 && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
1264 {
1265 png_color_8p sig_bit;
1266
1267 png_get_sBIT(png_ptr, info_ptr, &sig_bit);
1268 png_set_shift(png_ptr, sig_bit);
1269 }
1270#endif
1271
1272#if defined(PNG_READ_BGR_SUPPORTED)
1273 /* flip the RGB pixels to BGR (or RGBA to BGRA) */
1274 if (transforms & PNG_TRANSFORM_BGR)
1275 png_set_bgr(png_ptr);
1276#endif
1277
1278#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1279 /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
1280 if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
1281 png_set_swap_alpha(png_ptr);
1282#endif
1283
1284#if defined(PNG_READ_SWAP_SUPPORTED)
1285 /* swap bytes of 16 bit files to least significant byte first */
1286 if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
1287 png_set_swap(png_ptr);
1288#endif
1289
1290 /* We don't handle adding filler bytes */
1291
1292 /* Optional call to gamma correct and add the background to the palette
1293 * and update info structure. REQUIRED if you are expecting libpng to
1294 * update the palette for you (ie you selected such a transform above).
1295 */
1296 png_read_update_info(png_ptr, info_ptr);
1297
1298 /* -------------- image transformations end here ------------------- */
1299
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001300#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrson1ef65b62000-05-12 06:19:53 -05001301 png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001302#endif
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001303 if(info_ptr->row_pointers == NULL)
1304 {
1305 info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001306 info_ptr->height * sizeof(png_bytep));
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001307#ifdef PNG_FREE_ME_SUPPORTED
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001308 info_ptr->free_me |= PNG_FREE_ROWS;
Glenn Randers-Pehrson6942d532000-05-01 09:31:54 -05001309#endif
1310 for (row = 0; row < (int)info_ptr->height; row++)
1311 info_ptr->row_pointers[row] = png_malloc(png_ptr,
1312 png_get_rowbytes(png_ptr, info_ptr));
Glenn Randers-Pehrsona77ef622000-02-18 13:48:52 -06001313 }
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001314
1315 png_read_image(png_ptr, info_ptr->row_pointers);
1316 info_ptr->valid |= PNG_INFO_IDAT;
1317
1318 /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
1319 png_read_end(png_ptr, info_ptr);
Glenn Randers-Pehrson520a7642000-03-21 05:13:06 -06001320
1321 if(transforms == 0 || params == (voidp)NULL)
1322 /* quiet compiler warnings */ return;
1323
Glenn Randers-Pehrson61c32d92000-02-04 23:40:16 -06001324}
1325#endif