blob: a4d073b945db7e249ae0d5331c9d2ba3609d09ad [file] [log] [blame]
Guy Schalnat6d764711995-12-19 03:22:19 -06001
2/* pngpread.c - read a png file in push mode
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -06003 *
Glenn Randers-Pehrson212fd572014-06-11 21:10:16 -05004 * Last changed in libpng 1.6.11 [June 5, 2014]
Glenn Randers-Pehrsoneb657ae2014-02-22 21:59:40 -06005 * Copyright (c) 1998-2014 Glenn Randers-Pehrson
Glenn Randers-Pehrsond4366722000-06-04 14:29:29 -05006 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
7 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
Glenn Randers-Pehrson3e61d792009-06-24 09:31:28 -05008 *
Glenn Randers-Pehrsonbfbf8652009-06-26 21:46:52 -05009 * This code is released under the libpng license.
Glenn Randers-Pehrsonc332bbc2009-06-25 13:43:50 -050010 * For conditions of distribution and use, see the disclaimer
Glenn Randers-Pehrson037023b2009-06-24 10:27:36 -050011 * and license in png.h
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -060012 */
Guy Schalnat6d764711995-12-19 03:22:19 -060013
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -050014#include "pngpriv.h"
Guy Schalnat4ee97b01996-01-16 01:51:56 -060015
Glenn Randers-Pehrsonc3cd22b2010-03-08 21:10:25 -060016#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
17
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -050018/* Push model modes */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -060019#define PNG_READ_SIG_MODE 0
20#define PNG_READ_CHUNK_MODE 1
21#define PNG_READ_IDAT_MODE 2
22#define PNG_SKIP_MODE 3
23#define PNG_READ_tEXt_MODE 4
24#define PNG_READ_zTXt_MODE 5
25#define PNG_READ_DONE_MODE 6
26#define PNG_READ_iTXt_MODE 7
27#define PNG_ERROR_MODE 8
28
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -050029void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060030png_process_data(png_structrp png_ptr, png_inforp info_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -060031 png_bytep buffer, png_size_t buffer_size)
Guy Schalnat6d764711995-12-19 03:22:19 -060032{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -050033 if (png_ptr == NULL || info_ptr == NULL)
34 return;
35
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060036 png_push_restore_buffer(png_ptr, buffer, buffer_size);
Guy Schalnat6d764711995-12-19 03:22:19 -060037
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060038 while (png_ptr->buffer_size)
39 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -060040 png_process_some_data(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -060041 }
Guy Schalnat6d764711995-12-19 03:22:19 -060042}
43
John Bowler0a5c9c02011-01-22 17:36:34 -060044png_size_t PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060045png_process_data_pause(png_structrp png_ptr, int save)
John Bowler0a5c9c02011-01-22 17:36:34 -060046{
47 if (png_ptr != NULL)
48 {
49 /* It's easiest for the caller if we do the save, then the caller doesn't
50 * have to supply the same data again:
51 */
Glenn Randers-Pehrson05670152014-03-08 12:39:52 -060052 if (save != 0)
John Bowler0a5c9c02011-01-22 17:36:34 -060053 png_push_save_buffer(png_ptr);
54 else
55 {
56 /* This includes any pending saved bytes: */
57 png_size_t remaining = png_ptr->buffer_size;
58 png_ptr->buffer_size = 0;
59
60 /* So subtract the saved buffer size, unless all the data
61 * is actually 'saved', in which case we just return 0
62 */
63 if (png_ptr->save_buffer_size < remaining)
64 return remaining - png_ptr->save_buffer_size;
65 }
66 }
67
68 return 0;
69}
70
71png_uint_32 PNGAPI
John Bowler5d567862011-12-24 09:12:00 -060072png_process_data_skip(png_structrp png_ptr)
John Bowler0a5c9c02011-01-22 17:36:34 -060073{
John Bowlerfca50df2011-01-28 06:34:02 -060074 png_uint_32 remaining = 0;
John Bowler0a5c9c02011-01-22 17:36:34 -060075
76 if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE &&
77 png_ptr->skip_length > 0)
78 {
79 /* At the end of png_process_data the buffer size must be 0 (see the loop
80 * above) so we can detect a broken call here:
81 */
82 if (png_ptr->buffer_size != 0)
83 png_error(png_ptr,
84 "png_process_data_skip called inside png_process_data");
85
86 /* If is impossible for there to be a saved buffer at this point -
87 * otherwise we could not be in SKIP mode. This will also happen if
88 * png_process_skip is called inside png_process_data (but only very
89 * rarely.)
90 */
91 if (png_ptr->save_buffer_size != 0)
92 png_error(png_ptr, "png_process_data_skip called with saved data");
93
94 remaining = png_ptr->skip_length;
95 png_ptr->skip_length = 0;
96 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
97 }
98
99 return remaining;
100}
101
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600102/* What we do with the incoming data depends on what we were previously
103 * doing before we ran out of data...
104 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500105void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600106png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600107{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500108 if (png_ptr == NULL)
109 return;
110
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600111 switch (png_ptr->process_mode)
112 {
113 case PNG_READ_SIG_MODE:
114 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600115 png_push_read_sig(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600116 break;
117 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500118
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600119 case PNG_READ_CHUNK_MODE:
120 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600121 png_push_read_chunk(png_ptr, info_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600122 break;
123 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500124
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600125 case PNG_READ_IDAT_MODE:
126 {
Guy Schalnate5a37791996-06-05 15:50:50 -0500127 png_push_read_IDAT(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600128 break;
129 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500130
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600131 case PNG_SKIP_MODE:
132 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500133 png_push_crc_finish(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600134 break;
135 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500136
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600137 default:
138 {
139 png_ptr->buffer_size = 0;
140 break;
141 }
142 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600143}
144
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600145/* Read any remaining signature bytes from the stream and compare them with
146 * the correct PNG signature. It is possible that this routine is called
Glenn Randers-Pehrson345bc271998-06-14 14:43:31 -0500147 * with bytes already read from the signature, either because they have been
148 * checked by the calling application, or because of multiple calls to this
149 * routine.
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600150 */
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500151void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600152png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600153{
Glenn Randers-Pehrsonbc8e40d2013-07-15 08:44:53 -0500154 png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500155 num_to_check = 8 - num_checked;
Guy Schalnat6d764711995-12-19 03:22:19 -0600156
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600157 if (png_ptr->buffer_size < num_to_check)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600158 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600159 num_to_check = png_ptr->buffer_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600160 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600161
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600162 png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600163 num_to_check);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500164 png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
Guy Schalnat6d764711995-12-19 03:22:19 -0600165
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600166 if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600167 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600168 if (num_checked < 4 &&
169 png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
170 png_error(png_ptr, "Not a PNG file");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500171
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600172 else
173 png_error(png_ptr, "PNG file corrupted by ASCII conversion");
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600174 }
175 else
176 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600177 if (png_ptr->sig_bytes >= 8)
178 {
179 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
180 }
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600181 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600182}
183
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500184void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600185png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600186{
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500187 png_uint_32 chunk_name;
Glenn Randers-Pehrsonbd757ac2013-11-18 18:40:39 -0600188#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600189 int keep; /* unknown handling method */
190#endif
Glenn Randers-Pehrsona2567be2009-10-19 20:31:31 -0500191
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600192 /* First we make sure we have enough data for the 4 byte chunk name
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600193 * and the 4 byte chunk length before proceeding with decoding the
194 * chunk data. To fully decode each of these chunks, we also make
195 * sure we have enough data in the buffer for the 4 byte CRC at the
196 * end of every chunk (except IDAT, which is handled separately).
197 */
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600198 if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600199 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600200 png_byte chunk_length[4];
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500201 png_byte chunk_tag[4];
Guy Schalnat6d764711995-12-19 03:22:19 -0600202
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600203 if (png_ptr->buffer_size < 8)
204 {
205 png_push_save_buffer(png_ptr);
206 return;
207 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600208
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600209 png_push_fill_buffer(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500210 png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600211 png_reset_crc(png_ptr);
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500212 png_crc_read(png_ptr, chunk_tag, 4);
213 png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -0500214 png_check_chunk_name(png_ptr, png_ptr->chunk_name);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600215 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600216 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600217
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500218 chunk_name = png_ptr->chunk_name;
219
220 if (chunk_name == png_IDAT)
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -0500221 {
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600222 if (png_ptr->mode & PNG_AFTER_IDAT)
223 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600224
225 /* If we reach an IDAT chunk, this means we have read all of the
226 * header chunks, and we can start reading the image (or if this
227 * is called after the image has been read - we have an error).
228 */
229 if (!(png_ptr->mode & PNG_HAVE_IHDR))
230 png_error(png_ptr, "Missing IHDR before IDAT");
231
232 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
233 !(png_ptr->mode & PNG_HAVE_PLTE))
234 png_error(png_ptr, "Missing PLTE before IDAT");
235
236 png_ptr->mode |= PNG_HAVE_IDAT;
Glenn Randers-Pehrsoneb657ae2014-02-22 21:59:40 -0600237 png_ptr->process_mode = PNG_READ_IDAT_MODE;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600238
239 if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
240 if (png_ptr->push_length == 0)
241 return;
242
243 if (png_ptr->mode & PNG_AFTER_IDAT)
244 png_benign_error(png_ptr, "Too many IDATs found");
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -0500245 }
Glenn Randers-Pehrson6bc53be2006-06-16 07:52:03 -0500246
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500247 if (chunk_name == png_IHDR)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600248 {
Glenn Randers-Pehrsoneb580912008-07-30 14:47:09 -0500249 if (png_ptr->push_length != 13)
250 png_error(png_ptr, "Invalid IHDR length");
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500251
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500252 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
253 {
254 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600255 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500256 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500257
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600258 png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600259 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500260
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500261 else if (chunk_name == png_IEND)
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500262 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500263 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
264 {
265 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500266 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500267 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500268
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500269 png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
270
271 png_ptr->process_mode = PNG_READ_DONE_MODE;
272 png_push_have_end(png_ptr, info_ptr);
273 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500274
Glenn Randers-Pehrsonbd757ac2013-11-18 18:40:39 -0600275#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600276 else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500277 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500278 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
279 {
280 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500281 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500282 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500283
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600284 png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500285
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500286 if (chunk_name == png_PLTE)
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500287 png_ptr->mode |= PNG_HAVE_PLTE;
Glenn Randers-Pehrsond029a752004-08-09 21:50:32 -0500288 }
289#endif
Glenn Randers-Pehrson012d36f2013-11-17 19:42:48 -0600290
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500291 else if (chunk_name == png_PLTE)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600292 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500293 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
294 {
295 png_push_save_buffer(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600296 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500297 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600298 png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600299 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500300
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500301 else if (chunk_name == png_IDAT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600302 {
303 png_ptr->idat_size = png_ptr->push_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600304 png_ptr->process_mode = PNG_READ_IDAT_MODE;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600305 png_push_have_info(png_ptr, info_ptr);
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600306 png_ptr->zstream.avail_out =
307 (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
308 png_ptr->iwidth) + 1;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600309 png_ptr->zstream.next_out = png_ptr->row_buf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600310 return;
311 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500312
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500313#ifdef PNG_READ_gAMA_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500314 else if (png_ptr->chunk_name == png_gAMA)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600315 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500316 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
317 {
318 png_push_save_buffer(png_ptr);
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600319 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500320 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500321
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600322 png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600323 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500324
Guy Schalnat6d764711995-12-19 03:22:19 -0600325#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500326#ifdef PNG_READ_sBIT_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500327 else if (png_ptr->chunk_name == png_sBIT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600328 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500329 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
330 {
331 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600332 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500333 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500334
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600335 png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600336 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500337
Guy Schalnat6d764711995-12-19 03:22:19 -0600338#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500339#ifdef PNG_READ_cHRM_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500340 else if (png_ptr->chunk_name == png_cHRM)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600341 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500342 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
343 {
344 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600345 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500346 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500347
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600348 png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600349 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500350
Guy Schalnat6d764711995-12-19 03:22:19 -0600351#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500352#ifdef PNG_READ_sRGB_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500353 else if (chunk_name == png_sRGB)
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600354 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500355 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
356 {
357 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600358 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500359 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500360
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600361 png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
362 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500363
Glenn Randers-Pehrsonb6ce43d1998-01-01 07:13:13 -0600364#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500365#ifdef PNG_READ_iCCP_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500366 else if (png_ptr->chunk_name == png_iCCP)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600367 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500368 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
369 {
370 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600371 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500372 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500373
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600374 png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
375 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500376
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600377#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500378#ifdef PNG_READ_sPLT_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500379 else if (chunk_name == png_sPLT)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600380 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500381 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
382 {
383 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600384 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500385 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500386
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600387 png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
388 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500389
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600390#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500391#ifdef PNG_READ_tRNS_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500392 else if (chunk_name == png_tRNS)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600393 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500394 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
395 {
396 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600397 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500398 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500399
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600400 png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600401 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500402
Guy Schalnat6d764711995-12-19 03:22:19 -0600403#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500404#ifdef PNG_READ_bKGD_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500405 else if (chunk_name == png_bKGD)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600406 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500407 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
408 {
409 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600410 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500411 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500412
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600413 png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600414 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500415
Guy Schalnat6d764711995-12-19 03:22:19 -0600416#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500417#ifdef PNG_READ_hIST_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500418 else if (chunk_name == png_hIST)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600419 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500420 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
421 {
422 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600423 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500424 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500425
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600426 png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600427 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500428
Guy Schalnat6d764711995-12-19 03:22:19 -0600429#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500430#ifdef PNG_READ_pHYs_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500431 else if (chunk_name == png_pHYs)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600432 {
433 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
434 {
435 png_push_save_buffer(png_ptr);
436 return;
437 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500438
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600439 png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600440 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500441
Guy Schalnat6d764711995-12-19 03:22:19 -0600442#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500443#ifdef PNG_READ_oFFs_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500444 else if (chunk_name == png_oFFs)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600445 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500446 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
447 {
448 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600449 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500450 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500451
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600452 png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600453 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600454#endif
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500455
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500456#ifdef PNG_READ_pCAL_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500457 else if (chunk_name == png_pCAL)
Andreas Dilger47a0c421997-05-16 02:46:07 -0500458 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500459 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
460 {
461 png_push_save_buffer(png_ptr);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500462 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500463 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500464
Andreas Dilger47a0c421997-05-16 02:46:07 -0500465 png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
466 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500467
Andreas Dilger47a0c421997-05-16 02:46:07 -0500468#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500469#ifdef PNG_READ_sCAL_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500470 else if (chunk_name == png_sCAL)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600471 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500472 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
473 {
474 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600475 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500476 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500477
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600478 png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
479 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500480
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600481#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500482#ifdef PNG_READ_tIME_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500483 else if (chunk_name == png_tIME)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600484 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500485 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
486 {
487 png_push_save_buffer(png_ptr);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600488 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500489 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500490
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600491 png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600492 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500493
Guy Schalnat6d764711995-12-19 03:22:19 -0600494#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500495#ifdef PNG_READ_tEXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500496 else if (chunk_name == png_tEXt)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600497 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500498 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
499 {
500 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500501 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500502 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500503
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600504 png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600505 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500506
Guy Schalnat6d764711995-12-19 03:22:19 -0600507#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500508#ifdef PNG_READ_zTXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500509 else if (chunk_name == png_zTXt)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600510 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500511 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
512 {
513 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500514 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500515 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500516
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600517 png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600518 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500519
Guy Schalnat6d764711995-12-19 03:22:19 -0600520#endif
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500521#ifdef PNG_READ_iTXt_SUPPORTED
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500522 else if (chunk_name == png_iTXt)
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600523 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500524 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
525 {
526 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500527 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500528 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500529
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600530 png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -0600531 }
532#endif
Glenn Randers-Pehrson416bb932013-11-17 11:01:31 -0600533
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600534 else
535 {
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500536 if (png_ptr->push_length + 4 > png_ptr->buffer_size)
537 {
538 png_push_save_buffer(png_ptr);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -0500539 return;
Glenn Randers-Pehrson79084212008-08-04 13:31:41 -0500540 }
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600541 png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
542 PNG_HANDLE_CHUNK_AS_DEFAULT);
Glenn Randers-Pehrson68dfa9e2013-11-17 19:26:40 -0600543 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600544
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600545 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
Guy Schalnat6d764711995-12-19 03:22:19 -0600546}
547
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500548void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600549png_push_crc_skip(png_structrp png_ptr, png_uint_32 skip)
Guy Schalnat6d764711995-12-19 03:22:19 -0600550{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600551 png_ptr->process_mode = PNG_SKIP_MODE;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500552 png_ptr->skip_length = skip;
Guy Schalnat6d764711995-12-19 03:22:19 -0600553}
554
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500555void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600556png_push_crc_finish(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600557{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600558 if (png_ptr->skip_length && png_ptr->save_buffer_size)
559 {
Glenn Randers-Pehrson1408c2a2011-01-16 14:16:28 -0600560 png_size_t save_size = png_ptr->save_buffer_size;
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500561 png_uint_32 skip_length = png_ptr->skip_length;
Guy Schalnat6d764711995-12-19 03:22:19 -0600562
John Bowler168a4332011-01-16 19:32:22 -0600563 /* We want the smaller of 'skip_length' and 'save_buffer_size', but
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500564 * they are of different types and we don't know which variable has the
565 * fewest bits. Carefully select the smaller and cast it to the type of
566 * the larger - this cannot overflow. Do not cast in the following test
567 * - it will break on either 16 or 64 bit platforms.
568 */
569 if (skip_length < save_size)
570 save_size = (png_size_t)skip_length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500571
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600572 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500573 skip_length = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600574
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600575 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600576
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500577 png_ptr->skip_length -= skip_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600578 png_ptr->buffer_size -= save_size;
579 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500580 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600581 }
582 if (png_ptr->skip_length && png_ptr->current_buffer_size)
583 {
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500584 png_size_t save_size = png_ptr->current_buffer_size;
585 png_uint_32 skip_length = png_ptr->skip_length;
Guy Schalnat6d764711995-12-19 03:22:19 -0600586
John Bowler168a4332011-01-16 19:32:22 -0600587 /* We want the smaller of 'skip_length' and 'current_buffer_size', here,
588 * the same problem exists as above and the same solution.
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500589 */
590 if (skip_length < save_size)
591 save_size = (png_size_t)skip_length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500592
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600593 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500594 skip_length = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600595
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600596 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600597
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500598 png_ptr->skip_length -= skip_length;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600599 png_ptr->buffer_size -= save_size;
600 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500601 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600602 }
603 if (!png_ptr->skip_length)
604 {
605 if (png_ptr->buffer_size < 4)
606 {
607 png_push_save_buffer(png_ptr);
608 return;
609 }
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600610
611 png_crc_finish(png_ptr, 0);
Andreas Dilger47a0c421997-05-16 02:46:07 -0500612 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600613 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600614}
615
Glenn Randers-Pehrsoneae8e362010-03-12 17:36:53 -0600616void PNGCBAPI
Andreas Dilger47a0c421997-05-16 02:46:07 -0500617png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600618{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600619 png_bytep ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -0600620
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500621 if (png_ptr == NULL)
622 return;
623
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600624 ptr = buffer;
625 if (png_ptr->save_buffer_size)
626 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500627 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600628
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600629 if (length < png_ptr->save_buffer_size)
630 save_size = length;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500631
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600632 else
633 save_size = png_ptr->save_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600634
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600635 memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600636 length -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500637 ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600638 png_ptr->buffer_size -= save_size;
639 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500640 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600641 }
642 if (length && png_ptr->current_buffer_size)
643 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500644 png_size_t save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600645
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600646 if (length < png_ptr->current_buffer_size)
647 save_size = length;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500648
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600649 else
650 save_size = png_ptr->current_buffer_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600651
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600652 memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600653 png_ptr->buffer_size -= save_size;
654 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500655 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600656 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600657}
658
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500659void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600660png_push_save_buffer(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600661{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600662 if (png_ptr->save_buffer_size)
663 {
664 if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
665 {
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500666 png_size_t i, istop;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600667 png_bytep sp;
668 png_bytep dp;
Guy Schalnat6d764711995-12-19 03:22:19 -0600669
Glenn Randers-Pehrson896239b1998-04-21 15:03:57 -0500670 istop = png_ptr->save_buffer_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600671 for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600672 i < istop; i++, sp++, dp++)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600673 {
674 *dp = *sp;
675 }
676 }
677 }
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600678 if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600679 png_ptr->save_buffer_max)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600680 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500681 png_size_t new_max;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600682 png_bytep old_buffer;
Guy Schalnat6d764711995-12-19 03:22:19 -0600683
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600684 if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600685 (png_ptr->current_buffer_size + 256))
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600686 {
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600687 png_error(png_ptr, "Potential overflow of save_buffer");
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600688 }
Glenn Randers-Pehrsone3f3c4e2010-02-07 18:08:50 -0600689
Glenn Randers-Pehrsone00ed362010-02-07 22:42:58 -0600690 new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600691 old_buffer = png_ptr->save_buffer;
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600692 png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600693 (png_size_t)new_max);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500694
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600695 if (png_ptr->save_buffer == NULL)
696 {
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -0600697 png_free(png_ptr, old_buffer);
698 png_error(png_ptr, "Insufficient memory for save_buffer");
Glenn Randers-Pehrsonf1eb9182010-02-08 15:36:41 -0600699 }
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500700
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600701 memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
Glenn Randers-Pehrson82ae3832001-04-20 10:32:10 -0500702 png_free(png_ptr, old_buffer);
703 png_ptr->save_buffer_max = new_max;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600704 }
705 if (png_ptr->current_buffer_size)
706 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600707 memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
Andreas Dilger47a0c421997-05-16 02:46:07 -0500708 png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600709 png_ptr->save_buffer_size += png_ptr->current_buffer_size;
710 png_ptr->current_buffer_size = 0;
711 }
712 png_ptr->save_buffer_ptr = png_ptr->save_buffer;
713 png_ptr->buffer_size = 0;
Guy Schalnat6d764711995-12-19 03:22:19 -0600714}
715
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500716void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600717png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
Andreas Dilger47a0c421997-05-16 02:46:07 -0500718 png_size_t buffer_length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600719{
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600720 png_ptr->current_buffer = buffer;
721 png_ptr->current_buffer_size = buffer_length;
722 png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
723 png_ptr->current_buffer_ptr = png_ptr->current_buffer;
Guy Schalnat6d764711995-12-19 03:22:19 -0600724}
725
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500726void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600727png_push_read_IDAT(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600728{
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600729 if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600730 {
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600731 png_byte chunk_length[4];
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500732 png_byte chunk_tag[4];
Guy Schalnat6d764711995-12-19 03:22:19 -0600733
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500734 /* TODO: this code can be commoned up with the same code in push_read */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600735 if (png_ptr->buffer_size < 8)
736 {
737 png_push_save_buffer(png_ptr);
738 return;
739 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600740
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600741 png_push_fill_buffer(png_ptr, chunk_length, 4);
Glenn Randers-Pehrson145f5c82008-07-10 09:13:13 -0500742 png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600743 png_reset_crc(png_ptr);
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500744 png_crc_read(png_ptr, chunk_tag, 4);
745 png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600746 png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600747
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500748 if (png_ptr->chunk_name != png_IDAT)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600749 {
Andreas Dilger47a0c421997-05-16 02:46:07 -0500750 png_ptr->process_mode = PNG_READ_CHUNK_MODE;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500751
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600752 if (!(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600753 png_error(png_ptr, "Not enough compressed data");
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500754
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600755 return;
756 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600757
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600758 png_ptr->idat_size = png_ptr->push_length;
759 }
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500760
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600761 if (png_ptr->idat_size && png_ptr->save_buffer_size)
762 {
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500763 png_size_t save_size = png_ptr->save_buffer_size;
764 png_uint_32 idat_size = png_ptr->idat_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600765
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500766 /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
767 * are of different types and we don't know which variable has the fewest
768 * bits. Carefully select the smaller and cast it to the type of the
769 * larger - this cannot overflow. Do not cast in the following test - it
770 * will break on either 16 or 64 bit platforms.
771 */
772 if (idat_size < save_size)
773 save_size = (png_size_t)idat_size;
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500774
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600775 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500776 idat_size = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600777
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600778 png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500779
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500780 png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500781
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500782 png_ptr->idat_size -= idat_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600783 png_ptr->buffer_size -= save_size;
784 png_ptr->save_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500785 png_ptr->save_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600786 }
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500787
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600788 if (png_ptr->idat_size && png_ptr->current_buffer_size)
789 {
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500790 png_size_t save_size = png_ptr->current_buffer_size;
791 png_uint_32 idat_size = png_ptr->idat_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600792
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500793 /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
794 * are of different types and we don't know which variable has the fewest
795 * bits. Carefully select the smaller and cast it to the type of the
796 * larger - this cannot overflow.
797 */
798 if (idat_size < save_size)
799 save_size = (png_size_t)idat_size;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500800
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600801 else
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500802 idat_size = (png_uint_32)save_size;
Guy Schalnat6d764711995-12-19 03:22:19 -0600803
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600804 png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -0500805
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500806 png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
Guy Schalnat6d764711995-12-19 03:22:19 -0600807
Glenn Randers-Pehrsonbcb3aac2010-09-10 22:05:27 -0500808 png_ptr->idat_size -= idat_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600809 png_ptr->buffer_size -= save_size;
810 png_ptr->current_buffer_size -= save_size;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500811 png_ptr->current_buffer_ptr += save_size;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600812 }
813 if (!png_ptr->idat_size)
814 {
815 if (png_ptr->buffer_size < 4)
816 {
817 png_push_save_buffer(png_ptr);
818 return;
819 }
820
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600821 png_crc_finish(png_ptr, 0);
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -0600822 png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -0500823 png_ptr->mode |= PNG_AFTER_IDAT;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600824 png_ptr->zowner = 0;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600825 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600826}
827
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500828void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600829png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
Andreas Dilger47a0c421997-05-16 02:46:07 -0500830 png_size_t buffer_length)
Guy Schalnat6d764711995-12-19 03:22:19 -0600831{
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500832 /* The caller checks for a non-zero buffer length. */
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500833 if (!(buffer_length > 0) || buffer == NULL)
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500834 png_error(png_ptr, "No IDAT data (internal error)");
Guy Schalnat6d764711995-12-19 03:22:19 -0600835
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500836 /* This routine must process all the data it has been given
837 * before returning, calling the row callback as required to
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500838 * handle the uncompressed results.
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500839 */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600840 png_ptr->zstream.next_in = buffer;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600841 /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600842 png_ptr->zstream.avail_in = (uInt)buffer_length;
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500843
844 /* Keep going until the decompressed data is all processed
845 * or the stream marked as finished.
846 */
847 while (png_ptr->zstream.avail_in > 0 &&
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600848 !(png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600849 {
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500850 int ret;
851
852 /* We have data for zlib, but we must check that zlib
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500853 * has someplace to put the results. It doesn't matter
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500854 * if we don't expect any results -- it may be the input
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500855 * data is just the LZ end code.
856 */
857 if (!(png_ptr->zstream.avail_out > 0))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600858 {
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600859 /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
860 png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
861 png_ptr->iwidth) + 1);
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500862
Andreas Dilger02ad0ef1997-01-17 01:34:35 -0600863 png_ptr->zstream.next_out = png_ptr->row_buf;
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600864 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500865
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500866 /* Using Z_SYNC_FLUSH here means that an unterminated
Glenn Randers-Pehrsonef3831a2010-06-22 13:03:32 -0500867 * LZ stream (a stream with a missing end code) can still
868 * be handled, otherwise (Z_NO_FLUSH) a future zlib
869 * implementation might defer output and therefore
870 * change the current behavior (see comments in inflate.c
871 * for why this doesn't happen at present with zlib 1.2.5).
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500872 */
873 ret = inflate(&png_ptr->zstream, Z_SYNC_FLUSH);
874
875 /* Check for any failure before proceeding. */
876 if (ret != Z_OK && ret != Z_STREAM_END)
877 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500878 /* Terminate the decompression. */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600879 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
880 png_ptr->zowner = 0;
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500881
882 /* This may be a truncated stream (missing or
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500883 * damaged end code). Treat that as a warning.
884 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500885 if (png_ptr->row_number >= png_ptr->num_rows ||
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500886 png_ptr->pass > 6)
887 png_warning(png_ptr, "Truncated compressed data in IDAT");
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500888
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500889 else
890 png_error(png_ptr, "Decompression error in IDAT");
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500891
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500892 /* Skip the check on unprocessed input */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500893 return;
894 }
895
896 /* Did inflate output any data? */
897 if (png_ptr->zstream.next_out != png_ptr->row_buf)
898 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500899 /* Is this unexpected data after the last row?
900 * If it is, artificially terminate the LZ output
901 * here.
902 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500903 if (png_ptr->row_number >= png_ptr->num_rows ||
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500904 png_ptr->pass > 6)
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500905 {
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500906 /* Extra data. */
907 png_warning(png_ptr, "Extra compressed data in IDAT");
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600908 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
909 png_ptr->zowner = 0;
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500910
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500911 /* Do no more processing; skip the unprocessed
912 * input check below.
913 */
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500914 return;
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500915 }
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500916
Glenn Randers-Pehrsond9d4cec2010-07-12 07:12:09 -0500917 /* Do we have a complete row? */
918 if (png_ptr->zstream.avail_out == 0)
919 png_push_process_row(png_ptr);
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500920 }
Glenn Randers-Pehrson821b7102010-06-24 16:16:32 -0500921
922 /* And check for the end of the stream. */
923 if (ret == Z_STREAM_END)
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600924 png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
Andreas Dilger47a0c421997-05-16 02:46:07 -0500925 }
Glenn Randers-Pehrson57d96172010-06-19 19:25:17 -0500926
927 /* All the data should have been processed, if anything
928 * is left at this point we have bytes of IDAT data
929 * after the zlib end code.
930 */
931 if (png_ptr->zstream.avail_in > 0)
Glenn Randers-Pehrson5feb87c2010-06-21 12:28:05 -0500932 png_warning(png_ptr, "Extra compression data in IDAT");
Guy Schalnat6d764711995-12-19 03:22:19 -0600933}
934
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -0500935void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -0600936png_push_process_row(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -0600937{
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500938 /* 1.5.6: row_info moved out of png_struct to a local here. */
939 png_row_info row_info;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -0600940
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500941 row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
942 row_info.color_type = png_ptr->color_type;
943 row_info.bit_depth = png_ptr->bit_depth;
944 row_info.channels = png_ptr->channels;
945 row_info.pixel_depth = png_ptr->pixel_depth;
946 row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
Guy Schalnat6d764711995-12-19 03:22:19 -0600947
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500948 if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
949 {
950 if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
Mans Rullgardd3a94802011-11-03 00:47:55 -0500951 png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500952 png_ptr->prev_row + 1, png_ptr->row_buf[0]);
953 else
954 png_error(png_ptr, "bad adaptive filter value");
955 }
Guy Schalnat6d764711995-12-19 03:22:19 -0600956
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500957 /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
958 * 1.5.6, while the buffer really is this big in current versions of libpng
959 * it may not be in the future, so this was changed just to copy the
960 * interlaced row count:
961 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -0600962 memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
Guy Schalnat6d764711995-12-19 03:22:19 -0600963
John Bowler4a12f4a2011-04-17 18:34:22 -0500964#ifdef PNG_READ_TRANSFORMS_SUPPORTED
John Bowler9b872f42011-02-12 09:00:16 -0600965 if (png_ptr->transformations)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500966 png_do_read_transformations(png_ptr, &row_info);
John Bowler4a12f4a2011-04-17 18:34:22 -0500967#endif
Guy Schalnat6d764711995-12-19 03:22:19 -0600968
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500969 /* The transformed pixel depth should match the depth now in row_info. */
970 if (png_ptr->transformed_pixel_depth == 0)
971 {
972 png_ptr->transformed_pixel_depth = row_info.pixel_depth;
973 if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
974 png_error(png_ptr, "progressive row overflow");
975 }
976
977 else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
978 png_error(png_ptr, "internal progressive row size calculation error");
979
980
Glenn Randers-Pehrsone26c0952009-09-23 11:22:08 -0500981#ifdef PNG_READ_INTERLACING_SUPPORTED
Glenn Randers-Pehrsonc4b37182014-04-06 08:59:57 -0500982 /* Expand interlaced rows to full size */
Andreas Dilger47a0c421997-05-16 02:46:07 -0500983 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600984 {
985 if (png_ptr->pass < 6)
Glenn Randers-Pehrsonbb5cb142011-09-22 12:41:58 -0500986 png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
987 png_ptr->transformations);
Guy Schalnat6d764711995-12-19 03:22:19 -0600988
Glenn Randers-Pehrsonc4b37182014-04-06 08:59:57 -0500989 switch (png_ptr->pass)
990 {
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600991 case 0:
992 {
993 int i;
994 for (i = 0; i < 8 && png_ptr->pass == 0; i++)
995 {
996 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -0500997 png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -0600998 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -0500999
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001000 if (png_ptr->pass == 2) /* Pass 1 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001001 {
1002 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1003 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001004 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001005 png_read_push_finish_row(png_ptr);
1006 }
1007 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001008
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001009 if (png_ptr->pass == 4 && png_ptr->height <= 4)
1010 {
1011 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1012 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001013 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsond1e8c862002-06-20 06:54:34 -05001014 png_read_push_finish_row(png_ptr);
1015 }
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001016 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001017
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001018 if (png_ptr->pass == 6 && png_ptr->height <= 4)
1019 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001020 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrson3097f612001-05-07 14:52:45 -05001021 png_read_push_finish_row(png_ptr);
1022 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001023
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001024 break;
1025 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001026
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001027 case 1:
1028 {
1029 int i;
1030 for (i = 0; i < 8 && png_ptr->pass == 1; i++)
1031 {
1032 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1033 png_read_push_finish_row(png_ptr);
1034 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001035
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001036 if (png_ptr->pass == 2) /* Skip top 4 generated rows */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001037 {
1038 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1039 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001040 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001041 png_read_push_finish_row(png_ptr);
1042 }
1043 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001044
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001045 break;
1046 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001047
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001048 case 2:
1049 {
1050 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001051
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001052 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1053 {
1054 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1055 png_read_push_finish_row(png_ptr);
1056 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001057
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001058 for (i = 0; i < 4 && png_ptr->pass == 2; i++)
1059 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001060 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001061 png_read_push_finish_row(png_ptr);
1062 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001063
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001064 if (png_ptr->pass == 4) /* Pass 3 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001065 {
1066 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1067 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001068 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001069 png_read_push_finish_row(png_ptr);
1070 }
1071 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001072
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001073 break;
1074 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001075
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001076 case 3:
1077 {
1078 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001079
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001080 for (i = 0; i < 4 && png_ptr->pass == 3; i++)
1081 {
1082 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1083 png_read_push_finish_row(png_ptr);
1084 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001085
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001086 if (png_ptr->pass == 4) /* Skip top two generated rows */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001087 {
1088 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1089 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001090 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001091 png_read_push_finish_row(png_ptr);
1092 }
1093 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001094
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001095 break;
1096 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001097
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001098 case 4:
1099 {
1100 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001101
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001102 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1103 {
1104 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1105 png_read_push_finish_row(png_ptr);
1106 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001107
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001108 for (i = 0; i < 2 && png_ptr->pass == 4; i++)
1109 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001110 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001111 png_read_push_finish_row(png_ptr);
1112 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001113
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001114 if (png_ptr->pass == 6) /* Pass 5 might be empty */
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001115 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001116 png_push_have_row(png_ptr, NULL);
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001117 png_read_push_finish_row(png_ptr);
1118 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001119
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001120 break;
1121 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001122
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001123 case 5:
1124 {
1125 int i;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001126
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001127 for (i = 0; i < 2 && png_ptr->pass == 5; i++)
1128 {
1129 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1130 png_read_push_finish_row(png_ptr);
1131 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001132
Glenn Randers-Pehrson4bb4d012009-05-20 12:45:29 -05001133 if (png_ptr->pass == 6) /* Skip top generated row */
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001134 {
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001135 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001136 png_read_push_finish_row(png_ptr);
1137 }
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001138
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001139 break;
1140 }
Glenn Randers-Pehrson67439c42010-08-19 07:01:09 -05001141
Glenn Randers-Pehrsonb3edc732010-11-21 14:06:41 -06001142 default:
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001143 case 6:
1144 {
1145 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1146 png_read_push_finish_row(png_ptr);
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001147
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001148 if (png_ptr->pass != 6)
1149 break;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001150
Glenn Randers-Pehrsonbeb572e2006-08-19 13:59:24 -05001151 png_push_have_row(png_ptr, NULL);
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001152 png_read_push_finish_row(png_ptr);
1153 }
1154 }
1155 }
1156 else
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001157 {
1158 png_push_have_row(png_ptr, png_ptr->row_buf + 1);
1159 png_read_push_finish_row(png_ptr);
1160 }
Guy Schalnat6d764711995-12-19 03:22:19 -06001161}
1162
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001163void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001164png_read_push_finish_row(png_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001165{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001166 /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001167
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001168 /* Start of interlace block */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001169 static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001170
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001171 /* Offset to next interlace block */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001172 static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001173
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001174 /* Start of interlace block in the y direction */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001175 static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001176
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001177 /* Offset to next interlace block in the y direction */
John Bowlerbaeb6d12011-11-26 18:21:02 -06001178 static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001179
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06001180 /* Height of interlace block. This is not currently used - if you need
1181 * it, uncomment it here and in png.h
John Bowlerbaeb6d12011-11-26 18:21:02 -06001182 static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
Glenn Randers-Pehrson5379b241999-11-27 10:22:33 -06001183 */
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001184#endif
Glenn Randers-Pehrson166c5a31999-12-10 09:43:02 -06001185
Guy Schalnat6d764711995-12-19 03:22:19 -06001186 png_ptr->row_number++;
1187 if (png_ptr->row_number < png_ptr->num_rows)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001188 return;
Guy Schalnat6d764711995-12-19 03:22:19 -06001189
1190 if (png_ptr->interlaced)
1191 {
1192 png_ptr->row_number = 0;
Glenn Randers-Pehrson871b1d02013-03-02 14:58:22 -06001193 memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001194
Guy Schalnat6d764711995-12-19 03:22:19 -06001195 do
1196 {
1197 png_ptr->pass++;
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001198 if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
1199 (png_ptr->pass == 3 && png_ptr->width < 3) ||
1200 (png_ptr->pass == 5 && png_ptr->width < 2))
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001201 png_ptr->pass++;
Glenn Randers-Pehrsoncdf140b2001-01-15 12:22:32 -06001202
Glenn Randers-Pehrson859665d2002-08-06 18:06:11 -05001203 if (png_ptr->pass > 7)
1204 png_ptr->pass--;
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001205
Guy Schalnat6d764711995-12-19 03:22:19 -06001206 if (png_ptr->pass >= 7)
1207 break;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001208
Guy Schalnat6d764711995-12-19 03:22:19 -06001209 png_ptr->iwidth = (png_ptr->width +
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001210 png_pass_inc[png_ptr->pass] - 1 -
1211 png_pass_start[png_ptr->pass]) /
1212 png_pass_inc[png_ptr->pass];
Glenn Randers-Pehrson08a33431998-03-07 06:06:55 -06001213
Guy Schalnat6d764711995-12-19 03:22:19 -06001214 if (png_ptr->transformations & PNG_INTERLACE)
1215 break;
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001216
1217 png_ptr->num_rows = (png_ptr->height +
Glenn Randers-Pehrsonf24daf22010-05-06 09:44:04 -05001218 png_pass_yinc[png_ptr->pass] - 1 -
1219 png_pass_ystart[png_ptr->pass]) /
1220 png_pass_yinc[png_ptr->pass];
Glenn Randers-Pehrson5c6aeb21998-12-29 11:47:59 -06001221
1222 } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
Guy Schalnat6d764711995-12-19 03:22:19 -06001223 }
1224}
1225
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001226void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001227png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001228{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001229 if (png_ptr->info_fn != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001230 (*(png_ptr->info_fn))(png_ptr, info_ptr);
1231}
1232
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001233void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001234png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001235{
Andreas Dilger47a0c421997-05-16 02:46:07 -05001236 if (png_ptr->end_fn != NULL)
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001237 (*(png_ptr->end_fn))(png_ptr, info_ptr);
Guy Schalnat6d764711995-12-19 03:22:19 -06001238}
1239
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001240void /* PRIVATE */
John Bowler5d567862011-12-24 09:12:00 -06001241png_push_have_row(png_structrp png_ptr, png_bytep row)
Guy Schalnat6d764711995-12-19 03:22:19 -06001242{
Glenn Randers-Pehrson78d55452010-06-19 07:03:50 -05001243 if (png_ptr->row_fn != NULL)
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001244 (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
1245 (int)png_ptr->pass);
Guy Schalnat6d764711995-12-19 03:22:19 -06001246}
1247
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001248void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001249png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
Glenn Randers-Pehrsone600c512010-08-18 07:25:46 -05001250 png_const_bytep new_row)
Guy Schalnat6d764711995-12-19 03:22:19 -06001251{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001252 if (png_ptr == NULL)
1253 return;
1254
Glenn Randers-Pehrson4daae302011-10-06 21:37:47 -05001255 /* new_row is a flag here - if it is NULL then the app callback was called
1256 * from an empty row (see the calls to png_struct::row_fn below), otherwise
1257 * it must be png_ptr->row_buf+1
1258 */
1259 if (new_row != NULL)
Glenn Randers-Pehrson72855fb2014-04-13 21:27:25 -05001260 png_combine_row(png_ptr, old_row, 1/*blocky display*/);
Guy Schalnat6d764711995-12-19 03:22:19 -06001261}
1262
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001263void PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001264png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
Glenn Randers-Pehrson262d0ff2010-03-03 07:06:54 -06001265 png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
1266 png_progressive_end_ptr end_fn)
Guy Schalnat6d764711995-12-19 03:22:19 -06001267{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001268 if (png_ptr == NULL)
1269 return;
1270
Guy Schalnatb2e01bd1996-01-26 01:38:47 -06001271 png_ptr->info_fn = info_fn;
1272 png_ptr->row_fn = row_fn;
Guy Schalnat6d764711995-12-19 03:22:19 -06001273 png_ptr->end_fn = end_fn;
Guy Schalnate5a37791996-06-05 15:50:50 -05001274
Glenn Randers-Pehrson25d82242002-05-01 11:51:26 -05001275 png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
Guy Schalnat6d764711995-12-19 03:22:19 -06001276}
1277
Glenn Randers-Pehrson75294572000-05-06 14:09:57 -05001278png_voidp PNGAPI
John Bowler5d567862011-12-24 09:12:00 -06001279png_get_progressive_ptr(png_const_structrp png_ptr)
Guy Schalnat6d764711995-12-19 03:22:19 -06001280{
Glenn Randers-Pehrson glennrp@comcast.netb1c0d332009-05-15 20:39:34 -05001281 if (png_ptr == NULL)
1282 return (NULL);
1283
Andreas Dilger02ad0ef1997-01-17 01:34:35 -06001284 return png_ptr->io_ptr;
Guy Schalnat6d764711995-12-19 03:22:19 -06001285}
Guy Schalnat4ee97b01996-01-16 01:51:56 -06001286#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */