1*a67afe4dSAndroid Build Coastguard Worker
2*a67afe4dSAndroid Build Coastguard Worker /* pngpread.c - read a png file in push mode
3*a67afe4dSAndroid Build Coastguard Worker *
4*a67afe4dSAndroid Build Coastguard Worker * Copyright (c) 2018-2024 Cosmin Truta
5*a67afe4dSAndroid Build Coastguard Worker * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
6*a67afe4dSAndroid Build Coastguard Worker * Copyright (c) 1996-1997 Andreas Dilger
7*a67afe4dSAndroid Build Coastguard Worker * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
8*a67afe4dSAndroid Build Coastguard Worker *
9*a67afe4dSAndroid Build Coastguard Worker * This code is released under the libpng license.
10*a67afe4dSAndroid Build Coastguard Worker * For conditions of distribution and use, see the disclaimer
11*a67afe4dSAndroid Build Coastguard Worker * and license in png.h
12*a67afe4dSAndroid Build Coastguard Worker */
13*a67afe4dSAndroid Build Coastguard Worker
14*a67afe4dSAndroid Build Coastguard Worker #include "pngpriv.h"
15*a67afe4dSAndroid Build Coastguard Worker
16*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_PROGRESSIVE_READ_SUPPORTED
17*a67afe4dSAndroid Build Coastguard Worker
18*a67afe4dSAndroid Build Coastguard Worker /* Push model modes */
19*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_SIG_MODE 0
20*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_CHUNK_MODE 1
21*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_IDAT_MODE 2
22*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_tEXt_MODE 4
23*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_zTXt_MODE 5
24*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_DONE_MODE 6
25*a67afe4dSAndroid Build Coastguard Worker #define PNG_READ_iTXt_MODE 7
26*a67afe4dSAndroid Build Coastguard Worker #define PNG_ERROR_MODE 8
27*a67afe4dSAndroid Build Coastguard Worker
28*a67afe4dSAndroid Build Coastguard Worker #define PNG_PUSH_SAVE_BUFFER_IF_FULL \
29*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
30*a67afe4dSAndroid Build Coastguard Worker { png_push_save_buffer(png_ptr); return; }
31*a67afe4dSAndroid Build Coastguard Worker #define PNG_PUSH_SAVE_BUFFER_IF_LT(N) \
32*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->buffer_size < N) \
33*a67afe4dSAndroid Build Coastguard Worker { png_push_save_buffer(png_ptr); return; }
34*a67afe4dSAndroid Build Coastguard Worker
35*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_process_data(png_structrp png_ptr,png_inforp info_ptr,png_bytep buffer,size_t buffer_size)36*a67afe4dSAndroid Build Coastguard Worker png_process_data(png_structrp png_ptr, png_inforp info_ptr,
37*a67afe4dSAndroid Build Coastguard Worker png_bytep buffer, size_t buffer_size)
38*a67afe4dSAndroid Build Coastguard Worker {
39*a67afe4dSAndroid Build Coastguard Worker if (png_ptr == NULL || info_ptr == NULL)
40*a67afe4dSAndroid Build Coastguard Worker return;
41*a67afe4dSAndroid Build Coastguard Worker
42*a67afe4dSAndroid Build Coastguard Worker png_push_restore_buffer(png_ptr, buffer, buffer_size);
43*a67afe4dSAndroid Build Coastguard Worker
44*a67afe4dSAndroid Build Coastguard Worker while (png_ptr->buffer_size)
45*a67afe4dSAndroid Build Coastguard Worker {
46*a67afe4dSAndroid Build Coastguard Worker png_process_some_data(png_ptr, info_ptr);
47*a67afe4dSAndroid Build Coastguard Worker }
48*a67afe4dSAndroid Build Coastguard Worker }
49*a67afe4dSAndroid Build Coastguard Worker
50*a67afe4dSAndroid Build Coastguard Worker size_t PNGAPI
png_process_data_pause(png_structrp png_ptr,int save)51*a67afe4dSAndroid Build Coastguard Worker png_process_data_pause(png_structrp png_ptr, int save)
52*a67afe4dSAndroid Build Coastguard Worker {
53*a67afe4dSAndroid Build Coastguard Worker if (png_ptr != NULL)
54*a67afe4dSAndroid Build Coastguard Worker {
55*a67afe4dSAndroid Build Coastguard Worker /* It's easiest for the caller if we do the save; then the caller doesn't
56*a67afe4dSAndroid Build Coastguard Worker * have to supply the same data again:
57*a67afe4dSAndroid Build Coastguard Worker */
58*a67afe4dSAndroid Build Coastguard Worker if (save != 0)
59*a67afe4dSAndroid Build Coastguard Worker png_push_save_buffer(png_ptr);
60*a67afe4dSAndroid Build Coastguard Worker else
61*a67afe4dSAndroid Build Coastguard Worker {
62*a67afe4dSAndroid Build Coastguard Worker /* This includes any pending saved bytes: */
63*a67afe4dSAndroid Build Coastguard Worker size_t remaining = png_ptr->buffer_size;
64*a67afe4dSAndroid Build Coastguard Worker png_ptr->buffer_size = 0;
65*a67afe4dSAndroid Build Coastguard Worker
66*a67afe4dSAndroid Build Coastguard Worker /* So subtract the saved buffer size, unless all the data
67*a67afe4dSAndroid Build Coastguard Worker * is actually 'saved', in which case we just return 0
68*a67afe4dSAndroid Build Coastguard Worker */
69*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->save_buffer_size < remaining)
70*a67afe4dSAndroid Build Coastguard Worker return remaining - png_ptr->save_buffer_size;
71*a67afe4dSAndroid Build Coastguard Worker }
72*a67afe4dSAndroid Build Coastguard Worker }
73*a67afe4dSAndroid Build Coastguard Worker
74*a67afe4dSAndroid Build Coastguard Worker return 0;
75*a67afe4dSAndroid Build Coastguard Worker }
76*a67afe4dSAndroid Build Coastguard Worker
77*a67afe4dSAndroid Build Coastguard Worker png_uint_32 PNGAPI
png_process_data_skip(png_structrp png_ptr)78*a67afe4dSAndroid Build Coastguard Worker png_process_data_skip(png_structrp png_ptr)
79*a67afe4dSAndroid Build Coastguard Worker {
80*a67afe4dSAndroid Build Coastguard Worker /* TODO: Deprecate and remove this API.
81*a67afe4dSAndroid Build Coastguard Worker * Somewhere the implementation of this seems to have been lost,
82*a67afe4dSAndroid Build Coastguard Worker * or abandoned. It was only to support some internal back-door access
83*a67afe4dSAndroid Build Coastguard Worker * to png_struct) in libpng-1.4.x.
84*a67afe4dSAndroid Build Coastguard Worker */
85*a67afe4dSAndroid Build Coastguard Worker png_app_warning(png_ptr,
86*a67afe4dSAndroid Build Coastguard Worker "png_process_data_skip is not implemented in any current version of libpng");
87*a67afe4dSAndroid Build Coastguard Worker return 0;
88*a67afe4dSAndroid Build Coastguard Worker }
89*a67afe4dSAndroid Build Coastguard Worker
90*a67afe4dSAndroid Build Coastguard Worker /* What we do with the incoming data depends on what we were previously
91*a67afe4dSAndroid Build Coastguard Worker * doing before we ran out of data...
92*a67afe4dSAndroid Build Coastguard Worker */
93*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_process_some_data(png_structrp png_ptr,png_inforp info_ptr)94*a67afe4dSAndroid Build Coastguard Worker png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
95*a67afe4dSAndroid Build Coastguard Worker {
96*a67afe4dSAndroid Build Coastguard Worker if (png_ptr == NULL)
97*a67afe4dSAndroid Build Coastguard Worker return;
98*a67afe4dSAndroid Build Coastguard Worker
99*a67afe4dSAndroid Build Coastguard Worker switch (png_ptr->process_mode)
100*a67afe4dSAndroid Build Coastguard Worker {
101*a67afe4dSAndroid Build Coastguard Worker case PNG_READ_SIG_MODE:
102*a67afe4dSAndroid Build Coastguard Worker {
103*a67afe4dSAndroid Build Coastguard Worker png_push_read_sig(png_ptr, info_ptr);
104*a67afe4dSAndroid Build Coastguard Worker break;
105*a67afe4dSAndroid Build Coastguard Worker }
106*a67afe4dSAndroid Build Coastguard Worker
107*a67afe4dSAndroid Build Coastguard Worker case PNG_READ_CHUNK_MODE:
108*a67afe4dSAndroid Build Coastguard Worker {
109*a67afe4dSAndroid Build Coastguard Worker png_push_read_chunk(png_ptr, info_ptr);
110*a67afe4dSAndroid Build Coastguard Worker break;
111*a67afe4dSAndroid Build Coastguard Worker }
112*a67afe4dSAndroid Build Coastguard Worker
113*a67afe4dSAndroid Build Coastguard Worker case PNG_READ_IDAT_MODE:
114*a67afe4dSAndroid Build Coastguard Worker {
115*a67afe4dSAndroid Build Coastguard Worker png_push_read_IDAT(png_ptr);
116*a67afe4dSAndroid Build Coastguard Worker break;
117*a67afe4dSAndroid Build Coastguard Worker }
118*a67afe4dSAndroid Build Coastguard Worker
119*a67afe4dSAndroid Build Coastguard Worker default:
120*a67afe4dSAndroid Build Coastguard Worker {
121*a67afe4dSAndroid Build Coastguard Worker png_ptr->buffer_size = 0;
122*a67afe4dSAndroid Build Coastguard Worker break;
123*a67afe4dSAndroid Build Coastguard Worker }
124*a67afe4dSAndroid Build Coastguard Worker }
125*a67afe4dSAndroid Build Coastguard Worker }
126*a67afe4dSAndroid Build Coastguard Worker
127*a67afe4dSAndroid Build Coastguard Worker /* Read any remaining signature bytes from the stream and compare them with
128*a67afe4dSAndroid Build Coastguard Worker * the correct PNG signature. It is possible that this routine is called
129*a67afe4dSAndroid Build Coastguard Worker * with bytes already read from the signature, either because they have been
130*a67afe4dSAndroid Build Coastguard Worker * checked by the calling application, or because of multiple calls to this
131*a67afe4dSAndroid Build Coastguard Worker * routine.
132*a67afe4dSAndroid Build Coastguard Worker */
133*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_read_sig(png_structrp png_ptr,png_inforp info_ptr)134*a67afe4dSAndroid Build Coastguard Worker png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
135*a67afe4dSAndroid Build Coastguard Worker {
136*a67afe4dSAndroid Build Coastguard Worker size_t num_checked = png_ptr->sig_bytes; /* SAFE, does not exceed 8 */
137*a67afe4dSAndroid Build Coastguard Worker size_t num_to_check = 8 - num_checked;
138*a67afe4dSAndroid Build Coastguard Worker
139*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->buffer_size < num_to_check)
140*a67afe4dSAndroid Build Coastguard Worker {
141*a67afe4dSAndroid Build Coastguard Worker num_to_check = png_ptr->buffer_size;
142*a67afe4dSAndroid Build Coastguard Worker }
143*a67afe4dSAndroid Build Coastguard Worker
144*a67afe4dSAndroid Build Coastguard Worker png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
145*a67afe4dSAndroid Build Coastguard Worker num_to_check);
146*a67afe4dSAndroid Build Coastguard Worker png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
147*a67afe4dSAndroid Build Coastguard Worker
148*a67afe4dSAndroid Build Coastguard Worker if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
149*a67afe4dSAndroid Build Coastguard Worker {
150*a67afe4dSAndroid Build Coastguard Worker if (num_checked < 4 &&
151*a67afe4dSAndroid Build Coastguard Worker png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0)
152*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Not a PNG file");
153*a67afe4dSAndroid Build Coastguard Worker
154*a67afe4dSAndroid Build Coastguard Worker else
155*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "PNG file corrupted by ASCII conversion");
156*a67afe4dSAndroid Build Coastguard Worker }
157*a67afe4dSAndroid Build Coastguard Worker else
158*a67afe4dSAndroid Build Coastguard Worker {
159*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->sig_bytes >= 8)
160*a67afe4dSAndroid Build Coastguard Worker {
161*a67afe4dSAndroid Build Coastguard Worker png_ptr->process_mode = PNG_READ_CHUNK_MODE;
162*a67afe4dSAndroid Build Coastguard Worker }
163*a67afe4dSAndroid Build Coastguard Worker }
164*a67afe4dSAndroid Build Coastguard Worker }
165*a67afe4dSAndroid Build Coastguard Worker
166*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_read_chunk(png_structrp png_ptr,png_inforp info_ptr)167*a67afe4dSAndroid Build Coastguard Worker png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
168*a67afe4dSAndroid Build Coastguard Worker {
169*a67afe4dSAndroid Build Coastguard Worker png_uint_32 chunk_name;
170*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
171*a67afe4dSAndroid Build Coastguard Worker int keep; /* unknown handling method */
172*a67afe4dSAndroid Build Coastguard Worker #endif
173*a67afe4dSAndroid Build Coastguard Worker
174*a67afe4dSAndroid Build Coastguard Worker /* First we make sure we have enough data for the 4-byte chunk name
175*a67afe4dSAndroid Build Coastguard Worker * and the 4-byte chunk length before proceeding with decoding the
176*a67afe4dSAndroid Build Coastguard Worker * chunk data. To fully decode each of these chunks, we also make
177*a67afe4dSAndroid Build Coastguard Worker * sure we have enough data in the buffer for the 4-byte CRC at the
178*a67afe4dSAndroid Build Coastguard Worker * end of every chunk (except IDAT, which is handled separately).
179*a67afe4dSAndroid Build Coastguard Worker */
180*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
181*a67afe4dSAndroid Build Coastguard Worker {
182*a67afe4dSAndroid Build Coastguard Worker png_byte chunk_length[4];
183*a67afe4dSAndroid Build Coastguard Worker png_byte chunk_tag[4];
184*a67afe4dSAndroid Build Coastguard Worker
185*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_LT(8)
186*a67afe4dSAndroid Build Coastguard Worker png_push_fill_buffer(png_ptr, chunk_length, 4);
187*a67afe4dSAndroid Build Coastguard Worker png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
188*a67afe4dSAndroid Build Coastguard Worker png_reset_crc(png_ptr);
189*a67afe4dSAndroid Build Coastguard Worker png_crc_read(png_ptr, chunk_tag, 4);
190*a67afe4dSAndroid Build Coastguard Worker png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
191*a67afe4dSAndroid Build Coastguard Worker png_check_chunk_name(png_ptr, png_ptr->chunk_name);
192*a67afe4dSAndroid Build Coastguard Worker png_check_chunk_length(png_ptr, png_ptr->push_length);
193*a67afe4dSAndroid Build Coastguard Worker png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
194*a67afe4dSAndroid Build Coastguard Worker }
195*a67afe4dSAndroid Build Coastguard Worker
196*a67afe4dSAndroid Build Coastguard Worker chunk_name = png_ptr->chunk_name;
197*a67afe4dSAndroid Build Coastguard Worker
198*a67afe4dSAndroid Build Coastguard Worker if (chunk_name == png_IDAT)
199*a67afe4dSAndroid Build Coastguard Worker {
200*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
201*a67afe4dSAndroid Build Coastguard Worker png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
202*a67afe4dSAndroid Build Coastguard Worker
203*a67afe4dSAndroid Build Coastguard Worker /* If we reach an IDAT chunk, this means we have read all of the
204*a67afe4dSAndroid Build Coastguard Worker * header chunks, and we can start reading the image (or if this
205*a67afe4dSAndroid Build Coastguard Worker * is called after the image has been read - we have an error).
206*a67afe4dSAndroid Build Coastguard Worker */
207*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
208*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Missing IHDR before IDAT");
209*a67afe4dSAndroid Build Coastguard Worker
210*a67afe4dSAndroid Build Coastguard Worker else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
211*a67afe4dSAndroid Build Coastguard Worker (png_ptr->mode & PNG_HAVE_PLTE) == 0)
212*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Missing PLTE before IDAT");
213*a67afe4dSAndroid Build Coastguard Worker
214*a67afe4dSAndroid Build Coastguard Worker png_ptr->process_mode = PNG_READ_IDAT_MODE;
215*a67afe4dSAndroid Build Coastguard Worker
216*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
217*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
218*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->push_length == 0)
219*a67afe4dSAndroid Build Coastguard Worker return;
220*a67afe4dSAndroid Build Coastguard Worker
221*a67afe4dSAndroid Build Coastguard Worker png_ptr->mode |= PNG_HAVE_IDAT;
222*a67afe4dSAndroid Build Coastguard Worker
223*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
224*a67afe4dSAndroid Build Coastguard Worker png_benign_error(png_ptr, "Too many IDATs found");
225*a67afe4dSAndroid Build Coastguard Worker }
226*a67afe4dSAndroid Build Coastguard Worker
227*a67afe4dSAndroid Build Coastguard Worker if (chunk_name == png_IHDR)
228*a67afe4dSAndroid Build Coastguard Worker {
229*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->push_length != 13)
230*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Invalid IHDR length");
231*a67afe4dSAndroid Build Coastguard Worker
232*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
233*a67afe4dSAndroid Build Coastguard Worker png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
234*a67afe4dSAndroid Build Coastguard Worker }
235*a67afe4dSAndroid Build Coastguard Worker
236*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_IEND)
237*a67afe4dSAndroid Build Coastguard Worker {
238*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
239*a67afe4dSAndroid Build Coastguard Worker png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
240*a67afe4dSAndroid Build Coastguard Worker
241*a67afe4dSAndroid Build Coastguard Worker png_ptr->process_mode = PNG_READ_DONE_MODE;
242*a67afe4dSAndroid Build Coastguard Worker png_push_have_end(png_ptr, info_ptr);
243*a67afe4dSAndroid Build Coastguard Worker }
244*a67afe4dSAndroid Build Coastguard Worker
245*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
246*a67afe4dSAndroid Build Coastguard Worker else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
247*a67afe4dSAndroid Build Coastguard Worker {
248*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
249*a67afe4dSAndroid Build Coastguard Worker png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
250*a67afe4dSAndroid Build Coastguard Worker
251*a67afe4dSAndroid Build Coastguard Worker if (chunk_name == png_PLTE)
252*a67afe4dSAndroid Build Coastguard Worker png_ptr->mode |= PNG_HAVE_PLTE;
253*a67afe4dSAndroid Build Coastguard Worker }
254*a67afe4dSAndroid Build Coastguard Worker #endif
255*a67afe4dSAndroid Build Coastguard Worker
256*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_PLTE)
257*a67afe4dSAndroid Build Coastguard Worker {
258*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
259*a67afe4dSAndroid Build Coastguard Worker png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
260*a67afe4dSAndroid Build Coastguard Worker }
261*a67afe4dSAndroid Build Coastguard Worker
262*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_IDAT)
263*a67afe4dSAndroid Build Coastguard Worker {
264*a67afe4dSAndroid Build Coastguard Worker png_ptr->idat_size = png_ptr->push_length;
265*a67afe4dSAndroid Build Coastguard Worker png_ptr->process_mode = PNG_READ_IDAT_MODE;
266*a67afe4dSAndroid Build Coastguard Worker png_push_have_info(png_ptr, info_ptr);
267*a67afe4dSAndroid Build Coastguard Worker png_ptr->zstream.avail_out =
268*a67afe4dSAndroid Build Coastguard Worker (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
269*a67afe4dSAndroid Build Coastguard Worker png_ptr->iwidth) + 1;
270*a67afe4dSAndroid Build Coastguard Worker png_ptr->zstream.next_out = png_ptr->row_buf;
271*a67afe4dSAndroid Build Coastguard Worker return;
272*a67afe4dSAndroid Build Coastguard Worker }
273*a67afe4dSAndroid Build Coastguard Worker
274*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_gAMA_SUPPORTED
275*a67afe4dSAndroid Build Coastguard Worker else if (png_ptr->chunk_name == png_gAMA)
276*a67afe4dSAndroid Build Coastguard Worker {
277*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
278*a67afe4dSAndroid Build Coastguard Worker png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
279*a67afe4dSAndroid Build Coastguard Worker }
280*a67afe4dSAndroid Build Coastguard Worker
281*a67afe4dSAndroid Build Coastguard Worker #endif
282*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_sBIT_SUPPORTED
283*a67afe4dSAndroid Build Coastguard Worker else if (png_ptr->chunk_name == png_sBIT)
284*a67afe4dSAndroid Build Coastguard Worker {
285*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
286*a67afe4dSAndroid Build Coastguard Worker png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
287*a67afe4dSAndroid Build Coastguard Worker }
288*a67afe4dSAndroid Build Coastguard Worker
289*a67afe4dSAndroid Build Coastguard Worker #endif
290*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_cHRM_SUPPORTED
291*a67afe4dSAndroid Build Coastguard Worker else if (png_ptr->chunk_name == png_cHRM)
292*a67afe4dSAndroid Build Coastguard Worker {
293*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
294*a67afe4dSAndroid Build Coastguard Worker png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
295*a67afe4dSAndroid Build Coastguard Worker }
296*a67afe4dSAndroid Build Coastguard Worker
297*a67afe4dSAndroid Build Coastguard Worker #endif
298*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_eXIf_SUPPORTED
299*a67afe4dSAndroid Build Coastguard Worker else if (png_ptr->chunk_name == png_eXIf)
300*a67afe4dSAndroid Build Coastguard Worker {
301*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
302*a67afe4dSAndroid Build Coastguard Worker png_handle_eXIf(png_ptr, info_ptr, png_ptr->push_length);
303*a67afe4dSAndroid Build Coastguard Worker }
304*a67afe4dSAndroid Build Coastguard Worker
305*a67afe4dSAndroid Build Coastguard Worker #endif
306*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_sRGB_SUPPORTED
307*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_sRGB)
308*a67afe4dSAndroid Build Coastguard Worker {
309*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
310*a67afe4dSAndroid Build Coastguard Worker png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
311*a67afe4dSAndroid Build Coastguard Worker }
312*a67afe4dSAndroid Build Coastguard Worker
313*a67afe4dSAndroid Build Coastguard Worker #endif
314*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_iCCP_SUPPORTED
315*a67afe4dSAndroid Build Coastguard Worker else if (png_ptr->chunk_name == png_iCCP)
316*a67afe4dSAndroid Build Coastguard Worker {
317*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
318*a67afe4dSAndroid Build Coastguard Worker png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
319*a67afe4dSAndroid Build Coastguard Worker }
320*a67afe4dSAndroid Build Coastguard Worker
321*a67afe4dSAndroid Build Coastguard Worker #endif
322*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_sPLT_SUPPORTED
323*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_sPLT)
324*a67afe4dSAndroid Build Coastguard Worker {
325*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
326*a67afe4dSAndroid Build Coastguard Worker png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
327*a67afe4dSAndroid Build Coastguard Worker }
328*a67afe4dSAndroid Build Coastguard Worker
329*a67afe4dSAndroid Build Coastguard Worker #endif
330*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_tRNS_SUPPORTED
331*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_tRNS)
332*a67afe4dSAndroid Build Coastguard Worker {
333*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
334*a67afe4dSAndroid Build Coastguard Worker png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
335*a67afe4dSAndroid Build Coastguard Worker }
336*a67afe4dSAndroid Build Coastguard Worker
337*a67afe4dSAndroid Build Coastguard Worker #endif
338*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_bKGD_SUPPORTED
339*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_bKGD)
340*a67afe4dSAndroid Build Coastguard Worker {
341*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
342*a67afe4dSAndroid Build Coastguard Worker png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
343*a67afe4dSAndroid Build Coastguard Worker }
344*a67afe4dSAndroid Build Coastguard Worker
345*a67afe4dSAndroid Build Coastguard Worker #endif
346*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_hIST_SUPPORTED
347*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_hIST)
348*a67afe4dSAndroid Build Coastguard Worker {
349*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
350*a67afe4dSAndroid Build Coastguard Worker png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
351*a67afe4dSAndroid Build Coastguard Worker }
352*a67afe4dSAndroid Build Coastguard Worker
353*a67afe4dSAndroid Build Coastguard Worker #endif
354*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_pHYs_SUPPORTED
355*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_pHYs)
356*a67afe4dSAndroid Build Coastguard Worker {
357*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
358*a67afe4dSAndroid Build Coastguard Worker png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
359*a67afe4dSAndroid Build Coastguard Worker }
360*a67afe4dSAndroid Build Coastguard Worker
361*a67afe4dSAndroid Build Coastguard Worker #endif
362*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_oFFs_SUPPORTED
363*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_oFFs)
364*a67afe4dSAndroid Build Coastguard Worker {
365*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
366*a67afe4dSAndroid Build Coastguard Worker png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
367*a67afe4dSAndroid Build Coastguard Worker }
368*a67afe4dSAndroid Build Coastguard Worker #endif
369*a67afe4dSAndroid Build Coastguard Worker
370*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_pCAL_SUPPORTED
371*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_pCAL)
372*a67afe4dSAndroid Build Coastguard Worker {
373*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
374*a67afe4dSAndroid Build Coastguard Worker png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
375*a67afe4dSAndroid Build Coastguard Worker }
376*a67afe4dSAndroid Build Coastguard Worker
377*a67afe4dSAndroid Build Coastguard Worker #endif
378*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_sCAL_SUPPORTED
379*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_sCAL)
380*a67afe4dSAndroid Build Coastguard Worker {
381*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
382*a67afe4dSAndroid Build Coastguard Worker png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
383*a67afe4dSAndroid Build Coastguard Worker }
384*a67afe4dSAndroid Build Coastguard Worker
385*a67afe4dSAndroid Build Coastguard Worker #endif
386*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_tIME_SUPPORTED
387*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_tIME)
388*a67afe4dSAndroid Build Coastguard Worker {
389*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
390*a67afe4dSAndroid Build Coastguard Worker png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
391*a67afe4dSAndroid Build Coastguard Worker }
392*a67afe4dSAndroid Build Coastguard Worker
393*a67afe4dSAndroid Build Coastguard Worker #endif
394*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_tEXt_SUPPORTED
395*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_tEXt)
396*a67afe4dSAndroid Build Coastguard Worker {
397*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
398*a67afe4dSAndroid Build Coastguard Worker png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
399*a67afe4dSAndroid Build Coastguard Worker }
400*a67afe4dSAndroid Build Coastguard Worker
401*a67afe4dSAndroid Build Coastguard Worker #endif
402*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_zTXt_SUPPORTED
403*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_zTXt)
404*a67afe4dSAndroid Build Coastguard Worker {
405*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
406*a67afe4dSAndroid Build Coastguard Worker png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
407*a67afe4dSAndroid Build Coastguard Worker }
408*a67afe4dSAndroid Build Coastguard Worker
409*a67afe4dSAndroid Build Coastguard Worker #endif
410*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_iTXt_SUPPORTED
411*a67afe4dSAndroid Build Coastguard Worker else if (chunk_name == png_iTXt)
412*a67afe4dSAndroid Build Coastguard Worker {
413*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
414*a67afe4dSAndroid Build Coastguard Worker png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
415*a67afe4dSAndroid Build Coastguard Worker }
416*a67afe4dSAndroid Build Coastguard Worker #endif
417*a67afe4dSAndroid Build Coastguard Worker
418*a67afe4dSAndroid Build Coastguard Worker else
419*a67afe4dSAndroid Build Coastguard Worker {
420*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_FULL
421*a67afe4dSAndroid Build Coastguard Worker png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
422*a67afe4dSAndroid Build Coastguard Worker PNG_HANDLE_CHUNK_AS_DEFAULT);
423*a67afe4dSAndroid Build Coastguard Worker }
424*a67afe4dSAndroid Build Coastguard Worker
425*a67afe4dSAndroid Build Coastguard Worker png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
426*a67afe4dSAndroid Build Coastguard Worker }
427*a67afe4dSAndroid Build Coastguard Worker
428*a67afe4dSAndroid Build Coastguard Worker void PNGCBAPI
png_push_fill_buffer(png_structp png_ptr,png_bytep buffer,size_t length)429*a67afe4dSAndroid Build Coastguard Worker png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, size_t length)
430*a67afe4dSAndroid Build Coastguard Worker {
431*a67afe4dSAndroid Build Coastguard Worker png_bytep ptr;
432*a67afe4dSAndroid Build Coastguard Worker
433*a67afe4dSAndroid Build Coastguard Worker if (png_ptr == NULL)
434*a67afe4dSAndroid Build Coastguard Worker return;
435*a67afe4dSAndroid Build Coastguard Worker
436*a67afe4dSAndroid Build Coastguard Worker ptr = buffer;
437*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->save_buffer_size != 0)
438*a67afe4dSAndroid Build Coastguard Worker {
439*a67afe4dSAndroid Build Coastguard Worker size_t save_size;
440*a67afe4dSAndroid Build Coastguard Worker
441*a67afe4dSAndroid Build Coastguard Worker if (length < png_ptr->save_buffer_size)
442*a67afe4dSAndroid Build Coastguard Worker save_size = length;
443*a67afe4dSAndroid Build Coastguard Worker
444*a67afe4dSAndroid Build Coastguard Worker else
445*a67afe4dSAndroid Build Coastguard Worker save_size = png_ptr->save_buffer_size;
446*a67afe4dSAndroid Build Coastguard Worker
447*a67afe4dSAndroid Build Coastguard Worker memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
448*a67afe4dSAndroid Build Coastguard Worker length -= save_size;
449*a67afe4dSAndroid Build Coastguard Worker ptr += save_size;
450*a67afe4dSAndroid Build Coastguard Worker png_ptr->buffer_size -= save_size;
451*a67afe4dSAndroid Build Coastguard Worker png_ptr->save_buffer_size -= save_size;
452*a67afe4dSAndroid Build Coastguard Worker png_ptr->save_buffer_ptr += save_size;
453*a67afe4dSAndroid Build Coastguard Worker }
454*a67afe4dSAndroid Build Coastguard Worker if (length != 0 && png_ptr->current_buffer_size != 0)
455*a67afe4dSAndroid Build Coastguard Worker {
456*a67afe4dSAndroid Build Coastguard Worker size_t save_size;
457*a67afe4dSAndroid Build Coastguard Worker
458*a67afe4dSAndroid Build Coastguard Worker if (length < png_ptr->current_buffer_size)
459*a67afe4dSAndroid Build Coastguard Worker save_size = length;
460*a67afe4dSAndroid Build Coastguard Worker
461*a67afe4dSAndroid Build Coastguard Worker else
462*a67afe4dSAndroid Build Coastguard Worker save_size = png_ptr->current_buffer_size;
463*a67afe4dSAndroid Build Coastguard Worker
464*a67afe4dSAndroid Build Coastguard Worker memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
465*a67afe4dSAndroid Build Coastguard Worker png_ptr->buffer_size -= save_size;
466*a67afe4dSAndroid Build Coastguard Worker png_ptr->current_buffer_size -= save_size;
467*a67afe4dSAndroid Build Coastguard Worker png_ptr->current_buffer_ptr += save_size;
468*a67afe4dSAndroid Build Coastguard Worker }
469*a67afe4dSAndroid Build Coastguard Worker }
470*a67afe4dSAndroid Build Coastguard Worker
471*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_save_buffer(png_structrp png_ptr)472*a67afe4dSAndroid Build Coastguard Worker png_push_save_buffer(png_structrp png_ptr)
473*a67afe4dSAndroid Build Coastguard Worker {
474*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->save_buffer_size != 0)
475*a67afe4dSAndroid Build Coastguard Worker {
476*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
477*a67afe4dSAndroid Build Coastguard Worker {
478*a67afe4dSAndroid Build Coastguard Worker size_t i, istop;
479*a67afe4dSAndroid Build Coastguard Worker png_bytep sp;
480*a67afe4dSAndroid Build Coastguard Worker png_bytep dp;
481*a67afe4dSAndroid Build Coastguard Worker
482*a67afe4dSAndroid Build Coastguard Worker istop = png_ptr->save_buffer_size;
483*a67afe4dSAndroid Build Coastguard Worker for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
484*a67afe4dSAndroid Build Coastguard Worker i < istop; i++, sp++, dp++)
485*a67afe4dSAndroid Build Coastguard Worker {
486*a67afe4dSAndroid Build Coastguard Worker *dp = *sp;
487*a67afe4dSAndroid Build Coastguard Worker }
488*a67afe4dSAndroid Build Coastguard Worker }
489*a67afe4dSAndroid Build Coastguard Worker }
490*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
491*a67afe4dSAndroid Build Coastguard Worker png_ptr->save_buffer_max)
492*a67afe4dSAndroid Build Coastguard Worker {
493*a67afe4dSAndroid Build Coastguard Worker size_t new_max;
494*a67afe4dSAndroid Build Coastguard Worker png_bytep old_buffer;
495*a67afe4dSAndroid Build Coastguard Worker
496*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
497*a67afe4dSAndroid Build Coastguard Worker (png_ptr->current_buffer_size + 256))
498*a67afe4dSAndroid Build Coastguard Worker {
499*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Potential overflow of save_buffer");
500*a67afe4dSAndroid Build Coastguard Worker }
501*a67afe4dSAndroid Build Coastguard Worker
502*a67afe4dSAndroid Build Coastguard Worker new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
503*a67afe4dSAndroid Build Coastguard Worker old_buffer = png_ptr->save_buffer;
504*a67afe4dSAndroid Build Coastguard Worker png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
505*a67afe4dSAndroid Build Coastguard Worker (size_t)new_max);
506*a67afe4dSAndroid Build Coastguard Worker
507*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->save_buffer == NULL)
508*a67afe4dSAndroid Build Coastguard Worker {
509*a67afe4dSAndroid Build Coastguard Worker png_free(png_ptr, old_buffer);
510*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Insufficient memory for save_buffer");
511*a67afe4dSAndroid Build Coastguard Worker }
512*a67afe4dSAndroid Build Coastguard Worker
513*a67afe4dSAndroid Build Coastguard Worker if (old_buffer)
514*a67afe4dSAndroid Build Coastguard Worker memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
515*a67afe4dSAndroid Build Coastguard Worker else if (png_ptr->save_buffer_size)
516*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "save_buffer error");
517*a67afe4dSAndroid Build Coastguard Worker png_free(png_ptr, old_buffer);
518*a67afe4dSAndroid Build Coastguard Worker png_ptr->save_buffer_max = new_max;
519*a67afe4dSAndroid Build Coastguard Worker }
520*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->current_buffer_size)
521*a67afe4dSAndroid Build Coastguard Worker {
522*a67afe4dSAndroid Build Coastguard Worker memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
523*a67afe4dSAndroid Build Coastguard Worker png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
524*a67afe4dSAndroid Build Coastguard Worker png_ptr->save_buffer_size += png_ptr->current_buffer_size;
525*a67afe4dSAndroid Build Coastguard Worker png_ptr->current_buffer_size = 0;
526*a67afe4dSAndroid Build Coastguard Worker }
527*a67afe4dSAndroid Build Coastguard Worker png_ptr->save_buffer_ptr = png_ptr->save_buffer;
528*a67afe4dSAndroid Build Coastguard Worker png_ptr->buffer_size = 0;
529*a67afe4dSAndroid Build Coastguard Worker }
530*a67afe4dSAndroid Build Coastguard Worker
531*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_restore_buffer(png_structrp png_ptr,png_bytep buffer,size_t buffer_length)532*a67afe4dSAndroid Build Coastguard Worker png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
533*a67afe4dSAndroid Build Coastguard Worker size_t buffer_length)
534*a67afe4dSAndroid Build Coastguard Worker {
535*a67afe4dSAndroid Build Coastguard Worker png_ptr->current_buffer = buffer;
536*a67afe4dSAndroid Build Coastguard Worker png_ptr->current_buffer_size = buffer_length;
537*a67afe4dSAndroid Build Coastguard Worker png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
538*a67afe4dSAndroid Build Coastguard Worker png_ptr->current_buffer_ptr = png_ptr->current_buffer;
539*a67afe4dSAndroid Build Coastguard Worker }
540*a67afe4dSAndroid Build Coastguard Worker
541*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_read_IDAT(png_structrp png_ptr)542*a67afe4dSAndroid Build Coastguard Worker png_push_read_IDAT(png_structrp png_ptr)
543*a67afe4dSAndroid Build Coastguard Worker {
544*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
545*a67afe4dSAndroid Build Coastguard Worker {
546*a67afe4dSAndroid Build Coastguard Worker png_byte chunk_length[4];
547*a67afe4dSAndroid Build Coastguard Worker png_byte chunk_tag[4];
548*a67afe4dSAndroid Build Coastguard Worker
549*a67afe4dSAndroid Build Coastguard Worker /* TODO: this code can be commoned up with the same code in push_read */
550*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_LT(8)
551*a67afe4dSAndroid Build Coastguard Worker png_push_fill_buffer(png_ptr, chunk_length, 4);
552*a67afe4dSAndroid Build Coastguard Worker png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
553*a67afe4dSAndroid Build Coastguard Worker png_reset_crc(png_ptr);
554*a67afe4dSAndroid Build Coastguard Worker png_crc_read(png_ptr, chunk_tag, 4);
555*a67afe4dSAndroid Build Coastguard Worker png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
556*a67afe4dSAndroid Build Coastguard Worker png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
557*a67afe4dSAndroid Build Coastguard Worker
558*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->chunk_name != png_IDAT)
559*a67afe4dSAndroid Build Coastguard Worker {
560*a67afe4dSAndroid Build Coastguard Worker png_ptr->process_mode = PNG_READ_CHUNK_MODE;
561*a67afe4dSAndroid Build Coastguard Worker
562*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
563*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Not enough compressed data");
564*a67afe4dSAndroid Build Coastguard Worker
565*a67afe4dSAndroid Build Coastguard Worker return;
566*a67afe4dSAndroid Build Coastguard Worker }
567*a67afe4dSAndroid Build Coastguard Worker
568*a67afe4dSAndroid Build Coastguard Worker png_ptr->idat_size = png_ptr->push_length;
569*a67afe4dSAndroid Build Coastguard Worker }
570*a67afe4dSAndroid Build Coastguard Worker
571*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
572*a67afe4dSAndroid Build Coastguard Worker {
573*a67afe4dSAndroid Build Coastguard Worker size_t save_size = png_ptr->save_buffer_size;
574*a67afe4dSAndroid Build Coastguard Worker png_uint_32 idat_size = png_ptr->idat_size;
575*a67afe4dSAndroid Build Coastguard Worker
576*a67afe4dSAndroid Build Coastguard Worker /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
577*a67afe4dSAndroid Build Coastguard Worker * are of different types and we don't know which variable has the fewest
578*a67afe4dSAndroid Build Coastguard Worker * bits. Carefully select the smaller and cast it to the type of the
579*a67afe4dSAndroid Build Coastguard Worker * larger - this cannot overflow. Do not cast in the following test - it
580*a67afe4dSAndroid Build Coastguard Worker * will break on either 16-bit or 64-bit platforms.
581*a67afe4dSAndroid Build Coastguard Worker */
582*a67afe4dSAndroid Build Coastguard Worker if (idat_size < save_size)
583*a67afe4dSAndroid Build Coastguard Worker save_size = (size_t)idat_size;
584*a67afe4dSAndroid Build Coastguard Worker
585*a67afe4dSAndroid Build Coastguard Worker else
586*a67afe4dSAndroid Build Coastguard Worker idat_size = (png_uint_32)save_size;
587*a67afe4dSAndroid Build Coastguard Worker
588*a67afe4dSAndroid Build Coastguard Worker png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
589*a67afe4dSAndroid Build Coastguard Worker
590*a67afe4dSAndroid Build Coastguard Worker png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
591*a67afe4dSAndroid Build Coastguard Worker
592*a67afe4dSAndroid Build Coastguard Worker png_ptr->idat_size -= idat_size;
593*a67afe4dSAndroid Build Coastguard Worker png_ptr->buffer_size -= save_size;
594*a67afe4dSAndroid Build Coastguard Worker png_ptr->save_buffer_size -= save_size;
595*a67afe4dSAndroid Build Coastguard Worker png_ptr->save_buffer_ptr += save_size;
596*a67afe4dSAndroid Build Coastguard Worker }
597*a67afe4dSAndroid Build Coastguard Worker
598*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0)
599*a67afe4dSAndroid Build Coastguard Worker {
600*a67afe4dSAndroid Build Coastguard Worker size_t save_size = png_ptr->current_buffer_size;
601*a67afe4dSAndroid Build Coastguard Worker png_uint_32 idat_size = png_ptr->idat_size;
602*a67afe4dSAndroid Build Coastguard Worker
603*a67afe4dSAndroid Build Coastguard Worker /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
604*a67afe4dSAndroid Build Coastguard Worker * are of different types and we don't know which variable has the fewest
605*a67afe4dSAndroid Build Coastguard Worker * bits. Carefully select the smaller and cast it to the type of the
606*a67afe4dSAndroid Build Coastguard Worker * larger - this cannot overflow.
607*a67afe4dSAndroid Build Coastguard Worker */
608*a67afe4dSAndroid Build Coastguard Worker if (idat_size < save_size)
609*a67afe4dSAndroid Build Coastguard Worker save_size = (size_t)idat_size;
610*a67afe4dSAndroid Build Coastguard Worker
611*a67afe4dSAndroid Build Coastguard Worker else
612*a67afe4dSAndroid Build Coastguard Worker idat_size = (png_uint_32)save_size;
613*a67afe4dSAndroid Build Coastguard Worker
614*a67afe4dSAndroid Build Coastguard Worker png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
615*a67afe4dSAndroid Build Coastguard Worker
616*a67afe4dSAndroid Build Coastguard Worker png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
617*a67afe4dSAndroid Build Coastguard Worker
618*a67afe4dSAndroid Build Coastguard Worker png_ptr->idat_size -= idat_size;
619*a67afe4dSAndroid Build Coastguard Worker png_ptr->buffer_size -= save_size;
620*a67afe4dSAndroid Build Coastguard Worker png_ptr->current_buffer_size -= save_size;
621*a67afe4dSAndroid Build Coastguard Worker png_ptr->current_buffer_ptr += save_size;
622*a67afe4dSAndroid Build Coastguard Worker }
623*a67afe4dSAndroid Build Coastguard Worker
624*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->idat_size == 0)
625*a67afe4dSAndroid Build Coastguard Worker {
626*a67afe4dSAndroid Build Coastguard Worker PNG_PUSH_SAVE_BUFFER_IF_LT(4)
627*a67afe4dSAndroid Build Coastguard Worker png_crc_finish(png_ptr, 0);
628*a67afe4dSAndroid Build Coastguard Worker png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
629*a67afe4dSAndroid Build Coastguard Worker png_ptr->mode |= PNG_AFTER_IDAT;
630*a67afe4dSAndroid Build Coastguard Worker png_ptr->zowner = 0;
631*a67afe4dSAndroid Build Coastguard Worker }
632*a67afe4dSAndroid Build Coastguard Worker }
633*a67afe4dSAndroid Build Coastguard Worker
634*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_process_IDAT_data(png_structrp png_ptr,png_bytep buffer,size_t buffer_length)635*a67afe4dSAndroid Build Coastguard Worker png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
636*a67afe4dSAndroid Build Coastguard Worker size_t buffer_length)
637*a67afe4dSAndroid Build Coastguard Worker {
638*a67afe4dSAndroid Build Coastguard Worker /* The caller checks for a non-zero buffer length. */
639*a67afe4dSAndroid Build Coastguard Worker if (!(buffer_length > 0) || buffer == NULL)
640*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "No IDAT data (internal error)");
641*a67afe4dSAndroid Build Coastguard Worker
642*a67afe4dSAndroid Build Coastguard Worker /* This routine must process all the data it has been given
643*a67afe4dSAndroid Build Coastguard Worker * before returning, calling the row callback as required to
644*a67afe4dSAndroid Build Coastguard Worker * handle the uncompressed results.
645*a67afe4dSAndroid Build Coastguard Worker */
646*a67afe4dSAndroid Build Coastguard Worker png_ptr->zstream.next_in = buffer;
647*a67afe4dSAndroid Build Coastguard Worker /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
648*a67afe4dSAndroid Build Coastguard Worker png_ptr->zstream.avail_in = (uInt)buffer_length;
649*a67afe4dSAndroid Build Coastguard Worker
650*a67afe4dSAndroid Build Coastguard Worker /* Keep going until the decompressed data is all processed
651*a67afe4dSAndroid Build Coastguard Worker * or the stream marked as finished.
652*a67afe4dSAndroid Build Coastguard Worker */
653*a67afe4dSAndroid Build Coastguard Worker while (png_ptr->zstream.avail_in > 0 &&
654*a67afe4dSAndroid Build Coastguard Worker (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
655*a67afe4dSAndroid Build Coastguard Worker {
656*a67afe4dSAndroid Build Coastguard Worker int ret;
657*a67afe4dSAndroid Build Coastguard Worker
658*a67afe4dSAndroid Build Coastguard Worker /* We have data for zlib, but we must check that zlib
659*a67afe4dSAndroid Build Coastguard Worker * has someplace to put the results. It doesn't matter
660*a67afe4dSAndroid Build Coastguard Worker * if we don't expect any results -- it may be the input
661*a67afe4dSAndroid Build Coastguard Worker * data is just the LZ end code.
662*a67afe4dSAndroid Build Coastguard Worker */
663*a67afe4dSAndroid Build Coastguard Worker if (!(png_ptr->zstream.avail_out > 0))
664*a67afe4dSAndroid Build Coastguard Worker {
665*a67afe4dSAndroid Build Coastguard Worker /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
666*a67afe4dSAndroid Build Coastguard Worker png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
667*a67afe4dSAndroid Build Coastguard Worker png_ptr->iwidth) + 1);
668*a67afe4dSAndroid Build Coastguard Worker
669*a67afe4dSAndroid Build Coastguard Worker png_ptr->zstream.next_out = png_ptr->row_buf;
670*a67afe4dSAndroid Build Coastguard Worker }
671*a67afe4dSAndroid Build Coastguard Worker
672*a67afe4dSAndroid Build Coastguard Worker /* Using Z_SYNC_FLUSH here means that an unterminated
673*a67afe4dSAndroid Build Coastguard Worker * LZ stream (a stream with a missing end code) can still
674*a67afe4dSAndroid Build Coastguard Worker * be handled, otherwise (Z_NO_FLUSH) a future zlib
675*a67afe4dSAndroid Build Coastguard Worker * implementation might defer output and therefore
676*a67afe4dSAndroid Build Coastguard Worker * change the current behavior (see comments in inflate.c
677*a67afe4dSAndroid Build Coastguard Worker * for why this doesn't happen at present with zlib 1.2.5).
678*a67afe4dSAndroid Build Coastguard Worker */
679*a67afe4dSAndroid Build Coastguard Worker ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH);
680*a67afe4dSAndroid Build Coastguard Worker
681*a67afe4dSAndroid Build Coastguard Worker /* Check for any failure before proceeding. */
682*a67afe4dSAndroid Build Coastguard Worker if (ret != Z_OK && ret != Z_STREAM_END)
683*a67afe4dSAndroid Build Coastguard Worker {
684*a67afe4dSAndroid Build Coastguard Worker /* Terminate the decompression. */
685*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
686*a67afe4dSAndroid Build Coastguard Worker png_ptr->zowner = 0;
687*a67afe4dSAndroid Build Coastguard Worker
688*a67afe4dSAndroid Build Coastguard Worker /* This may be a truncated stream (missing or
689*a67afe4dSAndroid Build Coastguard Worker * damaged end code). Treat that as a warning.
690*a67afe4dSAndroid Build Coastguard Worker */
691*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->row_number >= png_ptr->num_rows ||
692*a67afe4dSAndroid Build Coastguard Worker png_ptr->pass > 6)
693*a67afe4dSAndroid Build Coastguard Worker png_warning(png_ptr, "Truncated compressed data in IDAT");
694*a67afe4dSAndroid Build Coastguard Worker
695*a67afe4dSAndroid Build Coastguard Worker else
696*a67afe4dSAndroid Build Coastguard Worker {
697*a67afe4dSAndroid Build Coastguard Worker if (ret == Z_DATA_ERROR)
698*a67afe4dSAndroid Build Coastguard Worker png_benign_error(png_ptr, "IDAT: ADLER32 checksum mismatch");
699*a67afe4dSAndroid Build Coastguard Worker else
700*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "Decompression error in IDAT");
701*a67afe4dSAndroid Build Coastguard Worker }
702*a67afe4dSAndroid Build Coastguard Worker
703*a67afe4dSAndroid Build Coastguard Worker /* Skip the check on unprocessed input */
704*a67afe4dSAndroid Build Coastguard Worker return;
705*a67afe4dSAndroid Build Coastguard Worker }
706*a67afe4dSAndroid Build Coastguard Worker
707*a67afe4dSAndroid Build Coastguard Worker /* Did inflate output any data? */
708*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->zstream.next_out != png_ptr->row_buf)
709*a67afe4dSAndroid Build Coastguard Worker {
710*a67afe4dSAndroid Build Coastguard Worker /* Is this unexpected data after the last row?
711*a67afe4dSAndroid Build Coastguard Worker * If it is, artificially terminate the LZ output
712*a67afe4dSAndroid Build Coastguard Worker * here.
713*a67afe4dSAndroid Build Coastguard Worker */
714*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->row_number >= png_ptr->num_rows ||
715*a67afe4dSAndroid Build Coastguard Worker png_ptr->pass > 6)
716*a67afe4dSAndroid Build Coastguard Worker {
717*a67afe4dSAndroid Build Coastguard Worker /* Extra data. */
718*a67afe4dSAndroid Build Coastguard Worker png_warning(png_ptr, "Extra compressed data in IDAT");
719*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
720*a67afe4dSAndroid Build Coastguard Worker png_ptr->zowner = 0;
721*a67afe4dSAndroid Build Coastguard Worker
722*a67afe4dSAndroid Build Coastguard Worker /* Do no more processing; skip the unprocessed
723*a67afe4dSAndroid Build Coastguard Worker * input check below.
724*a67afe4dSAndroid Build Coastguard Worker */
725*a67afe4dSAndroid Build Coastguard Worker return;
726*a67afe4dSAndroid Build Coastguard Worker }
727*a67afe4dSAndroid Build Coastguard Worker
728*a67afe4dSAndroid Build Coastguard Worker /* Do we have a complete row? */
729*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->zstream.avail_out == 0)
730*a67afe4dSAndroid Build Coastguard Worker png_push_process_row(png_ptr);
731*a67afe4dSAndroid Build Coastguard Worker }
732*a67afe4dSAndroid Build Coastguard Worker
733*a67afe4dSAndroid Build Coastguard Worker /* And check for the end of the stream. */
734*a67afe4dSAndroid Build Coastguard Worker if (ret == Z_STREAM_END)
735*a67afe4dSAndroid Build Coastguard Worker png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
736*a67afe4dSAndroid Build Coastguard Worker }
737*a67afe4dSAndroid Build Coastguard Worker
738*a67afe4dSAndroid Build Coastguard Worker /* All the data should have been processed, if anything
739*a67afe4dSAndroid Build Coastguard Worker * is left at this point we have bytes of IDAT data
740*a67afe4dSAndroid Build Coastguard Worker * after the zlib end code.
741*a67afe4dSAndroid Build Coastguard Worker */
742*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->zstream.avail_in > 0)
743*a67afe4dSAndroid Build Coastguard Worker png_warning(png_ptr, "Extra compression data in IDAT");
744*a67afe4dSAndroid Build Coastguard Worker }
745*a67afe4dSAndroid Build Coastguard Worker
746*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_process_row(png_structrp png_ptr)747*a67afe4dSAndroid Build Coastguard Worker png_push_process_row(png_structrp png_ptr)
748*a67afe4dSAndroid Build Coastguard Worker {
749*a67afe4dSAndroid Build Coastguard Worker /* 1.5.6: row_info moved out of png_struct to a local here. */
750*a67afe4dSAndroid Build Coastguard Worker png_row_info row_info;
751*a67afe4dSAndroid Build Coastguard Worker
752*a67afe4dSAndroid Build Coastguard Worker row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
753*a67afe4dSAndroid Build Coastguard Worker row_info.color_type = png_ptr->color_type;
754*a67afe4dSAndroid Build Coastguard Worker row_info.bit_depth = png_ptr->bit_depth;
755*a67afe4dSAndroid Build Coastguard Worker row_info.channels = png_ptr->channels;
756*a67afe4dSAndroid Build Coastguard Worker row_info.pixel_depth = png_ptr->pixel_depth;
757*a67afe4dSAndroid Build Coastguard Worker row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
758*a67afe4dSAndroid Build Coastguard Worker
759*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
760*a67afe4dSAndroid Build Coastguard Worker {
761*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
762*a67afe4dSAndroid Build Coastguard Worker png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
763*a67afe4dSAndroid Build Coastguard Worker png_ptr->prev_row + 1, png_ptr->row_buf[0]);
764*a67afe4dSAndroid Build Coastguard Worker else
765*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "bad adaptive filter value");
766*a67afe4dSAndroid Build Coastguard Worker }
767*a67afe4dSAndroid Build Coastguard Worker
768*a67afe4dSAndroid Build Coastguard Worker /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
769*a67afe4dSAndroid Build Coastguard Worker * 1.5.6, while the buffer really is this big in current versions of libpng
770*a67afe4dSAndroid Build Coastguard Worker * it may not be in the future, so this was changed just to copy the
771*a67afe4dSAndroid Build Coastguard Worker * interlaced row count:
772*a67afe4dSAndroid Build Coastguard Worker */
773*a67afe4dSAndroid Build Coastguard Worker memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
774*a67afe4dSAndroid Build Coastguard Worker
775*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_TRANSFORMS_SUPPORTED
776*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->transformations != 0)
777*a67afe4dSAndroid Build Coastguard Worker png_do_read_transformations(png_ptr, &row_info);
778*a67afe4dSAndroid Build Coastguard Worker #endif
779*a67afe4dSAndroid Build Coastguard Worker
780*a67afe4dSAndroid Build Coastguard Worker /* The transformed pixel depth should match the depth now in row_info. */
781*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->transformed_pixel_depth == 0)
782*a67afe4dSAndroid Build Coastguard Worker {
783*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformed_pixel_depth = row_info.pixel_depth;
784*a67afe4dSAndroid Build Coastguard Worker if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
785*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "progressive row overflow");
786*a67afe4dSAndroid Build Coastguard Worker }
787*a67afe4dSAndroid Build Coastguard Worker
788*a67afe4dSAndroid Build Coastguard Worker else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
789*a67afe4dSAndroid Build Coastguard Worker png_error(png_ptr, "internal progressive row size calculation error");
790*a67afe4dSAndroid Build Coastguard Worker
791*a67afe4dSAndroid Build Coastguard Worker
792*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INTERLACING_SUPPORTED
793*a67afe4dSAndroid Build Coastguard Worker /* Expand interlaced rows to full size */
794*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->interlaced != 0 &&
795*a67afe4dSAndroid Build Coastguard Worker (png_ptr->transformations & PNG_INTERLACE) != 0)
796*a67afe4dSAndroid Build Coastguard Worker {
797*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass < 6)
798*a67afe4dSAndroid Build Coastguard Worker png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
799*a67afe4dSAndroid Build Coastguard Worker png_ptr->transformations);
800*a67afe4dSAndroid Build Coastguard Worker
801*a67afe4dSAndroid Build Coastguard Worker switch (png_ptr->pass)
802*a67afe4dSAndroid Build Coastguard Worker {
803*a67afe4dSAndroid Build Coastguard Worker case 0:
804*a67afe4dSAndroid Build Coastguard Worker {
805*a67afe4dSAndroid Build Coastguard Worker int i;
806*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 8 && png_ptr->pass == 0; i++)
807*a67afe4dSAndroid Build Coastguard Worker {
808*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, png_ptr->row_buf + 1);
809*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
810*a67afe4dSAndroid Build Coastguard Worker }
811*a67afe4dSAndroid Build Coastguard Worker
812*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass == 2) /* Pass 1 might be empty */
813*a67afe4dSAndroid Build Coastguard Worker {
814*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 4 && png_ptr->pass == 2; i++)
815*a67afe4dSAndroid Build Coastguard Worker {
816*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, NULL);
817*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
818*a67afe4dSAndroid Build Coastguard Worker }
819*a67afe4dSAndroid Build Coastguard Worker }
820*a67afe4dSAndroid Build Coastguard Worker
821*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass == 4 && png_ptr->height <= 4)
822*a67afe4dSAndroid Build Coastguard Worker {
823*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 2 && png_ptr->pass == 4; i++)
824*a67afe4dSAndroid Build Coastguard Worker {
825*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, NULL);
826*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
827*a67afe4dSAndroid Build Coastguard Worker }
828*a67afe4dSAndroid Build Coastguard Worker }
829*a67afe4dSAndroid Build Coastguard Worker
830*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass == 6 && png_ptr->height <= 4)
831*a67afe4dSAndroid Build Coastguard Worker {
832*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, NULL);
833*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
834*a67afe4dSAndroid Build Coastguard Worker }
835*a67afe4dSAndroid Build Coastguard Worker
836*a67afe4dSAndroid Build Coastguard Worker break;
837*a67afe4dSAndroid Build Coastguard Worker }
838*a67afe4dSAndroid Build Coastguard Worker
839*a67afe4dSAndroid Build Coastguard Worker case 1:
840*a67afe4dSAndroid Build Coastguard Worker {
841*a67afe4dSAndroid Build Coastguard Worker int i;
842*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 8 && png_ptr->pass == 1; i++)
843*a67afe4dSAndroid Build Coastguard Worker {
844*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, png_ptr->row_buf + 1);
845*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
846*a67afe4dSAndroid Build Coastguard Worker }
847*a67afe4dSAndroid Build Coastguard Worker
848*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass == 2) /* Skip top 4 generated rows */
849*a67afe4dSAndroid Build Coastguard Worker {
850*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 4 && png_ptr->pass == 2; i++)
851*a67afe4dSAndroid Build Coastguard Worker {
852*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, NULL);
853*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
854*a67afe4dSAndroid Build Coastguard Worker }
855*a67afe4dSAndroid Build Coastguard Worker }
856*a67afe4dSAndroid Build Coastguard Worker
857*a67afe4dSAndroid Build Coastguard Worker break;
858*a67afe4dSAndroid Build Coastguard Worker }
859*a67afe4dSAndroid Build Coastguard Worker
860*a67afe4dSAndroid Build Coastguard Worker case 2:
861*a67afe4dSAndroid Build Coastguard Worker {
862*a67afe4dSAndroid Build Coastguard Worker int i;
863*a67afe4dSAndroid Build Coastguard Worker
864*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 4 && png_ptr->pass == 2; i++)
865*a67afe4dSAndroid Build Coastguard Worker {
866*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, png_ptr->row_buf + 1);
867*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
868*a67afe4dSAndroid Build Coastguard Worker }
869*a67afe4dSAndroid Build Coastguard Worker
870*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 4 && png_ptr->pass == 2; i++)
871*a67afe4dSAndroid Build Coastguard Worker {
872*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, NULL);
873*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
874*a67afe4dSAndroid Build Coastguard Worker }
875*a67afe4dSAndroid Build Coastguard Worker
876*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass == 4) /* Pass 3 might be empty */
877*a67afe4dSAndroid Build Coastguard Worker {
878*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 2 && png_ptr->pass == 4; i++)
879*a67afe4dSAndroid Build Coastguard Worker {
880*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, NULL);
881*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
882*a67afe4dSAndroid Build Coastguard Worker }
883*a67afe4dSAndroid Build Coastguard Worker }
884*a67afe4dSAndroid Build Coastguard Worker
885*a67afe4dSAndroid Build Coastguard Worker break;
886*a67afe4dSAndroid Build Coastguard Worker }
887*a67afe4dSAndroid Build Coastguard Worker
888*a67afe4dSAndroid Build Coastguard Worker case 3:
889*a67afe4dSAndroid Build Coastguard Worker {
890*a67afe4dSAndroid Build Coastguard Worker int i;
891*a67afe4dSAndroid Build Coastguard Worker
892*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 4 && png_ptr->pass == 3; i++)
893*a67afe4dSAndroid Build Coastguard Worker {
894*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, png_ptr->row_buf + 1);
895*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
896*a67afe4dSAndroid Build Coastguard Worker }
897*a67afe4dSAndroid Build Coastguard Worker
898*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass == 4) /* Skip top two generated rows */
899*a67afe4dSAndroid Build Coastguard Worker {
900*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 2 && png_ptr->pass == 4; i++)
901*a67afe4dSAndroid Build Coastguard Worker {
902*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, NULL);
903*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
904*a67afe4dSAndroid Build Coastguard Worker }
905*a67afe4dSAndroid Build Coastguard Worker }
906*a67afe4dSAndroid Build Coastguard Worker
907*a67afe4dSAndroid Build Coastguard Worker break;
908*a67afe4dSAndroid Build Coastguard Worker }
909*a67afe4dSAndroid Build Coastguard Worker
910*a67afe4dSAndroid Build Coastguard Worker case 4:
911*a67afe4dSAndroid Build Coastguard Worker {
912*a67afe4dSAndroid Build Coastguard Worker int i;
913*a67afe4dSAndroid Build Coastguard Worker
914*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 2 && png_ptr->pass == 4; i++)
915*a67afe4dSAndroid Build Coastguard Worker {
916*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, png_ptr->row_buf + 1);
917*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
918*a67afe4dSAndroid Build Coastguard Worker }
919*a67afe4dSAndroid Build Coastguard Worker
920*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 2 && png_ptr->pass == 4; i++)
921*a67afe4dSAndroid Build Coastguard Worker {
922*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, NULL);
923*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
924*a67afe4dSAndroid Build Coastguard Worker }
925*a67afe4dSAndroid Build Coastguard Worker
926*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass == 6) /* Pass 5 might be empty */
927*a67afe4dSAndroid Build Coastguard Worker {
928*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, NULL);
929*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
930*a67afe4dSAndroid Build Coastguard Worker }
931*a67afe4dSAndroid Build Coastguard Worker
932*a67afe4dSAndroid Build Coastguard Worker break;
933*a67afe4dSAndroid Build Coastguard Worker }
934*a67afe4dSAndroid Build Coastguard Worker
935*a67afe4dSAndroid Build Coastguard Worker case 5:
936*a67afe4dSAndroid Build Coastguard Worker {
937*a67afe4dSAndroid Build Coastguard Worker int i;
938*a67afe4dSAndroid Build Coastguard Worker
939*a67afe4dSAndroid Build Coastguard Worker for (i = 0; i < 2 && png_ptr->pass == 5; i++)
940*a67afe4dSAndroid Build Coastguard Worker {
941*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, png_ptr->row_buf + 1);
942*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
943*a67afe4dSAndroid Build Coastguard Worker }
944*a67afe4dSAndroid Build Coastguard Worker
945*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass == 6) /* Skip top generated row */
946*a67afe4dSAndroid Build Coastguard Worker {
947*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, NULL);
948*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
949*a67afe4dSAndroid Build Coastguard Worker }
950*a67afe4dSAndroid Build Coastguard Worker
951*a67afe4dSAndroid Build Coastguard Worker break;
952*a67afe4dSAndroid Build Coastguard Worker }
953*a67afe4dSAndroid Build Coastguard Worker
954*a67afe4dSAndroid Build Coastguard Worker default:
955*a67afe4dSAndroid Build Coastguard Worker case 6:
956*a67afe4dSAndroid Build Coastguard Worker {
957*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, png_ptr->row_buf + 1);
958*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
959*a67afe4dSAndroid Build Coastguard Worker
960*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass != 6)
961*a67afe4dSAndroid Build Coastguard Worker break;
962*a67afe4dSAndroid Build Coastguard Worker
963*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, NULL);
964*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
965*a67afe4dSAndroid Build Coastguard Worker }
966*a67afe4dSAndroid Build Coastguard Worker }
967*a67afe4dSAndroid Build Coastguard Worker }
968*a67afe4dSAndroid Build Coastguard Worker else
969*a67afe4dSAndroid Build Coastguard Worker #endif
970*a67afe4dSAndroid Build Coastguard Worker {
971*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_ptr, png_ptr->row_buf + 1);
972*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_ptr);
973*a67afe4dSAndroid Build Coastguard Worker }
974*a67afe4dSAndroid Build Coastguard Worker }
975*a67afe4dSAndroid Build Coastguard Worker
976*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_read_push_finish_row(png_structrp png_ptr)977*a67afe4dSAndroid Build Coastguard Worker png_read_push_finish_row(png_structrp png_ptr)
978*a67afe4dSAndroid Build Coastguard Worker {
979*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INTERLACING_SUPPORTED
980*a67afe4dSAndroid Build Coastguard Worker /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
981*a67afe4dSAndroid Build Coastguard Worker
982*a67afe4dSAndroid Build Coastguard Worker /* Start of interlace block */
983*a67afe4dSAndroid Build Coastguard Worker static const png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
984*a67afe4dSAndroid Build Coastguard Worker
985*a67afe4dSAndroid Build Coastguard Worker /* Offset to next interlace block */
986*a67afe4dSAndroid Build Coastguard Worker static const png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
987*a67afe4dSAndroid Build Coastguard Worker
988*a67afe4dSAndroid Build Coastguard Worker /* Start of interlace block in the y direction */
989*a67afe4dSAndroid Build Coastguard Worker static const png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
990*a67afe4dSAndroid Build Coastguard Worker
991*a67afe4dSAndroid Build Coastguard Worker /* Offset to next interlace block in the y direction */
992*a67afe4dSAndroid Build Coastguard Worker static const png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
993*a67afe4dSAndroid Build Coastguard Worker
994*a67afe4dSAndroid Build Coastguard Worker /* Height of interlace block. This is not currently used - if you need
995*a67afe4dSAndroid Build Coastguard Worker * it, uncomment it here and in png.h
996*a67afe4dSAndroid Build Coastguard Worker static const png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
997*a67afe4dSAndroid Build Coastguard Worker */
998*a67afe4dSAndroid Build Coastguard Worker #endif
999*a67afe4dSAndroid Build Coastguard Worker
1000*a67afe4dSAndroid Build Coastguard Worker png_ptr->row_number++;
1001*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->row_number < png_ptr->num_rows)
1002*a67afe4dSAndroid Build Coastguard Worker return;
1003*a67afe4dSAndroid Build Coastguard Worker
1004*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INTERLACING_SUPPORTED
1005*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->interlaced != 0)
1006*a67afe4dSAndroid Build Coastguard Worker {
1007*a67afe4dSAndroid Build Coastguard Worker png_ptr->row_number = 0;
1008*a67afe4dSAndroid Build Coastguard Worker memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
1009*a67afe4dSAndroid Build Coastguard Worker
1010*a67afe4dSAndroid Build Coastguard Worker do
1011*a67afe4dSAndroid Build Coastguard Worker {
1012*a67afe4dSAndroid Build Coastguard Worker png_ptr->pass++;
1013*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
1014*a67afe4dSAndroid Build Coastguard Worker (png_ptr->pass == 3 && png_ptr->width < 3) ||
1015*a67afe4dSAndroid Build Coastguard Worker (png_ptr->pass == 5 && png_ptr->width < 2))
1016*a67afe4dSAndroid Build Coastguard Worker png_ptr->pass++;
1017*a67afe4dSAndroid Build Coastguard Worker
1018*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass > 7)
1019*a67afe4dSAndroid Build Coastguard Worker png_ptr->pass--;
1020*a67afe4dSAndroid Build Coastguard Worker
1021*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->pass >= 7)
1022*a67afe4dSAndroid Build Coastguard Worker break;
1023*a67afe4dSAndroid Build Coastguard Worker
1024*a67afe4dSAndroid Build Coastguard Worker png_ptr->iwidth = (png_ptr->width +
1025*a67afe4dSAndroid Build Coastguard Worker png_pass_inc[png_ptr->pass] - 1 -
1026*a67afe4dSAndroid Build Coastguard Worker png_pass_start[png_ptr->pass]) /
1027*a67afe4dSAndroid Build Coastguard Worker png_pass_inc[png_ptr->pass];
1028*a67afe4dSAndroid Build Coastguard Worker
1029*a67afe4dSAndroid Build Coastguard Worker if ((png_ptr->transformations & PNG_INTERLACE) != 0)
1030*a67afe4dSAndroid Build Coastguard Worker break;
1031*a67afe4dSAndroid Build Coastguard Worker
1032*a67afe4dSAndroid Build Coastguard Worker png_ptr->num_rows = (png_ptr->height +
1033*a67afe4dSAndroid Build Coastguard Worker png_pass_yinc[png_ptr->pass] - 1 -
1034*a67afe4dSAndroid Build Coastguard Worker png_pass_ystart[png_ptr->pass]) /
1035*a67afe4dSAndroid Build Coastguard Worker png_pass_yinc[png_ptr->pass];
1036*a67afe4dSAndroid Build Coastguard Worker
1037*a67afe4dSAndroid Build Coastguard Worker } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
1038*a67afe4dSAndroid Build Coastguard Worker }
1039*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_INTERLACING */
1040*a67afe4dSAndroid Build Coastguard Worker }
1041*a67afe4dSAndroid Build Coastguard Worker
1042*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_have_info(png_structrp png_ptr,png_inforp info_ptr)1043*a67afe4dSAndroid Build Coastguard Worker png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
1044*a67afe4dSAndroid Build Coastguard Worker {
1045*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->info_fn != NULL)
1046*a67afe4dSAndroid Build Coastguard Worker (*(png_ptr->info_fn))(png_ptr, info_ptr);
1047*a67afe4dSAndroid Build Coastguard Worker }
1048*a67afe4dSAndroid Build Coastguard Worker
1049*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_have_end(png_structrp png_ptr,png_inforp info_ptr)1050*a67afe4dSAndroid Build Coastguard Worker png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
1051*a67afe4dSAndroid Build Coastguard Worker {
1052*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->end_fn != NULL)
1053*a67afe4dSAndroid Build Coastguard Worker (*(png_ptr->end_fn))(png_ptr, info_ptr);
1054*a67afe4dSAndroid Build Coastguard Worker }
1055*a67afe4dSAndroid Build Coastguard Worker
1056*a67afe4dSAndroid Build Coastguard Worker void /* PRIVATE */
png_push_have_row(png_structrp png_ptr,png_bytep row)1057*a67afe4dSAndroid Build Coastguard Worker png_push_have_row(png_structrp png_ptr, png_bytep row)
1058*a67afe4dSAndroid Build Coastguard Worker {
1059*a67afe4dSAndroid Build Coastguard Worker if (png_ptr->row_fn != NULL)
1060*a67afe4dSAndroid Build Coastguard Worker (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
1061*a67afe4dSAndroid Build Coastguard Worker (int)png_ptr->pass);
1062*a67afe4dSAndroid Build Coastguard Worker }
1063*a67afe4dSAndroid Build Coastguard Worker
1064*a67afe4dSAndroid Build Coastguard Worker #ifdef PNG_READ_INTERLACING_SUPPORTED
1065*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_progressive_combine_row(png_const_structrp png_ptr,png_bytep old_row,png_const_bytep new_row)1066*a67afe4dSAndroid Build Coastguard Worker png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
1067*a67afe4dSAndroid Build Coastguard Worker png_const_bytep new_row)
1068*a67afe4dSAndroid Build Coastguard Worker {
1069*a67afe4dSAndroid Build Coastguard Worker if (png_ptr == NULL)
1070*a67afe4dSAndroid Build Coastguard Worker return;
1071*a67afe4dSAndroid Build Coastguard Worker
1072*a67afe4dSAndroid Build Coastguard Worker /* new_row is a flag here - if it is NULL then the app callback was called
1073*a67afe4dSAndroid Build Coastguard Worker * from an empty row (see the calls to png_struct::row_fn below), otherwise
1074*a67afe4dSAndroid Build Coastguard Worker * it must be png_ptr->row_buf+1
1075*a67afe4dSAndroid Build Coastguard Worker */
1076*a67afe4dSAndroid Build Coastguard Worker if (new_row != NULL)
1077*a67afe4dSAndroid Build Coastguard Worker png_combine_row(png_ptr, old_row, 1/*blocky display*/);
1078*a67afe4dSAndroid Build Coastguard Worker }
1079*a67afe4dSAndroid Build Coastguard Worker #endif /* READ_INTERLACING */
1080*a67afe4dSAndroid Build Coastguard Worker
1081*a67afe4dSAndroid Build Coastguard Worker void PNGAPI
png_set_progressive_read_fn(png_structrp png_ptr,png_voidp progressive_ptr,png_progressive_info_ptr info_fn,png_progressive_row_ptr row_fn,png_progressive_end_ptr end_fn)1082*a67afe4dSAndroid Build Coastguard Worker png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
1083*a67afe4dSAndroid Build Coastguard Worker png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
1084*a67afe4dSAndroid Build Coastguard Worker png_progressive_end_ptr end_fn)
1085*a67afe4dSAndroid Build Coastguard Worker {
1086*a67afe4dSAndroid Build Coastguard Worker if (png_ptr == NULL)
1087*a67afe4dSAndroid Build Coastguard Worker return;
1088*a67afe4dSAndroid Build Coastguard Worker
1089*a67afe4dSAndroid Build Coastguard Worker png_ptr->info_fn = info_fn;
1090*a67afe4dSAndroid Build Coastguard Worker png_ptr->row_fn = row_fn;
1091*a67afe4dSAndroid Build Coastguard Worker png_ptr->end_fn = end_fn;
1092*a67afe4dSAndroid Build Coastguard Worker
1093*a67afe4dSAndroid Build Coastguard Worker png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
1094*a67afe4dSAndroid Build Coastguard Worker }
1095*a67afe4dSAndroid Build Coastguard Worker
1096*a67afe4dSAndroid Build Coastguard Worker png_voidp PNGAPI
png_get_progressive_ptr(png_const_structrp png_ptr)1097*a67afe4dSAndroid Build Coastguard Worker png_get_progressive_ptr(png_const_structrp png_ptr)
1098*a67afe4dSAndroid Build Coastguard Worker {
1099*a67afe4dSAndroid Build Coastguard Worker if (png_ptr == NULL)
1100*a67afe4dSAndroid Build Coastguard Worker return NULL;
1101*a67afe4dSAndroid Build Coastguard Worker
1102*a67afe4dSAndroid Build Coastguard Worker return png_ptr->io_ptr;
1103*a67afe4dSAndroid Build Coastguard Worker }
1104*a67afe4dSAndroid Build Coastguard Worker #endif /* PROGRESSIVE_READ */
1105