blob: 284b749aa980486682ce3ba8c1dff482c0efbe42 [file] [log] [blame]
Guy Schalnat6d764711995-12-19 03:22:19 -06001
2/* pngpread.c - read a png file in push mode
3
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06004 libpng 1.0 beta 4 - version 0.90
Guy Schalnat6d764711995-12-19 03:22:19 -06005 For conditions of distribution and use, see copyright notice in png.h
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06006 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06007 January 10, 1997
Guy Schalnat6d764711995-12-19 03:22:19 -06008 */
9
10#define PNG_INTERNAL
11#include "png.h"
12
Guy Schalnat4ee97b01996-01-16 01:51:56 -060013#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
14
Guy Schalnat6d764711995-12-19 03:22:19 -060015void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060016png_process_data(png_structp png_ptr, png_infop info_ptr,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060017 png_bytep buffer, png_uint_32 buffer_size)
Guy Schalnat6d764711995-12-19 03:22:19 -060018{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060019 png_push_restore_buffer(png_ptr, buffer, buffer_size);
Guy Schalnat6d764711995-12-19 03:22:19 -060020
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060021 while (png_ptr->buffer_size)
22 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060023 png_process_some_data(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060024 }
Guy Schalnat6d764711995-12-19 03:22:19 -060025}
26
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060027/* What we do with the incoming data depends on what we were previously
28 * doing before we ran out of data...
29 */
Guy Schalnat6d764711995-12-19 03:22:19 -060030void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060031png_process_some_data(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -060032{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060033 switch (png_ptr->process_mode)
34 {
35 case PNG_READ_SIG_MODE:
36 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060037 png_push_read_sig(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060038 break;
39 }
40 case PNG_READ_CHUNK_MODE:
41 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060042 png_push_read_chunk(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060043 break;
44 }
45 case PNG_READ_IDAT_MODE:
46 {
Guy Schalnate5a37791996-06-05 15:50:50 -050047 png_push_read_IDAT(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060048 break;
49 }
Guy Schalnat6d764711995-12-19 03:22:19 -060050#if defined(PNG_READ_tEXt_SUPPORTED)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060051 case PNG_READ_tEXt_MODE:
52 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060053 png_push_read_tEXt(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060054 break;
55 }
Guy Schalnat6d764711995-12-19 03:22:19 -060056#endif
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060057#if defined(PNG_READ_zTXt_SUPPORTED)
58 case PNG_READ_zTXt_MODE:
59 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060060 png_push_read_zTXt(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060061 break;
62 }
63#endif
64 case PNG_READ_END_MODE:
65 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060066 png_push_read_chunk(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060067 break;
68 }
69 case PNG_SKIP_MODE:
70 {
71 png_push_skip(png_ptr);
72 break;
73 }
74 default:
75 {
76 png_ptr->buffer_size = 0;
77 break;
78 }
79 }
Guy Schalnat6d764711995-12-19 03:22:19 -060080}
81
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060082/* Read any remaining signature bytes from the stream and compare them with
83 * the correct PNG signature. It is possible that this routine is called
84 * with bytes already read from the signature, whether because they have been
85 * checked by the calling application, or from multiple calls to this routine.
86 */
Guy Schalnat6d764711995-12-19 03:22:19 -060087void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060088png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -060089{
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060090 int num_checked = png_ptr->sig_bytes,
91 num_to_check = 8 - num_checked;
Guy Schalnat6d764711995-12-19 03:22:19 -060092
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060093 if (png_ptr->buffer_size < num_to_check)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060094 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060095 num_to_check = png_ptr->buffer_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060096 }
Guy Schalnat6d764711995-12-19 03:22:19 -060097
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060098 png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
99 (png_uint_32)num_to_check);
100 png_ptr->sig_bytes += num_to_check;
Guy Schalnat6d764711995-12-19 03:22:19 -0600101
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600102 if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600103 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600104 if (num_checked < 4 &&
105 png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
106 png_error(png_ptr, "Not a PNG file");
107 else
108 png_error(png_ptr, "PNG file corrupted by ASCII conversion");
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600109 }
110 else
111 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600112 if (png_ptr->sig_bytes >= 8)
113 {
114 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
115 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600116 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600117}
118
119void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600120png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600121{
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600122 /* First we make sure we have enough data for the 4 byte chunk name
123 and the 4 byte chunk length before proceeding with decoding the
124 chunk data. To fully decode each of these chunks, we also make
125 sure we have enough data in the buffer for the 4 byte CRC at the
126 end of every chunk (except IDAT, which is handled separately). */
Guy Schalnate5a37791996-06-05 15:50:50 -0500127 if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600128 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600129 png_byte chunk_length[4];
Guy Schalnat6d764711995-12-19 03:22:19 -0600130
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600131 if (png_ptr->buffer_size < 8)
132 {
133 png_push_save_buffer(png_ptr);
134 return;
135 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600136
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600137 png_push_fill_buffer(png_ptr, chunk_length, 4);
138 png_ptr->push_length = png_get_uint_32(chunk_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600139 png_reset_crc(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600140 png_push_fill_buffer(png_ptr, png_ptr->chunk_name, 4);
141 png_calculate_crc(png_ptr, png_ptr->chunk_name, 4);
142 png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600143 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600144
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600145 if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600146 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600147 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
148 {
149 png_push_save_buffer(png_ptr);
150 return;
151 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600152
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600153 png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600154 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600155 else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600156 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600157 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600158 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600159 png_push_save_buffer(png_ptr);
160 return;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600161 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600162
163 png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600164 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600165 else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600166 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600167 /* If we reach an IDAT chunk, this means we have read all of the
168 header chunks, and we can start reading the image (or if this
169 is called after the image has been read - we have an error). */
170 if (png_ptr->mode & PNG_HAVE_IDAT)
171 {
172 if (png_ptr->push_length == 0)
173 return;
174
175 if (png_ptr->mode & PNG_AFTER_IDAT)
176 png_error(png_ptr, "Too many IDAT's found");
177 }
178
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600179 png_ptr->idat_size = png_ptr->push_length;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600180 png_ptr->mode |= PNG_HAVE_IDAT;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600181 png_ptr->process_mode = PNG_READ_IDAT_MODE;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600182 png_push_have_info(png_ptr, info_ptr);
183 png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
184 png_ptr->zstream.next_out = png_ptr->row_buf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600185 return;
186 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600187 else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600188 {
189 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
190 {
191 png_push_save_buffer(png_ptr);
192 return;
193 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600194
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600195 png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
196 png_ptr->process_mode = PNG_READ_DONE_MODE;
197 png_push_have_end(png_ptr, info_ptr);
198 }
199#if defined(PNG_READ_gAMA_SUPPORTED)
200 else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
201 {
202 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
203 {
204 png_push_save_buffer(png_ptr);
205 return;
206 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600207
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600208 png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600209 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600210#endif
211#if defined(PNG_READ_sBIT_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600212 else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600213 {
214 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
215 {
216 png_push_save_buffer(png_ptr);
217 return;
218 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600219
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600220 png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600221 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600222#endif
223#if defined(PNG_READ_cHRM_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600224 else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600225 {
226 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
227 {
228 png_push_save_buffer(png_ptr);
229 return;
230 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600231
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600232 png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600233 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600234#endif
235#if defined(PNG_READ_tRNS_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600236 else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600237 {
238 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
239 {
240 png_push_save_buffer(png_ptr);
241 return;
242 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600243
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600244 png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600245 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600246#endif
247#if defined(PNG_READ_bKGD_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600248 else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600249 {
250 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
251 {
252 png_push_save_buffer(png_ptr);
253 return;
254 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600255
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600256 png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600257 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600258#endif
259#if defined(PNG_READ_hIST_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600260 else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600261 {
262 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
263 {
264 png_push_save_buffer(png_ptr);
265 return;
266 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600267
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600268 png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600269 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600270#endif
271#if defined(PNG_READ_pHYs_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600272 else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600273 {
274 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
275 {
276 png_push_save_buffer(png_ptr);
277 return;
278 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600279
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600280 png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600281 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600282#endif
283#if defined(PNG_READ_oFFs_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600284 else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600285 {
286 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
287 {
288 png_push_save_buffer(png_ptr);
289 return;
290 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600291
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600292 png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600293 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600294#endif
295#if defined(PNG_READ_tIME_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600296 else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600297 {
298 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
299 {
300 png_push_save_buffer(png_ptr);
301 return;
302 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600303
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600304 png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600305 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600306#endif
307#if defined(PNG_READ_tEXt_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600308 else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600309 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600310 png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600311 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600312#endif
313#if defined(PNG_READ_zTXt_SUPPORTED)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600314 else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600315 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600316 png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600317 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600318#endif
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600319 else
320 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600321 png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600322 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600323
Guy Schalnate5a37791996-06-05 15:50:50 -0500324 png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
Guy Schalnat6d764711995-12-19 03:22:19 -0600325}
326
327void
Guy Schalnat6d764711995-12-19 03:22:19 -0600328png_push_crc_skip(png_structp png_ptr, png_uint_32 length)
329{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600330 png_ptr->process_mode = PNG_SKIP_MODE;
331 png_ptr->skip_length = length;
Guy Schalnat6d764711995-12-19 03:22:19 -0600332}
333
334void
335png_push_skip(png_structp png_ptr)
336{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600337 if (png_ptr->skip_length && png_ptr->save_buffer_size)
338 {
339 png_uint_32 save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600340
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600341 if (png_ptr->skip_length < png_ptr->save_buffer_size)
342 save_size = png_ptr->skip_length;
343 else
344 save_size = png_ptr->save_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600345
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600346 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600347
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600348 png_ptr->skip_length -= save_size;
349 png_ptr->buffer_size -= save_size;
350 png_ptr->save_buffer_size -= save_size;
351 png_ptr->save_buffer_ptr += (png_size_t)save_size;
352 }
353 if (png_ptr->skip_length && png_ptr->current_buffer_size)
354 {
355 png_uint_32 save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600356
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600357 if (png_ptr->skip_length < png_ptr->current_buffer_size)
358 save_size = png_ptr->skip_length;
359 else
360 save_size = png_ptr->current_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600361
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600362 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600363
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600364 png_ptr->skip_length -= save_size;
365 png_ptr->buffer_size -= save_size;
366 png_ptr->current_buffer_size -= save_size;
367 png_ptr->current_buffer_ptr += (png_size_t)save_size;
368 }
369 if (!png_ptr->skip_length)
370 {
371 if (png_ptr->buffer_size < 4)
372 {
373 png_push_save_buffer(png_ptr);
374 return;
375 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600376
377 png_crc_finish(png_ptr, 0);
378
379 if (png_ptr->mode & PNG_AFTER_IDAT)
380 png_ptr->process_mode = PNG_READ_END_MODE;
381 else
382 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600383 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600384}
385
386void
387png_push_fill_buffer(png_structp png_ptr, png_bytep buffer,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600388 png_uint_32 length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600389{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600390 png_bytep ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -0600391
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600392 ptr = buffer;
393 if (png_ptr->save_buffer_size)
394 {
395 png_uint_32 save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600396
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600397 if (length < png_ptr->save_buffer_size)
398 save_size = length;
399 else
400 save_size = png_ptr->save_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600401
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600402 png_memcpy(ptr, png_ptr->save_buffer_ptr, (png_size_t)save_size);
403 length -= save_size;
404 ptr += (png_size_t)save_size;
405 png_ptr->buffer_size -= save_size;
406 png_ptr->save_buffer_size -= save_size;
407 png_ptr->save_buffer_ptr += (png_size_t)save_size;
408 }
409 if (length && png_ptr->current_buffer_size)
410 {
411 png_uint_32 save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600412
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600413 if (length < png_ptr->current_buffer_size)
414 save_size = length;
415 else
416 save_size = png_ptr->current_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600417
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600418 png_memcpy(ptr, png_ptr->current_buffer_ptr, (png_size_t)save_size);
419 png_ptr->buffer_size -= save_size;
420 png_ptr->current_buffer_size -= save_size;
421 png_ptr->current_buffer_ptr += (png_size_t)save_size;
422 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600423}
424
425void
426png_push_save_buffer(png_structp png_ptr)
427{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600428 if (png_ptr->save_buffer_size)
429 {
430 if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
431 {
432 int i;
433 png_bytep sp;
434 png_bytep dp;
Guy Schalnat6d764711995-12-19 03:22:19 -0600435
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600436 for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
437 i < png_ptr->save_buffer_size;
438 i++, sp++, dp++)
439 {
440 *dp = *sp;
441 }
442 }
443 }
444 if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
445 png_ptr->save_buffer_max)
446 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600447 png_uint_32 new_max;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600448 png_bytep old_buffer;
Guy Schalnat6d764711995-12-19 03:22:19 -0600449
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600450 new_max = (int)(png_ptr->save_buffer_size +
451 png_ptr->current_buffer_size + 256);
452 old_buffer = png_ptr->save_buffer;
453 png_ptr->save_buffer = (png_bytep)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600454 png_malloc(png_ptr, new_max);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600455 png_memcpy(png_ptr->save_buffer, old_buffer,
456 (png_size_t)png_ptr->save_buffer_size);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600457 png_free(png_ptr, old_buffer);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600458 png_ptr->save_buffer_max = new_max;
459 }
460 if (png_ptr->current_buffer_size)
461 {
462 png_memcpy(png_ptr->save_buffer +
463 (png_size_t)png_ptr->save_buffer_size,
464 png_ptr->current_buffer_ptr,
465 (png_size_t)png_ptr->current_buffer_size);
466 png_ptr->save_buffer_size += png_ptr->current_buffer_size;
467 png_ptr->current_buffer_size = 0;
468 }
469 png_ptr->save_buffer_ptr = png_ptr->save_buffer;
470 png_ptr->buffer_size = 0;
Guy Schalnat6d764711995-12-19 03:22:19 -0600471}
472
473void
474png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600475 png_uint_32 buffer_length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600476{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600477 png_ptr->current_buffer = buffer;
478 png_ptr->current_buffer_size = buffer_length;
479 png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
480 png_ptr->current_buffer_ptr = png_ptr->current_buffer;
Guy Schalnat6d764711995-12-19 03:22:19 -0600481}
482
483void
Guy Schalnate5a37791996-06-05 15:50:50 -0500484png_push_read_IDAT(png_structp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600485{
Guy Schalnate5a37791996-06-05 15:50:50 -0500486 if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600487 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600488 png_byte chunk_length[4];
Guy Schalnat6d764711995-12-19 03:22:19 -0600489
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600490 if (png_ptr->buffer_size < 8)
491 {
492 png_push_save_buffer(png_ptr);
493 return;
494 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600495
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600496 png_push_fill_buffer(png_ptr, chunk_length, 4);
497 png_ptr->push_length = png_get_uint_32(chunk_length);
498
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600499 png_reset_crc(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600500 png_push_fill_buffer(png_ptr, png_ptr->chunk_name, 4);
501 png_calculate_crc(png_ptr, chunk_length, 4);
502 png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
503
504 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600505 {
506 png_ptr->process_mode = PNG_READ_END_MODE;
Guy Schalnate5a37791996-06-05 15:50:50 -0500507 if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600508 png_error(png_ptr, "Not enough compressed data");
509 return;
510 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600511
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600512 png_ptr->idat_size = png_ptr->push_length;
513 }
514 if (png_ptr->idat_size && png_ptr->save_buffer_size)
515 {
516 png_uint_32 save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600517
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600518 if (png_ptr->idat_size < png_ptr->save_buffer_size)
519 save_size = png_ptr->idat_size;
520 else
521 save_size = png_ptr->save_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600522
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600523 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
524 png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600525
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600526 png_ptr->idat_size -= save_size;
527 png_ptr->buffer_size -= save_size;
528 png_ptr->save_buffer_size -= save_size;
529 png_ptr->save_buffer_ptr += (png_size_t)save_size;
530 }
531 if (png_ptr->idat_size && png_ptr->current_buffer_size)
532 {
533 png_uint_32 save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600534
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600535 if (png_ptr->idat_size < png_ptr->current_buffer_size)
536 save_size = png_ptr->idat_size;
537 else
538 save_size = png_ptr->current_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600539
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600540 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
541 png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600542
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600543 png_ptr->idat_size -= save_size;
544 png_ptr->buffer_size -= save_size;
545 png_ptr->current_buffer_size -= save_size;
546 png_ptr->current_buffer_ptr += (png_size_t)save_size;
547 }
548 if (!png_ptr->idat_size)
549 {
550 if (png_ptr->buffer_size < 4)
551 {
552 png_push_save_buffer(png_ptr);
553 return;
554 }
555
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600556 png_crc_finish(png_ptr, 0);
Guy Schalnate5a37791996-06-05 15:50:50 -0500557 png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600558 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600559}
560
561void
562png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600563 png_uint_32 buffer_length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600564{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600565 int ret;
Guy Schalnat6d764711995-12-19 03:22:19 -0600566
Guy Schalnate5a37791996-06-05 15:50:50 -0500567 if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600568 png_error(png_ptr, "Extra compression data");
Guy Schalnat6d764711995-12-19 03:22:19 -0600569
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600570 png_ptr->zstream.next_in = buffer;
571 png_ptr->zstream.avail_in = (uInt)buffer_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600572 do
573 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600574 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600575 if (ret == Z_STREAM_END)
576 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600577 if (png_ptr->zstream.avail_in)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600578 png_error(png_ptr, "Extra compressed data");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600579 if (!png_ptr->zstream.avail_out)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600580 {
581 png_push_process_row(png_ptr);
582 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600583 png_ptr->mode = PNG_AFTER_IDAT;
Guy Schalnate5a37791996-06-05 15:50:50 -0500584 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600585 break;
586 }
587 if (ret != Z_OK)
Guy Schalnate5a37791996-06-05 15:50:50 -0500588 png_error(png_ptr, "Decompression Error");
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600589 if (!(png_ptr->zstream.avail_out))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600590 {
591 png_push_process_row(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600592 png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
593 png_ptr->zstream.next_out = png_ptr->row_buf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600594 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600595
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600596 } while (png_ptr->zstream.avail_in);
Guy Schalnat6d764711995-12-19 03:22:19 -0600597}
598
599void
600png_push_process_row(png_structp png_ptr)
601{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600602 png_ptr->row_info.color_type = png_ptr->color_type;
Guy Schalnat6d764711995-12-19 03:22:19 -0600603 png_ptr->row_info.width = png_ptr->iwidth;
604 png_ptr->row_info.channels = png_ptr->channels;
605 png_ptr->row_info.bit_depth = png_ptr->bit_depth;
606 png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
607 png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
608 (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
609
Guy Schalnate5a37791996-06-05 15:50:50 -0500610 png_read_filter_row(png_ptr, &(png_ptr->row_info),
611 png_ptr->row_buf + 1, png_ptr->prev_row + 1,
612 (int)(png_ptr->row_buf[0]));
Guy Schalnat6d764711995-12-19 03:22:19 -0600613
614 png_memcpy(png_ptr->prev_row, png_ptr->row_buf, (png_size_t)png_ptr->rowbytes + 1);
615
616 if (png_ptr->transformations)
617 png_do_read_transformations(png_ptr);
618
619#if defined(PNG_READ_INTERLACING_SUPPORTED)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600620 /* blow up interlaced rows to full size */
621 if (png_ptr->interlaced &&
622 (png_ptr->transformations & PNG_INTERLACE))
623 {
624 if (png_ptr->pass < 6)
625 png_do_read_interlace(&(png_ptr->row_info),
626 png_ptr->row_buf + 1, png_ptr->pass);
Guy Schalnat6d764711995-12-19 03:22:19 -0600627
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600628 switch (png_ptr->pass)
629 {
630 case 0:
631 {
632 int i;
633 for (i = 0; i < 8 && png_ptr->pass == 0; i++)
634 {
635 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
636 png_read_push_finish_row(png_ptr);
637 }
638 break;
639 }
640 case 1:
641 {
642 int i;
643 for (i = 0; i < 8 && png_ptr->pass == 1; i++)
644 {
645 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
646 png_read_push_finish_row(png_ptr);
647 }
648 if (png_ptr->pass == 2)
649 {
650 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
651 {
652 png_push_have_row(png_ptr, NULL);
653 png_read_push_finish_row(png_ptr);
654 }
655 }
656 break;
657 }
658 case 2:
659 {
660 int i;
661 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
662 {
663 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
664 png_read_push_finish_row(png_ptr);
665 }
666 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
667 {
668 png_push_have_row(png_ptr, NULL);
669 png_read_push_finish_row(png_ptr);
670 }
671 break;
672 }
673 case 3:
674 {
675 int i;
676 for (i = 0; i < 4 && png_ptr->pass == 3; i++)
677 {
678 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
679 png_read_push_finish_row(png_ptr);
680 }
681 if (png_ptr->pass == 4)
682 {
683 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
684 {
685 png_push_have_row(png_ptr, NULL);
686 png_read_push_finish_row(png_ptr);
687 }
688 }
689 break;
690 }
691 case 4:
692 {
693 int i;
694 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
695 {
696 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
697 png_read_push_finish_row(png_ptr);
698 }
699 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
700 {
701 png_push_have_row(png_ptr, NULL);
702 png_read_push_finish_row(png_ptr);
703 }
704 break;
705 }
706 case 5:
707 {
708 int i;
709 for (i = 0; i < 2 && png_ptr->pass == 5; i++)
710 {
711 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
712 png_read_push_finish_row(png_ptr);
713 }
714 if (png_ptr->pass == 6)
715 {
716 png_push_have_row(png_ptr, NULL);
717 png_read_push_finish_row(png_ptr);
718 }
719 break;
720 }
721 case 6:
722 {
723 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
724 png_read_push_finish_row(png_ptr);
725 if (png_ptr->pass != 6)
726 break;
727 png_push_have_row(png_ptr, NULL);
728 png_read_push_finish_row(png_ptr);
729 }
730 }
731 }
732 else
Guy Schalnat6d764711995-12-19 03:22:19 -0600733#endif
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600734 {
735 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
736 png_read_push_finish_row(png_ptr);
737 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600738}
739
740void
741png_read_push_finish_row(png_structp png_ptr)
742{
743 png_ptr->row_number++;
744 if (png_ptr->row_number < png_ptr->num_rows)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600745 return;
Guy Schalnat6d764711995-12-19 03:22:19 -0600746
747 if (png_ptr->interlaced)
748 {
749 png_ptr->row_number = 0;
750 png_memset(png_ptr->prev_row, 0, (png_size_t)png_ptr->rowbytes + 1);
751 do
752 {
753 png_ptr->pass++;
754 if (png_ptr->pass >= 7)
755 break;
756 png_ptr->iwidth = (png_ptr->width +
757 png_pass_inc[png_ptr->pass] - 1 -
758 png_pass_start[png_ptr->pass]) /
759 png_pass_inc[png_ptr->pass];
760 png_ptr->irowbytes = ((png_ptr->iwidth *
761 png_ptr->pixel_depth + 7) >> 3) + 1;
762 if (!(png_ptr->transformations & PNG_INTERLACE))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600763 {
Guy Schalnat6d764711995-12-19 03:22:19 -0600764 png_ptr->num_rows = (png_ptr->height +
765 png_pass_yinc[png_ptr->pass] - 1 -
766 png_pass_ystart[png_ptr->pass]) /
767 png_pass_yinc[png_ptr->pass];
768 if (!(png_ptr->num_rows))
769 continue;
770 }
771 if (png_ptr->transformations & PNG_INTERLACE)
772 break;
773 } while (png_ptr->iwidth == 0);
774 }
775}
776
Guy Schalnat6d764711995-12-19 03:22:19 -0600777#if defined(PNG_READ_tEXt_SUPPORTED)
778void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600779png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600780{
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600781 if (png_ptr->mode == PNG_BEFORE_IHDR || png_ptr->mode & PNG_HAVE_IEND)
782 png_error(png_ptr, "Out of place tEXt");
783
784 png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600785 png_ptr->current_text[(png_size_t)length] = '\0';
786 png_ptr->current_text_ptr = png_ptr->current_text;
787 png_ptr->current_text_size = length;
788 png_ptr->current_text_left = length;
789 png_ptr->process_mode = PNG_READ_tEXt_MODE;
Guy Schalnat6d764711995-12-19 03:22:19 -0600790}
791
792void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600793png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600794{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600795 if (png_ptr->buffer_size && png_ptr->current_text_left)
796 {
797 png_uint_32 text_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600798
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600799 if (png_ptr->buffer_size < png_ptr->current_text_left)
800 text_size = png_ptr->buffer_size;
801 else
802 text_size = png_ptr->current_text_left;
803 png_push_fill_buffer(png_ptr, (png_bytep)png_ptr->current_text_ptr,
804 text_size);
805 png_calculate_crc(png_ptr, (png_bytep)png_ptr->current_text_ptr,
806 text_size);
807 png_ptr->current_text_left -= text_size;
808 png_ptr->current_text_ptr += (png_size_t)text_size;
809 }
810 if (!(png_ptr->current_text_left))
811 {
812 png_charp text;
813 png_charp key;
Guy Schalnat6d764711995-12-19 03:22:19 -0600814
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600815 if (png_ptr->buffer_size < 4)
816 {
817 png_push_save_buffer(png_ptr);
818 return;
819 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600820
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600821 png_crc_finish(png_ptr, 0);
Guy Schalnat6d764711995-12-19 03:22:19 -0600822
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600823 key = png_ptr->current_text;
824 png_ptr->current_text = 0;
Guy Schalnat6d764711995-12-19 03:22:19 -0600825
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600826 for (text = key; *text; text++)
827 /* empty loop */ ;
Guy Schalnat6d764711995-12-19 03:22:19 -0600828
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600829 if (text != key + (png_size_t)png_ptr->current_text_size)
830 text++;
831
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600832 png_read_tEXt(png_ptr, info_ptr, key, text,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600833 png_ptr->current_text_size - (text - key));
834
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600835 if (png_ptr->mode == PNG_AFTER_IDAT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600836 {
837 png_ptr->process_mode = PNG_READ_END_MODE;
838 }
839 else
840 {
841 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
842 }
843 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600844}
845#endif
846
847#if defined(PNG_READ_zTXt_SUPPORTED)
848void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600849png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600850{
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600851 if (png_ptr->mode == PNG_BEFORE_IHDR || png_ptr->mode & PNG_HAVE_IEND)
852 png_error(png_ptr, "Out of place zTXt");
853
854 png_ptr->current_text = (png_charp)png_malloc(png_ptr, length + 1);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600855 png_ptr->current_text[(png_size_t)length] = '\0';
856 png_ptr->current_text_ptr = png_ptr->current_text;
857 png_ptr->current_text_size = length;
858 png_ptr->current_text_left = length;
859 png_ptr->process_mode = PNG_READ_zTXt_MODE;
Guy Schalnat6d764711995-12-19 03:22:19 -0600860}
861
862void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600863png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600864{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600865 if (png_ptr->buffer_size && png_ptr->current_text_left)
866 {
867 png_uint_32 text_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600868
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600869 if (png_ptr->buffer_size < png_ptr->current_text_left)
870 text_size = png_ptr->buffer_size;
871 else
872 text_size = png_ptr->current_text_left;
873 png_push_fill_buffer(png_ptr, (png_bytep)png_ptr->current_text_ptr,
874 text_size);
875 png_calculate_crc(png_ptr, (png_bytep)png_ptr->current_text_ptr,
876 text_size);
877 png_ptr->current_text_left -= text_size;
878 png_ptr->current_text_ptr += (png_size_t)text_size;
879 }
880 if (!(png_ptr->current_text_left))
881 {
882 png_charp text;
883 png_charp key;
884 int ret;
885 png_uint_32 text_size, key_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600886
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600887 if (png_ptr->buffer_size < 4)
888 {
889 png_push_save_buffer(png_ptr);
890 return;
891 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600892
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600893 png_crc_finish(png_ptr, 0);
Guy Schalnat6d764711995-12-19 03:22:19 -0600894
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600895 key = png_ptr->current_text;
896 png_ptr->current_text = 0;
Guy Schalnat6d764711995-12-19 03:22:19 -0600897
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600898 for (text = key; *text; text++)
899 /* empty loop */ ;
Guy Schalnat6d764711995-12-19 03:22:19 -0600900
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600901 /* zTXt can't have zero text */
902 if (text == key + (png_size_t)png_ptr->current_text_size)
903 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600904 png_free(png_ptr, key);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600905 return;
906 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600907
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600908 text++;
Guy Schalnat6d764711995-12-19 03:22:19 -0600909
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600910 if (*text) /* check compression byte */
911 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600912 png_free(png_ptr, key);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600913 return;
914 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600915
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600916 text++;
Guy Schalnat6d764711995-12-19 03:22:19 -0600917
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600918 png_ptr->zstream.next_in = (png_bytep )text;
919 png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600920 (text - key));
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600921 png_ptr->zstream.next_out = png_ptr->zbuf;
922 png_ptr->zstream.avail_out = (png_size_t)png_ptr->zbuf_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600923
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600924 key_size = text - key;
925 text_size = 0;
926 text = NULL;
927 ret = Z_STREAM_END;
Guy Schalnat6d764711995-12-19 03:22:19 -0600928
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600929 while (png_ptr->zstream.avail_in)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600930 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600931 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600932 if (ret != Z_OK && ret != Z_STREAM_END)
933 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600934 inflateReset(&png_ptr->zstream);
935 png_ptr->zstream.avail_in = 0;
936 png_free(png_ptr, key);
937 png_free(png_ptr, text);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600938 return;
939 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600940 if (!png_ptr->zstream.avail_out || ret == Z_STREAM_END)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600941 {
942 if (!text)
943 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600944 text = (png_charp)png_malloc(png_ptr,
945 png_ptr->zbuf_size - png_ptr->zstream.avail_out +
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600946 key_size + 1);
947 png_memcpy(text + (png_size_t)key_size, png_ptr->zbuf,
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600948 (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600949 png_memcpy(text, key, (png_size_t)key_size);
950 text_size = key_size + (png_size_t)png_ptr->zbuf_size -
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600951 png_ptr->zstream.avail_out;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600952 *(text + (png_size_t)text_size) = '\0';
953 }
954 else
955 {
956 png_charp tmp;
Guy Schalnat6d764711995-12-19 03:22:19 -0600957
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600958 tmp = text;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600959 text = png_malloc(png_ptr, text_size +
960 png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600961 png_memcpy(text, tmp, (png_size_t)text_size);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600962 png_free(png_ptr, tmp);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600963 png_memcpy(text + (png_size_t)text_size, png_ptr->zbuf,
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600964 (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
965 text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600966 *(text + (png_size_t)text_size) = '\0';
967 }
968 if (ret != Z_STREAM_END)
969 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600970 png_ptr->zstream.next_out = png_ptr->zbuf;
971 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600972 }
973 }
974 else
975 {
976 break;
977 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600978
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600979 if (ret == Z_STREAM_END)
980 break;
981 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600982
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600983 inflateReset(&png_ptr->zstream);
984 png_ptr->zstream.avail_in = 0;
Guy Schalnat6d764711995-12-19 03:22:19 -0600985
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600986 if (ret != Z_STREAM_END)
987 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600988 png_free(png_ptr, key);
989 png_free(png_ptr, text);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600990 return;
991 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600992
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600993 png_free(png_ptr, key);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600994 key = text;
995 text += (png_size_t)key_size;
996 text_size -= key_size;
997
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600998 png_read_zTXt(png_ptr, info_ptr, key, text, text_size, 0);
999 if (png_ptr->mode == PNG_AFTER_IDAT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001000 {
1001 png_ptr->process_mode = PNG_READ_END_MODE;
1002 }
1003 else
1004 {
1005 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
1006 }
1007 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001008}
1009#endif
1010
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001011/* This function is called when we haven't found a handler for this
1012 chunk. In the future we will have code here which can handle
1013 user-defined callback functions for unknown chunks before they are
1014 ignored or cause an error. If there isn't a problem with the
1015 chunk itself (ie a bad chunk name or a critical chunk), the chunk
1016 is (currently) silently ignored. */
Guy Schalnat6d764711995-12-19 03:22:19 -06001017void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001018png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
Guy Schalnat6d764711995-12-19 03:22:19 -06001019{
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001020 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
1021
1022 if (!(png_ptr->chunk_name[0] & 0x20))
1023 {
1024 char msg[40];
1025
1026 sprintf(msg, "Unknown critical chunk %s", png_ptr->chunk_name);
1027 png_error(png_ptr, msg);
1028 }
1029
1030 png_push_crc_skip(png_ptr, length);
Guy Schalnat6d764711995-12-19 03:22:19 -06001031}
1032
1033void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001034png_push_have_info(png_structp png_ptr, png_infop info_ptr)
1035{
1036 if (png_ptr->info_fn)
1037 (*(png_ptr->info_fn))(png_ptr, info_ptr);
1038}
1039
1040void
1041png_push_have_end(png_structp png_ptr, png_infop info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001042{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001043 if (png_ptr->end_fn)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001044 (*(png_ptr->end_fn))(png_ptr, info_ptr);
Guy Schalnat6d764711995-12-19 03:22:19 -06001045}
1046
1047void
1048png_push_have_row(png_structp png_ptr, png_bytep row)
1049{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001050 if (png_ptr->row_fn)
1051 (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
1052 (int)png_ptr->pass);
Guy Schalnat6d764711995-12-19 03:22:19 -06001053}
1054
Guy Schalnat6d764711995-12-19 03:22:19 -06001055void
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001056png_progressive_combine_row (png_structp png_ptr,
1057 png_bytep old_row, png_bytep new_row)
Guy Schalnat6d764711995-12-19 03:22:19 -06001058{
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001059 if (new_row)
1060 png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
Guy Schalnat6d764711995-12-19 03:22:19 -06001061}
1062
1063void
1064png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001065 png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
1066 png_progressive_end_ptr end_fn)
Guy Schalnat6d764711995-12-19 03:22:19 -06001067{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001068 png_ptr->info_fn = info_fn;
1069 png_ptr->row_fn = row_fn;
Guy Schalnat6d764711995-12-19 03:22:19 -06001070 png_ptr->end_fn = end_fn;
Guy Schalnate5a37791996-06-05 15:50:50 -05001071
1072 png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
Guy Schalnat6d764711995-12-19 03:22:19 -06001073}
1074
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001075png_voidp
1076png_get_progressive_ptr(png_structp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001077{
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001078 return png_ptr->io_ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -06001079}
1080
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001081#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
1082