1 |
william |
31 |
|
2 |
|
|
/* pngpread.c - read a png file in push mode |
3 |
|
|
* |
4 |
|
|
* Last changed in libpng 1.2.38 [July 16, 2009] |
5 |
|
|
* Copyright (c) 1998-2009 Glenn Randers-Pehrson |
6 |
|
|
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) |
7 |
|
|
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) |
8 |
|
|
* |
9 |
|
|
* This code is released under the libpng license. |
10 |
|
|
* For conditions of distribution and use, see the disclaimer |
11 |
|
|
* and license in png.h |
12 |
|
|
*/ |
13 |
|
|
|
14 |
|
|
#define PNG_INTERNAL |
15 |
|
|
#include "png.h" |
16 |
|
|
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED |
17 |
|
|
|
18 |
|
|
/* Push model modes */ |
19 |
|
|
#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 |
|
|
|
29 |
|
|
void PNGAPI |
30 |
|
|
png_process_data(png_structp png_ptr, png_infop info_ptr, |
31 |
|
|
png_bytep buffer, png_size_t buffer_size) |
32 |
|
|
{ |
33 |
|
|
if (png_ptr == NULL || info_ptr == NULL) |
34 |
|
|
return; |
35 |
|
|
|
36 |
|
|
png_push_restore_buffer(png_ptr, buffer, buffer_size); |
37 |
|
|
|
38 |
|
|
while (png_ptr->buffer_size) |
39 |
|
|
{ |
40 |
|
|
png_process_some_data(png_ptr, info_ptr); |
41 |
|
|
} |
42 |
|
|
} |
43 |
|
|
|
44 |
|
|
/* What we do with the incoming data depends on what we were previously |
45 |
|
|
* doing before we ran out of data... |
46 |
|
|
*/ |
47 |
|
|
void /* PRIVATE */ |
48 |
|
|
png_process_some_data(png_structp png_ptr, png_infop info_ptr) |
49 |
|
|
{ |
50 |
|
|
if (png_ptr == NULL) |
51 |
|
|
return; |
52 |
|
|
|
53 |
|
|
switch (png_ptr->process_mode) |
54 |
|
|
{ |
55 |
|
|
case PNG_READ_SIG_MODE: |
56 |
|
|
{ |
57 |
|
|
png_push_read_sig(png_ptr, info_ptr); |
58 |
|
|
break; |
59 |
|
|
} |
60 |
|
|
|
61 |
|
|
case PNG_READ_CHUNK_MODE: |
62 |
|
|
{ |
63 |
|
|
png_push_read_chunk(png_ptr, info_ptr); |
64 |
|
|
break; |
65 |
|
|
} |
66 |
|
|
|
67 |
|
|
case PNG_READ_IDAT_MODE: |
68 |
|
|
{ |
69 |
|
|
png_push_read_IDAT(png_ptr); |
70 |
|
|
break; |
71 |
|
|
} |
72 |
|
|
|
73 |
|
|
#if defined(PNG_READ_tEXt_SUPPORTED) |
74 |
|
|
case PNG_READ_tEXt_MODE: |
75 |
|
|
{ |
76 |
|
|
png_push_read_tEXt(png_ptr, info_ptr); |
77 |
|
|
break; |
78 |
|
|
} |
79 |
|
|
|
80 |
|
|
#endif |
81 |
|
|
#if defined(PNG_READ_zTXt_SUPPORTED) |
82 |
|
|
case PNG_READ_zTXt_MODE: |
83 |
|
|
{ |
84 |
|
|
png_push_read_zTXt(png_ptr, info_ptr); |
85 |
|
|
break; |
86 |
|
|
} |
87 |
|
|
|
88 |
|
|
#endif |
89 |
|
|
#if defined(PNG_READ_iTXt_SUPPORTED) |
90 |
|
|
case PNG_READ_iTXt_MODE: |
91 |
|
|
{ |
92 |
|
|
png_push_read_iTXt(png_ptr, info_ptr); |
93 |
|
|
break; |
94 |
|
|
} |
95 |
|
|
|
96 |
|
|
#endif |
97 |
|
|
case PNG_SKIP_MODE: |
98 |
|
|
{ |
99 |
|
|
png_push_crc_finish(png_ptr); |
100 |
|
|
break; |
101 |
|
|
} |
102 |
|
|
|
103 |
|
|
default: |
104 |
|
|
{ |
105 |
|
|
png_ptr->buffer_size = 0; |
106 |
|
|
break; |
107 |
|
|
} |
108 |
|
|
} |
109 |
|
|
} |
110 |
|
|
|
111 |
|
|
/* Read any remaining signature bytes from the stream and compare them with |
112 |
|
|
* the correct PNG signature. It is possible that this routine is called |
113 |
|
|
* with bytes already read from the signature, either because they have been |
114 |
|
|
* checked by the calling application, or because of multiple calls to this |
115 |
|
|
* routine. |
116 |
|
|
*/ |
117 |
|
|
void /* PRIVATE */ |
118 |
|
|
png_push_read_sig(png_structp png_ptr, png_infop info_ptr) |
119 |
|
|
{ |
120 |
|
|
png_size_t num_checked = png_ptr->sig_bytes, |
121 |
|
|
num_to_check = 8 - num_checked; |
122 |
|
|
|
123 |
|
|
if (png_ptr->buffer_size < num_to_check) |
124 |
|
|
{ |
125 |
|
|
num_to_check = png_ptr->buffer_size; |
126 |
|
|
} |
127 |
|
|
|
128 |
|
|
png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), |
129 |
|
|
num_to_check); |
130 |
|
|
png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check); |
131 |
|
|
|
132 |
|
|
if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) |
133 |
|
|
{ |
134 |
|
|
if (num_checked < 4 && |
135 |
|
|
png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) |
136 |
|
|
png_error(png_ptr, "Not a PNG file"); |
137 |
|
|
else |
138 |
|
|
png_error(png_ptr, "PNG file corrupted by ASCII conversion"); |
139 |
|
|
} |
140 |
|
|
else |
141 |
|
|
{ |
142 |
|
|
if (png_ptr->sig_bytes >= 8) |
143 |
|
|
{ |
144 |
|
|
png_ptr->process_mode = PNG_READ_CHUNK_MODE; |
145 |
|
|
} |
146 |
|
|
} |
147 |
|
|
} |
148 |
|
|
|
149 |
|
|
void /* PRIVATE */ |
150 |
|
|
png_push_read_chunk(png_structp png_ptr, png_infop info_ptr) |
151 |
|
|
{ |
152 |
|
|
#ifdef PNG_USE_LOCAL_ARRAYS |
153 |
|
|
PNG_CONST PNG_IHDR; |
154 |
|
|
PNG_CONST PNG_IDAT; |
155 |
|
|
PNG_CONST PNG_IEND; |
156 |
|
|
PNG_CONST PNG_PLTE; |
157 |
|
|
#if defined(PNG_READ_bKGD_SUPPORTED) |
158 |
|
|
PNG_CONST PNG_bKGD; |
159 |
|
|
#endif |
160 |
|
|
#if defined(PNG_READ_cHRM_SUPPORTED) |
161 |
|
|
PNG_CONST PNG_cHRM; |
162 |
|
|
#endif |
163 |
|
|
#if defined(PNG_READ_gAMA_SUPPORTED) |
164 |
|
|
PNG_CONST PNG_gAMA; |
165 |
|
|
#endif |
166 |
|
|
#if defined(PNG_READ_hIST_SUPPORTED) |
167 |
|
|
PNG_CONST PNG_hIST; |
168 |
|
|
#endif |
169 |
|
|
#if defined(PNG_READ_iCCP_SUPPORTED) |
170 |
|
|
PNG_CONST PNG_iCCP; |
171 |
|
|
#endif |
172 |
|
|
#if defined(PNG_READ_iTXt_SUPPORTED) |
173 |
|
|
PNG_CONST PNG_iTXt; |
174 |
|
|
#endif |
175 |
|
|
#if defined(PNG_READ_oFFs_SUPPORTED) |
176 |
|
|
PNG_CONST PNG_oFFs; |
177 |
|
|
#endif |
178 |
|
|
#if defined(PNG_READ_pCAL_SUPPORTED) |
179 |
|
|
PNG_CONST PNG_pCAL; |
180 |
|
|
#endif |
181 |
|
|
#if defined(PNG_READ_pHYs_SUPPORTED) |
182 |
|
|
PNG_CONST PNG_pHYs; |
183 |
|
|
#endif |
184 |
|
|
#if defined(PNG_READ_sBIT_SUPPORTED) |
185 |
|
|
PNG_CONST PNG_sBIT; |
186 |
|
|
#endif |
187 |
|
|
#if defined(PNG_READ_sCAL_SUPPORTED) |
188 |
|
|
PNG_CONST PNG_sCAL; |
189 |
|
|
#endif |
190 |
|
|
#if defined(PNG_READ_sRGB_SUPPORTED) |
191 |
|
|
PNG_CONST PNG_sRGB; |
192 |
|
|
#endif |
193 |
|
|
#if defined(PNG_READ_sPLT_SUPPORTED) |
194 |
|
|
PNG_CONST PNG_sPLT; |
195 |
|
|
#endif |
196 |
|
|
#if defined(PNG_READ_tEXt_SUPPORTED) |
197 |
|
|
PNG_CONST PNG_tEXt; |
198 |
|
|
#endif |
199 |
|
|
#if defined(PNG_READ_tIME_SUPPORTED) |
200 |
|
|
PNG_CONST PNG_tIME; |
201 |
|
|
#endif |
202 |
|
|
#if defined(PNG_READ_tRNS_SUPPORTED) |
203 |
|
|
PNG_CONST PNG_tRNS; |
204 |
|
|
#endif |
205 |
|
|
#if defined(PNG_READ_zTXt_SUPPORTED) |
206 |
|
|
PNG_CONST PNG_zTXt; |
207 |
|
|
#endif |
208 |
|
|
#endif /* PNG_USE_LOCAL_ARRAYS */ |
209 |
|
|
/* First we make sure we have enough data for the 4 byte chunk name |
210 |
|
|
* and the 4 byte chunk length before proceeding with decoding the |
211 |
|
|
* chunk data. To fully decode each of these chunks, we also make |
212 |
|
|
* sure we have enough data in the buffer for the 4 byte CRC at the |
213 |
|
|
* end of every chunk (except IDAT, which is handled separately). |
214 |
|
|
*/ |
215 |
|
|
if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) |
216 |
|
|
{ |
217 |
|
|
png_byte chunk_length[4]; |
218 |
|
|
|
219 |
|
|
if (png_ptr->buffer_size < 8) |
220 |
|
|
{ |
221 |
|
|
png_push_save_buffer(png_ptr); |
222 |
|
|
return; |
223 |
|
|
} |
224 |
|
|
|
225 |
|
|
png_push_fill_buffer(png_ptr, chunk_length, 4); |
226 |
|
|
png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); |
227 |
|
|
png_reset_crc(png_ptr); |
228 |
|
|
png_crc_read(png_ptr, png_ptr->chunk_name, 4); |
229 |
|
|
png_check_chunk_name(png_ptr, png_ptr->chunk_name); |
230 |
|
|
png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; |
231 |
|
|
} |
232 |
|
|
|
233 |
|
|
if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) |
234 |
|
|
if (png_ptr->mode & PNG_AFTER_IDAT) |
235 |
|
|
png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; |
236 |
|
|
|
237 |
|
|
if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4)) |
238 |
|
|
{ |
239 |
|
|
if (png_ptr->push_length != 13) |
240 |
|
|
png_error(png_ptr, "Invalid IHDR length"); |
241 |
|
|
|
242 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
243 |
|
|
{ |
244 |
|
|
png_push_save_buffer(png_ptr); |
245 |
|
|
return; |
246 |
|
|
} |
247 |
|
|
|
248 |
|
|
png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length); |
249 |
|
|
} |
250 |
|
|
|
251 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4)) |
252 |
|
|
{ |
253 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
254 |
|
|
{ |
255 |
|
|
png_push_save_buffer(png_ptr); |
256 |
|
|
return; |
257 |
|
|
} |
258 |
|
|
|
259 |
|
|
png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length); |
260 |
|
|
|
261 |
|
|
png_ptr->process_mode = PNG_READ_DONE_MODE; |
262 |
|
|
png_push_have_end(png_ptr, info_ptr); |
263 |
|
|
} |
264 |
|
|
|
265 |
|
|
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED |
266 |
|
|
else if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name)) |
267 |
|
|
{ |
268 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
269 |
|
|
{ |
270 |
|
|
png_push_save_buffer(png_ptr); |
271 |
|
|
return; |
272 |
|
|
} |
273 |
|
|
|
274 |
|
|
if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) |
275 |
|
|
png_ptr->mode |= PNG_HAVE_IDAT; |
276 |
|
|
|
277 |
|
|
png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); |
278 |
|
|
|
279 |
|
|
if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) |
280 |
|
|
png_ptr->mode |= PNG_HAVE_PLTE; |
281 |
|
|
|
282 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) |
283 |
|
|
{ |
284 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
285 |
|
|
png_error(png_ptr, "Missing IHDR before IDAT"); |
286 |
|
|
|
287 |
|
|
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && |
288 |
|
|
!(png_ptr->mode & PNG_HAVE_PLTE)) |
289 |
|
|
png_error(png_ptr, "Missing PLTE before IDAT"); |
290 |
|
|
} |
291 |
|
|
} |
292 |
|
|
|
293 |
|
|
#endif |
294 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4)) |
295 |
|
|
{ |
296 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
297 |
|
|
{ |
298 |
|
|
png_push_save_buffer(png_ptr); |
299 |
|
|
return; |
300 |
|
|
} |
301 |
|
|
png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length); |
302 |
|
|
} |
303 |
|
|
|
304 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) |
305 |
|
|
{ |
306 |
|
|
/* If we reach an IDAT chunk, this means we have read all of the |
307 |
|
|
* header chunks, and we can start reading the image (or if this |
308 |
|
|
* is called after the image has been read - we have an error). |
309 |
|
|
*/ |
310 |
|
|
|
311 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR)) |
312 |
|
|
png_error(png_ptr, "Missing IHDR before IDAT"); |
313 |
|
|
|
314 |
|
|
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && |
315 |
|
|
!(png_ptr->mode & PNG_HAVE_PLTE)) |
316 |
|
|
png_error(png_ptr, "Missing PLTE before IDAT"); |
317 |
|
|
|
318 |
|
|
if (png_ptr->mode & PNG_HAVE_IDAT) |
319 |
|
|
{ |
320 |
|
|
if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) |
321 |
|
|
if (png_ptr->push_length == 0) |
322 |
|
|
return; |
323 |
|
|
|
324 |
|
|
if (png_ptr->mode & PNG_AFTER_IDAT) |
325 |
|
|
png_error(png_ptr, "Too many IDAT's found"); |
326 |
|
|
} |
327 |
|
|
|
328 |
|
|
png_ptr->idat_size = png_ptr->push_length; |
329 |
|
|
png_ptr->mode |= PNG_HAVE_IDAT; |
330 |
|
|
png_ptr->process_mode = PNG_READ_IDAT_MODE; |
331 |
|
|
png_push_have_info(png_ptr, info_ptr); |
332 |
|
|
png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; |
333 |
|
|
png_ptr->zstream.next_out = png_ptr->row_buf; |
334 |
|
|
return; |
335 |
|
|
} |
336 |
|
|
|
337 |
|
|
#if defined(PNG_READ_gAMA_SUPPORTED) |
338 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4)) |
339 |
|
|
{ |
340 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
341 |
|
|
{ |
342 |
|
|
png_push_save_buffer(png_ptr); |
343 |
|
|
return; |
344 |
|
|
} |
345 |
|
|
|
346 |
|
|
png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length); |
347 |
|
|
} |
348 |
|
|
|
349 |
|
|
#endif |
350 |
|
|
#if defined(PNG_READ_sBIT_SUPPORTED) |
351 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4)) |
352 |
|
|
{ |
353 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
354 |
|
|
{ |
355 |
|
|
png_push_save_buffer(png_ptr); |
356 |
|
|
return; |
357 |
|
|
} |
358 |
|
|
|
359 |
|
|
png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length); |
360 |
|
|
} |
361 |
|
|
|
362 |
|
|
#endif |
363 |
|
|
#if defined(PNG_READ_cHRM_SUPPORTED) |
364 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4)) |
365 |
|
|
{ |
366 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
367 |
|
|
{ |
368 |
|
|
png_push_save_buffer(png_ptr); |
369 |
|
|
return; |
370 |
|
|
} |
371 |
|
|
|
372 |
|
|
png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length); |
373 |
|
|
} |
374 |
|
|
|
375 |
|
|
#endif |
376 |
|
|
#if defined(PNG_READ_sRGB_SUPPORTED) |
377 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4)) |
378 |
|
|
{ |
379 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
380 |
|
|
{ |
381 |
|
|
png_push_save_buffer(png_ptr); |
382 |
|
|
return; |
383 |
|
|
} |
384 |
|
|
|
385 |
|
|
png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length); |
386 |
|
|
} |
387 |
|
|
|
388 |
|
|
#endif |
389 |
|
|
#if defined(PNG_READ_iCCP_SUPPORTED) |
390 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_iCCP, 4)) |
391 |
|
|
{ |
392 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
393 |
|
|
{ |
394 |
|
|
png_push_save_buffer(png_ptr); |
395 |
|
|
return; |
396 |
|
|
} |
397 |
|
|
|
398 |
|
|
png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length); |
399 |
|
|
} |
400 |
|
|
|
401 |
|
|
#endif |
402 |
|
|
#if defined(PNG_READ_sPLT_SUPPORTED) |
403 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_sPLT, 4)) |
404 |
|
|
{ |
405 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
406 |
|
|
{ |
407 |
|
|
png_push_save_buffer(png_ptr); |
408 |
|
|
return; |
409 |
|
|
} |
410 |
|
|
|
411 |
|
|
png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length); |
412 |
|
|
} |
413 |
|
|
|
414 |
|
|
#endif |
415 |
|
|
#if defined(PNG_READ_tRNS_SUPPORTED) |
416 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4)) |
417 |
|
|
{ |
418 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
419 |
|
|
{ |
420 |
|
|
png_push_save_buffer(png_ptr); |
421 |
|
|
return; |
422 |
|
|
} |
423 |
|
|
|
424 |
|
|
png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length); |
425 |
|
|
} |
426 |
|
|
|
427 |
|
|
#endif |
428 |
|
|
#if defined(PNG_READ_bKGD_SUPPORTED) |
429 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4)) |
430 |
|
|
{ |
431 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
432 |
|
|
{ |
433 |
|
|
png_push_save_buffer(png_ptr); |
434 |
|
|
return; |
435 |
|
|
} |
436 |
|
|
|
437 |
|
|
png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length); |
438 |
|
|
} |
439 |
|
|
|
440 |
|
|
#endif |
441 |
|
|
#if defined(PNG_READ_hIST_SUPPORTED) |
442 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4)) |
443 |
|
|
{ |
444 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
445 |
|
|
{ |
446 |
|
|
png_push_save_buffer(png_ptr); |
447 |
|
|
return; |
448 |
|
|
} |
449 |
|
|
|
450 |
|
|
png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length); |
451 |
|
|
} |
452 |
|
|
|
453 |
|
|
#endif |
454 |
|
|
#if defined(PNG_READ_pHYs_SUPPORTED) |
455 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4)) |
456 |
|
|
{ |
457 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
458 |
|
|
{ |
459 |
|
|
png_push_save_buffer(png_ptr); |
460 |
|
|
return; |
461 |
|
|
} |
462 |
|
|
|
463 |
|
|
png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length); |
464 |
|
|
} |
465 |
|
|
|
466 |
|
|
#endif |
467 |
|
|
#if defined(PNG_READ_oFFs_SUPPORTED) |
468 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4)) |
469 |
|
|
{ |
470 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
471 |
|
|
{ |
472 |
|
|
png_push_save_buffer(png_ptr); |
473 |
|
|
return; |
474 |
|
|
} |
475 |
|
|
|
476 |
|
|
png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length); |
477 |
|
|
} |
478 |
|
|
#endif |
479 |
|
|
|
480 |
|
|
#if defined(PNG_READ_pCAL_SUPPORTED) |
481 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4)) |
482 |
|
|
{ |
483 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
484 |
|
|
{ |
485 |
|
|
png_push_save_buffer(png_ptr); |
486 |
|
|
return; |
487 |
|
|
} |
488 |
|
|
|
489 |
|
|
png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length); |
490 |
|
|
} |
491 |
|
|
|
492 |
|
|
#endif |
493 |
|
|
#if defined(PNG_READ_sCAL_SUPPORTED) |
494 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_sCAL, 4)) |
495 |
|
|
{ |
496 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
497 |
|
|
{ |
498 |
|
|
png_push_save_buffer(png_ptr); |
499 |
|
|
return; |
500 |
|
|
} |
501 |
|
|
|
502 |
|
|
png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length); |
503 |
|
|
} |
504 |
|
|
|
505 |
|
|
#endif |
506 |
|
|
#if defined(PNG_READ_tIME_SUPPORTED) |
507 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4)) |
508 |
|
|
{ |
509 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
510 |
|
|
{ |
511 |
|
|
png_push_save_buffer(png_ptr); |
512 |
|
|
return; |
513 |
|
|
} |
514 |
|
|
|
515 |
|
|
png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length); |
516 |
|
|
} |
517 |
|
|
|
518 |
|
|
#endif |
519 |
|
|
#if defined(PNG_READ_tEXt_SUPPORTED) |
520 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4)) |
521 |
|
|
{ |
522 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
523 |
|
|
{ |
524 |
|
|
png_push_save_buffer(png_ptr); |
525 |
|
|
return; |
526 |
|
|
} |
527 |
|
|
|
528 |
|
|
png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length); |
529 |
|
|
} |
530 |
|
|
|
531 |
|
|
#endif |
532 |
|
|
#if defined(PNG_READ_zTXt_SUPPORTED) |
533 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4)) |
534 |
|
|
{ |
535 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
536 |
|
|
{ |
537 |
|
|
png_push_save_buffer(png_ptr); |
538 |
|
|
return; |
539 |
|
|
} |
540 |
|
|
|
541 |
|
|
png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length); |
542 |
|
|
} |
543 |
|
|
|
544 |
|
|
#endif |
545 |
|
|
#if defined(PNG_READ_iTXt_SUPPORTED) |
546 |
|
|
else if (!png_memcmp(png_ptr->chunk_name, png_iTXt, 4)) |
547 |
|
|
{ |
548 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
549 |
|
|
{ |
550 |
|
|
png_push_save_buffer(png_ptr); |
551 |
|
|
return; |
552 |
|
|
} |
553 |
|
|
|
554 |
|
|
png_push_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length); |
555 |
|
|
} |
556 |
|
|
|
557 |
|
|
#endif |
558 |
|
|
else |
559 |
|
|
{ |
560 |
|
|
if (png_ptr->push_length + 4 > png_ptr->buffer_size) |
561 |
|
|
{ |
562 |
|
|
png_push_save_buffer(png_ptr); |
563 |
|
|
return; |
564 |
|
|
} |
565 |
|
|
png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length); |
566 |
|
|
} |
567 |
|
|
|
568 |
|
|
png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; |
569 |
|
|
} |
570 |
|
|
|
571 |
|
|
void /* PRIVATE */ |
572 |
|
|
png_push_crc_skip(png_structp png_ptr, png_uint_32 skip) |
573 |
|
|
{ |
574 |
|
|
png_ptr->process_mode = PNG_SKIP_MODE; |
575 |
|
|
png_ptr->skip_length = skip; |
576 |
|
|
} |
577 |
|
|
|
578 |
|
|
void /* PRIVATE */ |
579 |
|
|
png_push_crc_finish(png_structp png_ptr) |
580 |
|
|
{ |
581 |
|
|
if (png_ptr->skip_length && png_ptr->save_buffer_size) |
582 |
|
|
{ |
583 |
|
|
png_size_t save_size; |
584 |
|
|
|
585 |
|
|
if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size) |
586 |
|
|
save_size = (png_size_t)png_ptr->skip_length; |
587 |
|
|
else |
588 |
|
|
save_size = png_ptr->save_buffer_size; |
589 |
|
|
|
590 |
|
|
png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); |
591 |
|
|
|
592 |
|
|
png_ptr->skip_length -= save_size; |
593 |
|
|
png_ptr->buffer_size -= save_size; |
594 |
|
|
png_ptr->save_buffer_size -= save_size; |
595 |
|
|
png_ptr->save_buffer_ptr += save_size; |
596 |
|
|
} |
597 |
|
|
if (png_ptr->skip_length && png_ptr->current_buffer_size) |
598 |
|
|
{ |
599 |
|
|
png_size_t save_size; |
600 |
|
|
|
601 |
|
|
if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size) |
602 |
|
|
save_size = (png_size_t)png_ptr->skip_length; |
603 |
|
|
else |
604 |
|
|
save_size = png_ptr->current_buffer_size; |
605 |
|
|
|
606 |
|
|
png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); |
607 |
|
|
|
608 |
|
|
png_ptr->skip_length -= save_size; |
609 |
|
|
png_ptr->buffer_size -= save_size; |
610 |
|
|
png_ptr->current_buffer_size -= save_size; |
611 |
|
|
png_ptr->current_buffer_ptr += save_size; |
612 |
|
|
} |
613 |
|
|
if (!png_ptr->skip_length) |
614 |
|
|
{ |
615 |
|
|
if (png_ptr->buffer_size < 4) |
616 |
|
|
{ |
617 |
|
|
png_push_save_buffer(png_ptr); |
618 |
|
|
return; |
619 |
|
|
} |
620 |
|
|
|
621 |
|
|
png_crc_finish(png_ptr, 0); |
622 |
|
|
png_ptr->process_mode = PNG_READ_CHUNK_MODE; |
623 |
|
|
} |
624 |
|
|
} |
625 |
|
|
|
626 |
|
|
void PNGAPI |
627 |
|
|
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) |
628 |
|
|
{ |
629 |
|
|
png_bytep ptr; |
630 |
|
|
|
631 |
|
|
if (png_ptr == NULL) |
632 |
|
|
return; |
633 |
|
|
|
634 |
|
|
ptr = buffer; |
635 |
|
|
if (png_ptr->save_buffer_size) |
636 |
|
|
{ |
637 |
|
|
png_size_t save_size; |
638 |
|
|
|
639 |
|
|
if (length < png_ptr->save_buffer_size) |
640 |
|
|
save_size = length; |
641 |
|
|
else |
642 |
|
|
save_size = png_ptr->save_buffer_size; |
643 |
|
|
|
644 |
|
|
png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size); |
645 |
|
|
length -= save_size; |
646 |
|
|
ptr += save_size; |
647 |
|
|
png_ptr->buffer_size -= save_size; |
648 |
|
|
png_ptr->save_buffer_size -= save_size; |
649 |
|
|
png_ptr->save_buffer_ptr += save_size; |
650 |
|
|
} |
651 |
|
|
if (length && png_ptr->current_buffer_size) |
652 |
|
|
{ |
653 |
|
|
png_size_t save_size; |
654 |
|
|
|
655 |
|
|
if (length < png_ptr->current_buffer_size) |
656 |
|
|
save_size = length; |
657 |
|
|
|
658 |
|
|
else |
659 |
|
|
save_size = png_ptr->current_buffer_size; |
660 |
|
|
|
661 |
|
|
png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size); |
662 |
|
|
png_ptr->buffer_size -= save_size; |
663 |
|
|
png_ptr->current_buffer_size -= save_size; |
664 |
|
|
png_ptr->current_buffer_ptr += save_size; |
665 |
|
|
} |
666 |
|
|
} |
667 |
|
|
|
668 |
|
|
void /* PRIVATE */ |
669 |
|
|
png_push_save_buffer(png_structp png_ptr) |
670 |
|
|
{ |
671 |
|
|
if (png_ptr->save_buffer_size) |
672 |
|
|
{ |
673 |
|
|
if (png_ptr->save_buffer_ptr != png_ptr->save_buffer) |
674 |
|
|
{ |
675 |
|
|
png_size_t i, istop; |
676 |
|
|
png_bytep sp; |
677 |
|
|
png_bytep dp; |
678 |
|
|
|
679 |
|
|
istop = png_ptr->save_buffer_size; |
680 |
|
|
for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer; |
681 |
|
|
i < istop; i++, sp++, dp++) |
682 |
|
|
{ |
683 |
|
|
*dp = *sp; |
684 |
|
|
} |
685 |
|
|
} |
686 |
|
|
} |
687 |
|
|
if (png_ptr->save_buffer_size + png_ptr->current_buffer_size > |
688 |
|
|
png_ptr->save_buffer_max) |
689 |
|
|
{ |
690 |
|
|
png_size_t new_max; |
691 |
|
|
png_bytep old_buffer; |
692 |
|
|
|
693 |
|
|
if (png_ptr->save_buffer_size > PNG_SIZE_MAX - |
694 |
|
|
(png_ptr->current_buffer_size + 256)) |
695 |
|
|
{ |
696 |
|
|
png_error(png_ptr, "Potential overflow of save_buffer"); |
697 |
|
|
} |
698 |
|
|
|
699 |
|
|
new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256; |
700 |
|
|
old_buffer = png_ptr->save_buffer; |
701 |
|
|
png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, |
702 |
|
|
(png_uint_32)new_max); |
703 |
|
|
png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); |
704 |
|
|
png_free(png_ptr, old_buffer); |
705 |
|
|
png_ptr->save_buffer_max = new_max; |
706 |
|
|
} |
707 |
|
|
if (png_ptr->current_buffer_size) |
708 |
|
|
{ |
709 |
|
|
png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size, |
710 |
|
|
png_ptr->current_buffer_ptr, png_ptr->current_buffer_size); |
711 |
|
|
png_ptr->save_buffer_size += png_ptr->current_buffer_size; |
712 |
|
|
png_ptr->current_buffer_size = 0; |
713 |
|
|
} |
714 |
|
|
png_ptr->save_buffer_ptr = png_ptr->save_buffer; |
715 |
|
|
png_ptr->buffer_size = 0; |
716 |
|
|
} |
717 |
|
|
|
718 |
|
|
void /* PRIVATE */ |
719 |
|
|
png_push_restore_buffer(png_structp png_ptr, png_bytep buffer, |
720 |
|
|
png_size_t buffer_length) |
721 |
|
|
{ |
722 |
|
|
png_ptr->current_buffer = buffer; |
723 |
|
|
png_ptr->current_buffer_size = buffer_length; |
724 |
|
|
png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size; |
725 |
|
|
png_ptr->current_buffer_ptr = png_ptr->current_buffer; |
726 |
|
|
} |
727 |
|
|
|
728 |
|
|
void /* PRIVATE */ |
729 |
|
|
png_push_read_IDAT(png_structp png_ptr) |
730 |
|
|
{ |
731 |
|
|
#ifdef PNG_USE_LOCAL_ARRAYS |
732 |
|
|
PNG_CONST PNG_IDAT; |
733 |
|
|
#endif |
734 |
|
|
if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER)) |
735 |
|
|
{ |
736 |
|
|
png_byte chunk_length[4]; |
737 |
|
|
|
738 |
|
|
if (png_ptr->buffer_size < 8) |
739 |
|
|
{ |
740 |
|
|
png_push_save_buffer(png_ptr); |
741 |
|
|
return; |
742 |
|
|
} |
743 |
|
|
|
744 |
|
|
png_push_fill_buffer(png_ptr, chunk_length, 4); |
745 |
|
|
png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length); |
746 |
|
|
png_reset_crc(png_ptr); |
747 |
|
|
png_crc_read(png_ptr, png_ptr->chunk_name, 4); |
748 |
|
|
png_ptr->mode |= PNG_HAVE_CHUNK_HEADER; |
749 |
|
|
|
750 |
|
|
if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) |
751 |
|
|
{ |
752 |
|
|
png_ptr->process_mode = PNG_READ_CHUNK_MODE; |
753 |
|
|
if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) |
754 |
|
|
png_error(png_ptr, "Not enough compressed data"); |
755 |
|
|
return; |
756 |
|
|
} |
757 |
|
|
|
758 |
|
|
png_ptr->idat_size = png_ptr->push_length; |
759 |
|
|
} |
760 |
|
|
if (png_ptr->idat_size && png_ptr->save_buffer_size) |
761 |
|
|
{ |
762 |
|
|
png_size_t save_size; |
763 |
|
|
|
764 |
|
|
if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size) |
765 |
|
|
{ |
766 |
|
|
save_size = (png_size_t)png_ptr->idat_size; |
767 |
|
|
|
768 |
|
|
/* Check for overflow */ |
769 |
|
|
if ((png_uint_32)save_size != png_ptr->idat_size) |
770 |
|
|
png_error(png_ptr, "save_size overflowed in pngpread"); |
771 |
|
|
} |
772 |
|
|
else |
773 |
|
|
save_size = png_ptr->save_buffer_size; |
774 |
|
|
|
775 |
|
|
png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); |
776 |
|
|
|
777 |
|
|
if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) |
778 |
|
|
png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size); |
779 |
|
|
|
780 |
|
|
png_ptr->idat_size -= save_size; |
781 |
|
|
png_ptr->buffer_size -= save_size; |
782 |
|
|
png_ptr->save_buffer_size -= save_size; |
783 |
|
|
png_ptr->save_buffer_ptr += save_size; |
784 |
|
|
} |
785 |
|
|
if (png_ptr->idat_size && png_ptr->current_buffer_size) |
786 |
|
|
{ |
787 |
|
|
png_size_t save_size; |
788 |
|
|
|
789 |
|
|
if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size) |
790 |
|
|
{ |
791 |
|
|
save_size = (png_size_t)png_ptr->idat_size; |
792 |
|
|
|
793 |
|
|
/* Check for overflow */ |
794 |
|
|
if ((png_uint_32)save_size != png_ptr->idat_size) |
795 |
|
|
png_error(png_ptr, "save_size overflowed in pngpread"); |
796 |
|
|
} |
797 |
|
|
else |
798 |
|
|
save_size = png_ptr->current_buffer_size; |
799 |
|
|
|
800 |
|
|
png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); |
801 |
|
|
if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED)) |
802 |
|
|
png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size); |
803 |
|
|
|
804 |
|
|
png_ptr->idat_size -= save_size; |
805 |
|
|
png_ptr->buffer_size -= save_size; |
806 |
|
|
png_ptr->current_buffer_size -= save_size; |
807 |
|
|
png_ptr->current_buffer_ptr += save_size; |
808 |
|
|
} |
809 |
|
|
if (!png_ptr->idat_size) |
810 |
|
|
{ |
811 |
|
|
if (png_ptr->buffer_size < 4) |
812 |
|
|
{ |
813 |
|
|
png_push_save_buffer(png_ptr); |
814 |
|
|
return; |
815 |
|
|
} |
816 |
|
|
|
817 |
|
|
png_crc_finish(png_ptr, 0); |
818 |
|
|
png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; |
819 |
|
|
png_ptr->mode |= PNG_AFTER_IDAT; |
820 |
|
|
} |
821 |
|
|
} |
822 |
|
|
|
823 |
|
|
void /* PRIVATE */ |
824 |
|
|
png_process_IDAT_data(png_structp png_ptr, png_bytep buffer, |
825 |
|
|
png_size_t buffer_length) |
826 |
|
|
{ |
827 |
|
|
int ret; |
828 |
|
|
|
829 |
|
|
if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length) |
830 |
|
|
png_error(png_ptr, "Extra compression data"); |
831 |
|
|
|
832 |
|
|
png_ptr->zstream.next_in = buffer; |
833 |
|
|
png_ptr->zstream.avail_in = (uInt)buffer_length; |
834 |
|
|
for (;;) |
835 |
|
|
{ |
836 |
|
|
ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); |
837 |
|
|
if (ret != Z_OK) |
838 |
|
|
{ |
839 |
|
|
if (ret == Z_STREAM_END) |
840 |
|
|
{ |
841 |
|
|
if (png_ptr->zstream.avail_in) |
842 |
|
|
png_error(png_ptr, "Extra compressed data"); |
843 |
|
|
|
844 |
|
|
if (!(png_ptr->zstream.avail_out)) |
845 |
|
|
{ |
846 |
|
|
png_push_process_row(png_ptr); |
847 |
|
|
} |
848 |
|
|
|
849 |
|
|
png_ptr->mode |= PNG_AFTER_IDAT; |
850 |
|
|
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; |
851 |
|
|
break; |
852 |
|
|
} |
853 |
|
|
else if (ret == Z_BUF_ERROR) |
854 |
|
|
break; |
855 |
|
|
|
856 |
|
|
else |
857 |
|
|
png_error(png_ptr, "Decompression Error"); |
858 |
|
|
} |
859 |
|
|
if (!(png_ptr->zstream.avail_out)) |
860 |
|
|
{ |
861 |
|
|
if (( |
862 |
|
|
#if defined(PNG_READ_INTERLACING_SUPPORTED) |
863 |
|
|
png_ptr->interlaced && png_ptr->pass > 6) || |
864 |
|
|
(!png_ptr->interlaced && |
865 |
|
|
#endif |
866 |
|
|
png_ptr->row_number == png_ptr->num_rows)) |
867 |
|
|
{ |
868 |
|
|
if (png_ptr->zstream.avail_in) |
869 |
|
|
png_warning(png_ptr, "Too much data in IDAT chunks"); |
870 |
|
|
png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; |
871 |
|
|
break; |
872 |
|
|
} |
873 |
|
|
png_push_process_row(png_ptr); |
874 |
|
|
png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes; |
875 |
|
|
png_ptr->zstream.next_out = png_ptr->row_buf; |
876 |
|
|
} |
877 |
|
|
|
878 |
|
|
else |
879 |
|
|
break; |
880 |
|
|
} |
881 |
|
|
} |
882 |
|
|
|
883 |
|
|
void /* PRIVATE */ |
884 |
|
|
png_push_process_row(png_structp png_ptr) |
885 |
|
|
{ |
886 |
|
|
png_ptr->row_info.color_type = png_ptr->color_type; |
887 |
|
|
png_ptr->row_info.width = png_ptr->iwidth; |
888 |
|
|
png_ptr->row_info.channels = png_ptr->channels; |
889 |
|
|
png_ptr->row_info.bit_depth = png_ptr->bit_depth; |
890 |
|
|
png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; |
891 |
|
|
|
892 |
|
|
png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, |
893 |
|
|
png_ptr->row_info.width); |
894 |
|
|
|
895 |
|
|
png_read_filter_row(png_ptr, &(png_ptr->row_info), |
896 |
|
|
png_ptr->row_buf + 1, png_ptr->prev_row + 1, |
897 |
|
|
(int)(png_ptr->row_buf[0])); |
898 |
|
|
|
899 |
|
|
png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, |
900 |
|
|
png_ptr->rowbytes + 1); |
901 |
|
|
|
902 |
|
|
if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) |
903 |
|
|
png_do_read_transformations(png_ptr); |
904 |
|
|
|
905 |
|
|
#if defined(PNG_READ_INTERLACING_SUPPORTED) |
906 |
|
|
/* Blow up interlaced rows to full size */ |
907 |
|
|
if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) |
908 |
|
|
{ |
909 |
|
|
if (png_ptr->pass < 6) |
910 |
|
|
/* old interface (pre-1.0.9): |
911 |
|
|
png_do_read_interlace(&(png_ptr->row_info), |
912 |
|
|
png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); |
913 |
|
|
*/ |
914 |
|
|
png_do_read_interlace(png_ptr); |
915 |
|
|
|
916 |
|
|
switch (png_ptr->pass) |
917 |
|
|
{ |
918 |
|
|
case 0: |
919 |
|
|
{ |
920 |
|
|
int i; |
921 |
|
|
for (i = 0; i < 8 && png_ptr->pass == 0; i++) |
922 |
|
|
{ |
923 |
|
|
png_push_have_row(png_ptr, png_ptr->row_buf + 1); |
924 |
|
|
png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */ |
925 |
|
|
} |
926 |
|
|
|
927 |
|
|
if (png_ptr->pass == 2) /* Pass 1 might be empty */ |
928 |
|
|
{ |
929 |
|
|
for (i = 0; i < 4 && png_ptr->pass == 2; i++) |
930 |
|
|
{ |
931 |
|
|
png_push_have_row(png_ptr, png_bytep_NULL); |
932 |
|
|
png_read_push_finish_row(png_ptr); |
933 |
|
|
} |
934 |
|
|
} |
935 |
|
|
|
936 |
|
|
if (png_ptr->pass == 4 && png_ptr->height <= 4) |
937 |
|
|
{ |
938 |
|
|
for (i = 0; i < 2 && png_ptr->pass == 4; i++) |
939 |
|
|
{ |
940 |
|
|
png_push_have_row(png_ptr, png_bytep_NULL); |
941 |
|
|
png_read_push_finish_row(png_ptr); |
942 |
|
|
} |
943 |
|
|
} |
944 |
|
|
|
945 |
|
|
if (png_ptr->pass == 6 && png_ptr->height <= 4) |
946 |
|
|
{ |
947 |
|
|
png_push_have_row(png_ptr, png_bytep_NULL); |
948 |
|
|
png_read_push_finish_row(png_ptr); |
949 |
|
|
} |
950 |
|
|
|
951 |
|
|
break; |
952 |
|
|
} |
953 |
|
|
|
954 |
|
|
case 1: |
955 |
|
|
{ |
956 |
|
|
int i; |
957 |
|
|
for (i = 0; i < 8 && png_ptr->pass == 1; i++) |
958 |
|
|
{ |
959 |
|
|
png_push_have_row(png_ptr, png_ptr->row_buf + 1); |
960 |
|
|
png_read_push_finish_row(png_ptr); |
961 |
|
|
} |
962 |
|
|
|
963 |
|
|
if (png_ptr->pass == 2) /* Skip top 4 generated rows */ |
964 |
|
|
{ |
965 |
|
|
for (i = 0; i < 4 && png_ptr->pass == 2; i++) |
966 |
|
|
{ |
967 |
|
|
png_push_have_row(png_ptr, png_bytep_NULL); |
968 |
|
|
png_read_push_finish_row(png_ptr); |
969 |
|
|
} |
970 |
|
|
} |
971 |
|
|
|
972 |
|
|
break; |
973 |
|
|
} |
974 |
|
|
|
975 |
|
|
case 2: |
976 |
|
|
{ |
977 |
|
|
int i; |
978 |
|
|
|
979 |
|
|
for (i = 0; i < 4 && png_ptr->pass == 2; i++) |
980 |
|
|
{ |
981 |
|
|
png_push_have_row(png_ptr, png_ptr->row_buf + 1); |
982 |
|
|
png_read_push_finish_row(png_ptr); |
983 |
|
|
} |
984 |
|
|
|
985 |
|
|
for (i = 0; i < 4 && png_ptr->pass == 2; i++) |
986 |
|
|
{ |
987 |
|
|
png_push_have_row(png_ptr, png_bytep_NULL); |
988 |
|
|
png_read_push_finish_row(png_ptr); |
989 |
|
|
} |
990 |
|
|
|
991 |
|
|
if (png_ptr->pass == 4) /* Pass 3 might be empty */ |
992 |
|
|
{ |
993 |
|
|
for (i = 0; i < 2 && png_ptr->pass == 4; i++) |
994 |
|
|
{ |
995 |
|
|
png_push_have_row(png_ptr, png_bytep_NULL); |
996 |
|
|
png_read_push_finish_row(png_ptr); |
997 |
|
|
} |
998 |
|
|
} |
999 |
|
|
|
1000 |
|
|
break; |
1001 |
|
|
} |
1002 |
|
|
|
1003 |
|
|
case 3: |
1004 |
|
|
{ |
1005 |
|
|
int i; |
1006 |
|
|
|
1007 |
|
|
for (i = 0; i < 4 && png_ptr->pass == 3; i++) |
1008 |
|
|
{ |
1009 |
|
|
png_push_have_row(png_ptr, png_ptr->row_buf + 1); |
1010 |
|
|
png_read_push_finish_row(png_ptr); |
1011 |
|
|
} |
1012 |
|
|
|
1013 |
|
|
if (png_ptr->pass == 4) /* Skip top two generated rows */ |
1014 |
|
|
{ |
1015 |
|
|
for (i = 0; i < 2 && png_ptr->pass == 4; i++) |
1016 |
|
|
{ |
1017 |
|
|
png_push_have_row(png_ptr, png_bytep_NULL); |
1018 |
|
|
png_read_push_finish_row(png_ptr); |
1019 |
|
|
} |
1020 |
|
|
} |
1021 |
|
|
|
1022 |
|
|
break; |
1023 |
|
|
} |
1024 |
|
|
|
1025 |
|
|
case 4: |
1026 |
|
|
{ |
1027 |
|
|
int i; |
1028 |
|
|
|
1029 |
|
|
for (i = 0; i < 2 && png_ptr->pass == 4; i++) |
1030 |
|
|
{ |
1031 |
|
|
png_push_have_row(png_ptr, png_ptr->row_buf + 1); |
1032 |
|
|
png_read_push_finish_row(png_ptr); |
1033 |
|
|
} |
1034 |
|
|
|
1035 |
|
|
for (i = 0; i < 2 && png_ptr->pass == 4; i++) |
1036 |
|
|
{ |
1037 |
|
|
png_push_have_row(png_ptr, png_bytep_NULL); |
1038 |
|
|
png_read_push_finish_row(png_ptr); |
1039 |
|
|
} |
1040 |
|
|
|
1041 |
|
|
if (png_ptr->pass == 6) /* Pass 5 might be empty */ |
1042 |
|
|
{ |
1043 |
|
|
png_push_have_row(png_ptr, png_bytep_NULL); |
1044 |
|
|
png_read_push_finish_row(png_ptr); |
1045 |
|
|
} |
1046 |
|
|
|
1047 |
|
|
break; |
1048 |
|
|
} |
1049 |
|
|
|
1050 |
|
|
case 5: |
1051 |
|
|
{ |
1052 |
|
|
int i; |
1053 |
|
|
|
1054 |
|
|
for (i = 0; i < 2 && png_ptr->pass == 5; i++) |
1055 |
|
|
{ |
1056 |
|
|
png_push_have_row(png_ptr, png_ptr->row_buf + 1); |
1057 |
|
|
png_read_push_finish_row(png_ptr); |
1058 |
|
|
} |
1059 |
|
|
|
1060 |
|
|
if (png_ptr->pass == 6) /* Skip top generated row */ |
1061 |
|
|
{ |
1062 |
|
|
png_push_have_row(png_ptr, png_bytep_NULL); |
1063 |
|
|
png_read_push_finish_row(png_ptr); |
1064 |
|
|
} |
1065 |
|
|
|
1066 |
|
|
break; |
1067 |
|
|
} |
1068 |
|
|
case 6: |
1069 |
|
|
{ |
1070 |
|
|
png_push_have_row(png_ptr, png_ptr->row_buf + 1); |
1071 |
|
|
png_read_push_finish_row(png_ptr); |
1072 |
|
|
|
1073 |
|
|
if (png_ptr->pass != 6) |
1074 |
|
|
break; |
1075 |
|
|
|
1076 |
|
|
png_push_have_row(png_ptr, png_bytep_NULL); |
1077 |
|
|
png_read_push_finish_row(png_ptr); |
1078 |
|
|
} |
1079 |
|
|
} |
1080 |
|
|
} |
1081 |
|
|
else |
1082 |
|
|
#endif |
1083 |
|
|
{ |
1084 |
|
|
png_push_have_row(png_ptr, png_ptr->row_buf + 1); |
1085 |
|
|
png_read_push_finish_row(png_ptr); |
1086 |
|
|
} |
1087 |
|
|
} |
1088 |
|
|
|
1089 |
|
|
void /* PRIVATE */ |
1090 |
|
|
png_read_push_finish_row(png_structp png_ptr) |
1091 |
|
|
{ |
1092 |
|
|
#ifdef PNG_USE_LOCAL_ARRAYS |
1093 |
|
|
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ |
1094 |
|
|
|
1095 |
|
|
/* Start of interlace block */ |
1096 |
|
|
PNG_CONST int FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0}; |
1097 |
|
|
|
1098 |
|
|
/* Offset to next interlace block */ |
1099 |
|
|
PNG_CONST int FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1}; |
1100 |
|
|
|
1101 |
|
|
/* Start of interlace block in the y direction */ |
1102 |
|
|
PNG_CONST int FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1}; |
1103 |
|
|
|
1104 |
|
|
/* Offset to next interlace block in the y direction */ |
1105 |
|
|
PNG_CONST int FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2}; |
1106 |
|
|
|
1107 |
|
|
/* Height of interlace block. This is not currently used - if you need |
1108 |
|
|
* it, uncomment it here and in png.h |
1109 |
|
|
PNG_CONST int FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1}; |
1110 |
|
|
*/ |
1111 |
|
|
#endif |
1112 |
|
|
|
1113 |
|
|
png_ptr->row_number++; |
1114 |
|
|
if (png_ptr->row_number < png_ptr->num_rows) |
1115 |
|
|
return; |
1116 |
|
|
|
1117 |
|
|
#if defined(PNG_READ_INTERLACING_SUPPORTED) |
1118 |
|
|
if (png_ptr->interlaced) |
1119 |
|
|
{ |
1120 |
|
|
png_ptr->row_number = 0; |
1121 |
|
|
png_memset_check(png_ptr, png_ptr->prev_row, 0, |
1122 |
|
|
png_ptr->rowbytes + 1); |
1123 |
|
|
do |
1124 |
|
|
{ |
1125 |
|
|
png_ptr->pass++; |
1126 |
|
|
if ((png_ptr->pass == 1 && png_ptr->width < 5) || |
1127 |
|
|
(png_ptr->pass == 3 && png_ptr->width < 3) || |
1128 |
|
|
(png_ptr->pass == 5 && png_ptr->width < 2)) |
1129 |
|
|
png_ptr->pass++; |
1130 |
|
|
|
1131 |
|
|
if (png_ptr->pass > 7) |
1132 |
|
|
png_ptr->pass--; |
1133 |
|
|
|
1134 |
|
|
if (png_ptr->pass >= 7) |
1135 |
|
|
break; |
1136 |
|
|
|
1137 |
|
|
png_ptr->iwidth = (png_ptr->width + |
1138 |
|
|
png_pass_inc[png_ptr->pass] - 1 - |
1139 |
|
|
png_pass_start[png_ptr->pass]) / |
1140 |
|
|
png_pass_inc[png_ptr->pass]; |
1141 |
|
|
|
1142 |
|
|
png_ptr->irowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, |
1143 |
|
|
png_ptr->iwidth) + 1; |
1144 |
|
|
|
1145 |
|
|
if (png_ptr->transformations & PNG_INTERLACE) |
1146 |
|
|
break; |
1147 |
|
|
|
1148 |
|
|
png_ptr->num_rows = (png_ptr->height + |
1149 |
|
|
png_pass_yinc[png_ptr->pass] - 1 - |
1150 |
|
|
png_pass_ystart[png_ptr->pass]) / |
1151 |
|
|
png_pass_yinc[png_ptr->pass]; |
1152 |
|
|
|
1153 |
|
|
} while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0); |
1154 |
|
|
} |
1155 |
|
|
#endif /* PNG_READ_INTERLACING_SUPPORTED */ |
1156 |
|
|
} |
1157 |
|
|
|
1158 |
|
|
#if defined(PNG_READ_tEXt_SUPPORTED) |
1159 |
|
|
void /* PRIVATE */ |
1160 |
|
|
png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 |
1161 |
|
|
length) |
1162 |
|
|
{ |
1163 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) |
1164 |
|
|
{ |
1165 |
|
|
png_error(png_ptr, "Out of place tEXt"); |
1166 |
|
|
info_ptr = info_ptr; /* To quiet some compiler warnings */ |
1167 |
|
|
} |
1168 |
|
|
|
1169 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
1170 |
|
|
png_ptr->skip_length = 0; /* This may not be necessary */ |
1171 |
|
|
|
1172 |
|
|
if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ |
1173 |
|
|
{ |
1174 |
|
|
png_warning(png_ptr, "tEXt chunk too large to fit in memory"); |
1175 |
|
|
png_ptr->skip_length = length - (png_uint_32)65535L; |
1176 |
|
|
length = (png_uint_32)65535L; |
1177 |
|
|
} |
1178 |
|
|
#endif |
1179 |
|
|
|
1180 |
|
|
png_ptr->current_text = (png_charp)png_malloc(png_ptr, |
1181 |
|
|
(png_uint_32)(length + 1)); |
1182 |
|
|
png_ptr->current_text[length] = '\0'; |
1183 |
|
|
png_ptr->current_text_ptr = png_ptr->current_text; |
1184 |
|
|
png_ptr->current_text_size = (png_size_t)length; |
1185 |
|
|
png_ptr->current_text_left = (png_size_t)length; |
1186 |
|
|
png_ptr->process_mode = PNG_READ_tEXt_MODE; |
1187 |
|
|
} |
1188 |
|
|
|
1189 |
|
|
void /* PRIVATE */ |
1190 |
|
|
png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr) |
1191 |
|
|
{ |
1192 |
|
|
if (png_ptr->buffer_size && png_ptr->current_text_left) |
1193 |
|
|
{ |
1194 |
|
|
png_size_t text_size; |
1195 |
|
|
|
1196 |
|
|
if (png_ptr->buffer_size < png_ptr->current_text_left) |
1197 |
|
|
text_size = png_ptr->buffer_size; |
1198 |
|
|
|
1199 |
|
|
else |
1200 |
|
|
text_size = png_ptr->current_text_left; |
1201 |
|
|
|
1202 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); |
1203 |
|
|
png_ptr->current_text_left -= text_size; |
1204 |
|
|
png_ptr->current_text_ptr += text_size; |
1205 |
|
|
} |
1206 |
|
|
if (!(png_ptr->current_text_left)) |
1207 |
|
|
{ |
1208 |
|
|
png_textp text_ptr; |
1209 |
|
|
png_charp text; |
1210 |
|
|
png_charp key; |
1211 |
|
|
int ret; |
1212 |
|
|
|
1213 |
|
|
if (png_ptr->buffer_size < 4) |
1214 |
|
|
{ |
1215 |
|
|
png_push_save_buffer(png_ptr); |
1216 |
|
|
return; |
1217 |
|
|
} |
1218 |
|
|
|
1219 |
|
|
png_push_crc_finish(png_ptr); |
1220 |
|
|
|
1221 |
|
|
#if defined(PNG_MAX_MALLOC_64K) |
1222 |
|
|
if (png_ptr->skip_length) |
1223 |
|
|
return; |
1224 |
|
|
#endif |
1225 |
|
|
|
1226 |
|
|
key = png_ptr->current_text; |
1227 |
|
|
|
1228 |
|
|
for (text = key; *text; text++) |
1229 |
|
|
/* Empty loop */ ; |
1230 |
|
|
|
1231 |
|
|
if (text < key + png_ptr->current_text_size) |
1232 |
|
|
text++; |
1233 |
|
|
|
1234 |
|
|
text_ptr = (png_textp)png_malloc(png_ptr, |
1235 |
|
|
(png_uint_32)png_sizeof(png_text)); |
1236 |
|
|
text_ptr->compression = PNG_TEXT_COMPRESSION_NONE; |
1237 |
|
|
text_ptr->key = key; |
1238 |
|
|
#ifdef PNG_iTXt_SUPPORTED |
1239 |
|
|
text_ptr->lang = NULL; |
1240 |
|
|
text_ptr->lang_key = NULL; |
1241 |
|
|
#endif |
1242 |
|
|
text_ptr->text = text; |
1243 |
|
|
|
1244 |
|
|
ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); |
1245 |
|
|
|
1246 |
|
|
png_free(png_ptr, key); |
1247 |
|
|
png_free(png_ptr, text_ptr); |
1248 |
|
|
png_ptr->current_text = NULL; |
1249 |
|
|
|
1250 |
|
|
if (ret) |
1251 |
|
|
png_warning(png_ptr, "Insufficient memory to store text chunk."); |
1252 |
|
|
} |
1253 |
|
|
} |
1254 |
|
|
#endif |
1255 |
|
|
|
1256 |
|
|
#if defined(PNG_READ_zTXt_SUPPORTED) |
1257 |
|
|
void /* PRIVATE */ |
1258 |
|
|
png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 |
1259 |
|
|
length) |
1260 |
|
|
{ |
1261 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) |
1262 |
|
|
{ |
1263 |
|
|
png_error(png_ptr, "Out of place zTXt"); |
1264 |
|
|
info_ptr = info_ptr; /* To quiet some compiler warnings */ |
1265 |
|
|
} |
1266 |
|
|
|
1267 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
1268 |
|
|
/* We can't handle zTXt chunks > 64K, since we don't have enough space |
1269 |
|
|
* to be able to store the uncompressed data. Actually, the threshold |
1270 |
|
|
* is probably around 32K, but it isn't as definite as 64K is. |
1271 |
|
|
*/ |
1272 |
|
|
if (length > (png_uint_32)65535L) |
1273 |
|
|
{ |
1274 |
|
|
png_warning(png_ptr, "zTXt chunk too large to fit in memory"); |
1275 |
|
|
png_push_crc_skip(png_ptr, length); |
1276 |
|
|
return; |
1277 |
|
|
} |
1278 |
|
|
#endif |
1279 |
|
|
|
1280 |
|
|
png_ptr->current_text = (png_charp)png_malloc(png_ptr, |
1281 |
|
|
(png_uint_32)(length + 1)); |
1282 |
|
|
png_ptr->current_text[length] = '\0'; |
1283 |
|
|
png_ptr->current_text_ptr = png_ptr->current_text; |
1284 |
|
|
png_ptr->current_text_size = (png_size_t)length; |
1285 |
|
|
png_ptr->current_text_left = (png_size_t)length; |
1286 |
|
|
png_ptr->process_mode = PNG_READ_zTXt_MODE; |
1287 |
|
|
} |
1288 |
|
|
|
1289 |
|
|
void /* PRIVATE */ |
1290 |
|
|
png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr) |
1291 |
|
|
{ |
1292 |
|
|
if (png_ptr->buffer_size && png_ptr->current_text_left) |
1293 |
|
|
{ |
1294 |
|
|
png_size_t text_size; |
1295 |
|
|
|
1296 |
|
|
if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left) |
1297 |
|
|
text_size = png_ptr->buffer_size; |
1298 |
|
|
|
1299 |
|
|
else |
1300 |
|
|
text_size = png_ptr->current_text_left; |
1301 |
|
|
|
1302 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); |
1303 |
|
|
png_ptr->current_text_left -= text_size; |
1304 |
|
|
png_ptr->current_text_ptr += text_size; |
1305 |
|
|
} |
1306 |
|
|
if (!(png_ptr->current_text_left)) |
1307 |
|
|
{ |
1308 |
|
|
png_textp text_ptr; |
1309 |
|
|
png_charp text; |
1310 |
|
|
png_charp key; |
1311 |
|
|
int ret; |
1312 |
|
|
png_size_t text_size, key_size; |
1313 |
|
|
|
1314 |
|
|
if (png_ptr->buffer_size < 4) |
1315 |
|
|
{ |
1316 |
|
|
png_push_save_buffer(png_ptr); |
1317 |
|
|
return; |
1318 |
|
|
} |
1319 |
|
|
|
1320 |
|
|
png_push_crc_finish(png_ptr); |
1321 |
|
|
|
1322 |
|
|
key = png_ptr->current_text; |
1323 |
|
|
|
1324 |
|
|
for (text = key; *text; text++) |
1325 |
|
|
/* Empty loop */ ; |
1326 |
|
|
|
1327 |
|
|
/* zTXt can't have zero text */ |
1328 |
|
|
if (text >= key + png_ptr->current_text_size) |
1329 |
|
|
{ |
1330 |
|
|
png_ptr->current_text = NULL; |
1331 |
|
|
png_free(png_ptr, key); |
1332 |
|
|
return; |
1333 |
|
|
} |
1334 |
|
|
|
1335 |
|
|
text++; |
1336 |
|
|
|
1337 |
|
|
if (*text != PNG_TEXT_COMPRESSION_zTXt) /* Check compression byte */ |
1338 |
|
|
{ |
1339 |
|
|
png_ptr->current_text = NULL; |
1340 |
|
|
png_free(png_ptr, key); |
1341 |
|
|
return; |
1342 |
|
|
} |
1343 |
|
|
|
1344 |
|
|
text++; |
1345 |
|
|
|
1346 |
|
|
png_ptr->zstream.next_in = (png_bytep )text; |
1347 |
|
|
png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size - |
1348 |
|
|
(text - key)); |
1349 |
|
|
png_ptr->zstream.next_out = png_ptr->zbuf; |
1350 |
|
|
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |
1351 |
|
|
|
1352 |
|
|
key_size = text - key; |
1353 |
|
|
text_size = 0; |
1354 |
|
|
text = NULL; |
1355 |
|
|
ret = Z_STREAM_END; |
1356 |
|
|
|
1357 |
|
|
while (png_ptr->zstream.avail_in) |
1358 |
|
|
{ |
1359 |
|
|
ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); |
1360 |
|
|
if (ret != Z_OK && ret != Z_STREAM_END) |
1361 |
|
|
{ |
1362 |
|
|
inflateReset(&png_ptr->zstream); |
1363 |
|
|
png_ptr->zstream.avail_in = 0; |
1364 |
|
|
png_ptr->current_text = NULL; |
1365 |
|
|
png_free(png_ptr, key); |
1366 |
|
|
png_free(png_ptr, text); |
1367 |
|
|
return; |
1368 |
|
|
} |
1369 |
|
|
if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END) |
1370 |
|
|
{ |
1371 |
|
|
if (text == NULL) |
1372 |
|
|
{ |
1373 |
|
|
text = (png_charp)png_malloc(png_ptr, |
1374 |
|
|
(png_uint_32)(png_ptr->zbuf_size |
1375 |
|
|
- png_ptr->zstream.avail_out + key_size + 1)); |
1376 |
|
|
|
1377 |
|
|
png_memcpy(text + key_size, png_ptr->zbuf, |
1378 |
|
|
png_ptr->zbuf_size - png_ptr->zstream.avail_out); |
1379 |
|
|
|
1380 |
|
|
png_memcpy(text, key, key_size); |
1381 |
|
|
|
1382 |
|
|
text_size = key_size + png_ptr->zbuf_size - |
1383 |
|
|
png_ptr->zstream.avail_out; |
1384 |
|
|
|
1385 |
|
|
*(text + text_size) = '\0'; |
1386 |
|
|
} |
1387 |
|
|
else |
1388 |
|
|
{ |
1389 |
|
|
png_charp tmp; |
1390 |
|
|
|
1391 |
|
|
tmp = text; |
1392 |
|
|
text = (png_charp)png_malloc(png_ptr, text_size + |
1393 |
|
|
(png_uint_32)(png_ptr->zbuf_size |
1394 |
|
|
- png_ptr->zstream.avail_out + 1)); |
1395 |
|
|
|
1396 |
|
|
png_memcpy(text, tmp, text_size); |
1397 |
|
|
png_free(png_ptr, tmp); |
1398 |
|
|
|
1399 |
|
|
png_memcpy(text + text_size, png_ptr->zbuf, |
1400 |
|
|
png_ptr->zbuf_size - png_ptr->zstream.avail_out); |
1401 |
|
|
|
1402 |
|
|
text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out; |
1403 |
|
|
*(text + text_size) = '\0'; |
1404 |
|
|
} |
1405 |
|
|
if (ret != Z_STREAM_END) |
1406 |
|
|
{ |
1407 |
|
|
png_ptr->zstream.next_out = png_ptr->zbuf; |
1408 |
|
|
png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; |
1409 |
|
|
} |
1410 |
|
|
} |
1411 |
|
|
else |
1412 |
|
|
{ |
1413 |
|
|
break; |
1414 |
|
|
} |
1415 |
|
|
|
1416 |
|
|
if (ret == Z_STREAM_END) |
1417 |
|
|
break; |
1418 |
|
|
} |
1419 |
|
|
|
1420 |
|
|
inflateReset(&png_ptr->zstream); |
1421 |
|
|
png_ptr->zstream.avail_in = 0; |
1422 |
|
|
|
1423 |
|
|
if (ret != Z_STREAM_END) |
1424 |
|
|
{ |
1425 |
|
|
png_ptr->current_text = NULL; |
1426 |
|
|
png_free(png_ptr, key); |
1427 |
|
|
png_free(png_ptr, text); |
1428 |
|
|
return; |
1429 |
|
|
} |
1430 |
|
|
|
1431 |
|
|
png_ptr->current_text = NULL; |
1432 |
|
|
png_free(png_ptr, key); |
1433 |
|
|
key = text; |
1434 |
|
|
text += key_size; |
1435 |
|
|
|
1436 |
|
|
text_ptr = (png_textp)png_malloc(png_ptr, |
1437 |
|
|
(png_uint_32)png_sizeof(png_text)); |
1438 |
|
|
text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt; |
1439 |
|
|
text_ptr->key = key; |
1440 |
|
|
#ifdef PNG_iTXt_SUPPORTED |
1441 |
|
|
text_ptr->lang = NULL; |
1442 |
|
|
text_ptr->lang_key = NULL; |
1443 |
|
|
#endif |
1444 |
|
|
text_ptr->text = text; |
1445 |
|
|
|
1446 |
|
|
ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); |
1447 |
|
|
|
1448 |
|
|
png_free(png_ptr, key); |
1449 |
|
|
png_free(png_ptr, text_ptr); |
1450 |
|
|
|
1451 |
|
|
if (ret) |
1452 |
|
|
png_warning(png_ptr, "Insufficient memory to store text chunk."); |
1453 |
|
|
} |
1454 |
|
|
} |
1455 |
|
|
#endif |
1456 |
|
|
|
1457 |
|
|
#if defined(PNG_READ_iTXt_SUPPORTED) |
1458 |
|
|
void /* PRIVATE */ |
1459 |
|
|
png_push_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 |
1460 |
|
|
length) |
1461 |
|
|
{ |
1462 |
|
|
if (!(png_ptr->mode & PNG_HAVE_IHDR) || (png_ptr->mode & PNG_HAVE_IEND)) |
1463 |
|
|
{ |
1464 |
|
|
png_error(png_ptr, "Out of place iTXt"); |
1465 |
|
|
info_ptr = info_ptr; /* To quiet some compiler warnings */ |
1466 |
|
|
} |
1467 |
|
|
|
1468 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
1469 |
|
|
png_ptr->skip_length = 0; /* This may not be necessary */ |
1470 |
|
|
|
1471 |
|
|
if (length > (png_uint_32)65535L) /* Can't hold entire string in memory */ |
1472 |
|
|
{ |
1473 |
|
|
png_warning(png_ptr, "iTXt chunk too large to fit in memory"); |
1474 |
|
|
png_ptr->skip_length = length - (png_uint_32)65535L; |
1475 |
|
|
length = (png_uint_32)65535L; |
1476 |
|
|
} |
1477 |
|
|
#endif |
1478 |
|
|
|
1479 |
|
|
png_ptr->current_text = (png_charp)png_malloc(png_ptr, |
1480 |
|
|
(png_uint_32)(length + 1)); |
1481 |
|
|
png_ptr->current_text[length] = '\0'; |
1482 |
|
|
png_ptr->current_text_ptr = png_ptr->current_text; |
1483 |
|
|
png_ptr->current_text_size = (png_size_t)length; |
1484 |
|
|
png_ptr->current_text_left = (png_size_t)length; |
1485 |
|
|
png_ptr->process_mode = PNG_READ_iTXt_MODE; |
1486 |
|
|
} |
1487 |
|
|
|
1488 |
|
|
void /* PRIVATE */ |
1489 |
|
|
png_push_read_iTXt(png_structp png_ptr, png_infop info_ptr) |
1490 |
|
|
{ |
1491 |
|
|
|
1492 |
|
|
if (png_ptr->buffer_size && png_ptr->current_text_left) |
1493 |
|
|
{ |
1494 |
|
|
png_size_t text_size; |
1495 |
|
|
|
1496 |
|
|
if (png_ptr->buffer_size < png_ptr->current_text_left) |
1497 |
|
|
text_size = png_ptr->buffer_size; |
1498 |
|
|
|
1499 |
|
|
else |
1500 |
|
|
text_size = png_ptr->current_text_left; |
1501 |
|
|
|
1502 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size); |
1503 |
|
|
png_ptr->current_text_left -= text_size; |
1504 |
|
|
png_ptr->current_text_ptr += text_size; |
1505 |
|
|
} |
1506 |
|
|
if (!(png_ptr->current_text_left)) |
1507 |
|
|
{ |
1508 |
|
|
png_textp text_ptr; |
1509 |
|
|
png_charp key; |
1510 |
|
|
int comp_flag; |
1511 |
|
|
png_charp lang; |
1512 |
|
|
png_charp lang_key; |
1513 |
|
|
png_charp text; |
1514 |
|
|
int ret; |
1515 |
|
|
|
1516 |
|
|
if (png_ptr->buffer_size < 4) |
1517 |
|
|
{ |
1518 |
|
|
png_push_save_buffer(png_ptr); |
1519 |
|
|
return; |
1520 |
|
|
} |
1521 |
|
|
|
1522 |
|
|
png_push_crc_finish(png_ptr); |
1523 |
|
|
|
1524 |
|
|
#if defined(PNG_MAX_MALLOC_64K) |
1525 |
|
|
if (png_ptr->skip_length) |
1526 |
|
|
return; |
1527 |
|
|
#endif |
1528 |
|
|
|
1529 |
|
|
key = png_ptr->current_text; |
1530 |
|
|
|
1531 |
|
|
for (lang = key; *lang; lang++) |
1532 |
|
|
/* Empty loop */ ; |
1533 |
|
|
|
1534 |
|
|
if (lang < key + png_ptr->current_text_size - 3) |
1535 |
|
|
lang++; |
1536 |
|
|
|
1537 |
|
|
comp_flag = *lang++; |
1538 |
|
|
lang++; /* Skip comp_type, always zero */ |
1539 |
|
|
|
1540 |
|
|
for (lang_key = lang; *lang_key; lang_key++) |
1541 |
|
|
/* Empty loop */ ; |
1542 |
|
|
|
1543 |
|
|
lang_key++; /* Skip NUL separator */ |
1544 |
|
|
|
1545 |
|
|
text=lang_key; |
1546 |
|
|
|
1547 |
|
|
if (lang_key < key + png_ptr->current_text_size - 1) |
1548 |
|
|
{ |
1549 |
|
|
for (; *text; text++) |
1550 |
|
|
/* Empty loop */ ; |
1551 |
|
|
} |
1552 |
|
|
|
1553 |
|
|
if (text < key + png_ptr->current_text_size) |
1554 |
|
|
text++; |
1555 |
|
|
|
1556 |
|
|
text_ptr = (png_textp)png_malloc(png_ptr, |
1557 |
|
|
(png_uint_32)png_sizeof(png_text)); |
1558 |
|
|
|
1559 |
|
|
text_ptr->compression = comp_flag + 2; |
1560 |
|
|
text_ptr->key = key; |
1561 |
|
|
text_ptr->lang = lang; |
1562 |
|
|
text_ptr->lang_key = lang_key; |
1563 |
|
|
text_ptr->text = text; |
1564 |
|
|
text_ptr->text_length = 0; |
1565 |
|
|
text_ptr->itxt_length = png_strlen(text); |
1566 |
|
|
|
1567 |
|
|
ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1); |
1568 |
|
|
|
1569 |
|
|
png_ptr->current_text = NULL; |
1570 |
|
|
|
1571 |
|
|
png_free(png_ptr, text_ptr); |
1572 |
|
|
if (ret) |
1573 |
|
|
png_warning(png_ptr, "Insufficient memory to store iTXt chunk."); |
1574 |
|
|
} |
1575 |
|
|
} |
1576 |
|
|
#endif |
1577 |
|
|
|
1578 |
|
|
/* This function is called when we haven't found a handler for this |
1579 |
|
|
* chunk. If there isn't a problem with the chunk itself (ie a bad chunk |
1580 |
|
|
* name or a critical chunk), the chunk is (currently) silently ignored. |
1581 |
|
|
*/ |
1582 |
|
|
void /* PRIVATE */ |
1583 |
|
|
png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 |
1584 |
|
|
length) |
1585 |
|
|
{ |
1586 |
|
|
png_uint_32 skip = 0; |
1587 |
|
|
|
1588 |
|
|
if (!(png_ptr->chunk_name[0] & 0x20)) |
1589 |
|
|
{ |
1590 |
|
|
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) |
1591 |
|
|
if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != |
1592 |
|
|
PNG_HANDLE_CHUNK_ALWAYS |
1593 |
|
|
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) |
1594 |
|
|
&& png_ptr->read_user_chunk_fn == NULL |
1595 |
|
|
#endif |
1596 |
|
|
) |
1597 |
|
|
#endif |
1598 |
|
|
png_chunk_error(png_ptr, "unknown critical chunk"); |
1599 |
|
|
|
1600 |
|
|
info_ptr = info_ptr; /* To quiet some compiler warnings */ |
1601 |
|
|
} |
1602 |
|
|
|
1603 |
|
|
#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) |
1604 |
|
|
if (png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS) |
1605 |
|
|
{ |
1606 |
|
|
#ifdef PNG_MAX_MALLOC_64K |
1607 |
|
|
if (length > (png_uint_32)65535L) |
1608 |
|
|
{ |
1609 |
|
|
png_warning(png_ptr, "unknown chunk too large to fit in memory"); |
1610 |
|
|
skip = length - (png_uint_32)65535L; |
1611 |
|
|
length = (png_uint_32)65535L; |
1612 |
|
|
} |
1613 |
|
|
#endif |
1614 |
|
|
png_memcpy((png_charp)png_ptr->unknown_chunk.name, |
1615 |
|
|
(png_charp)png_ptr->chunk_name, |
1616 |
|
|
png_sizeof(png_ptr->unknown_chunk.name)); |
1617 |
|
|
png_ptr->unknown_chunk.name[png_sizeof(png_ptr->unknown_chunk.name) - 1] |
1618 |
|
|
= '\0'; |
1619 |
|
|
|
1620 |
|
|
png_ptr->unknown_chunk.size = (png_size_t)length; |
1621 |
|
|
|
1622 |
|
|
if (length == 0) |
1623 |
|
|
png_ptr->unknown_chunk.data = NULL; |
1624 |
|
|
|
1625 |
|
|
else |
1626 |
|
|
{ |
1627 |
|
|
png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, |
1628 |
|
|
(png_uint_32)length); |
1629 |
|
|
png_crc_read(png_ptr, (png_bytep)png_ptr->unknown_chunk.data, length); |
1630 |
|
|
} |
1631 |
|
|
|
1632 |
|
|
#if defined(PNG_READ_USER_CHUNKS_SUPPORTED) |
1633 |
|
|
if (png_ptr->read_user_chunk_fn != NULL) |
1634 |
|
|
{ |
1635 |
|
|
/* Callback to user unknown chunk handler */ |
1636 |
|
|
int ret; |
1637 |
|
|
ret = (*(png_ptr->read_user_chunk_fn)) |
1638 |
|
|
(png_ptr, &png_ptr->unknown_chunk); |
1639 |
|
|
|
1640 |
|
|
if (ret < 0) |
1641 |
|
|
png_chunk_error(png_ptr, "error in user chunk"); |
1642 |
|
|
|
1643 |
|
|
if (ret == 0) |
1644 |
|
|
{ |
1645 |
|
|
if (!(png_ptr->chunk_name[0] & 0x20)) |
1646 |
|
|
if (png_handle_as_unknown(png_ptr, png_ptr->chunk_name) != |
1647 |
|
|
PNG_HANDLE_CHUNK_ALWAYS) |
1648 |
|
|
png_chunk_error(png_ptr, "unknown critical chunk"); |
1649 |
|
|
png_set_unknown_chunks(png_ptr, info_ptr, |
1650 |
|
|
&png_ptr->unknown_chunk, 1); |
1651 |
|
|
} |
1652 |
|
|
} |
1653 |
|
|
|
1654 |
|
|
else |
1655 |
|
|
#endif |
1656 |
|
|
png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1); |
1657 |
|
|
png_free(png_ptr, png_ptr->unknown_chunk.data); |
1658 |
|
|
png_ptr->unknown_chunk.data = NULL; |
1659 |
|
|
} |
1660 |
|
|
|
1661 |
|
|
else |
1662 |
|
|
#endif |
1663 |
|
|
skip=length; |
1664 |
|
|
png_push_crc_skip(png_ptr, skip); |
1665 |
|
|
} |
1666 |
|
|
|
1667 |
|
|
void /* PRIVATE */ |
1668 |
|
|
png_push_have_info(png_structp png_ptr, png_infop info_ptr) |
1669 |
|
|
{ |
1670 |
|
|
if (png_ptr->info_fn != NULL) |
1671 |
|
|
(*(png_ptr->info_fn))(png_ptr, info_ptr); |
1672 |
|
|
} |
1673 |
|
|
|
1674 |
|
|
void /* PRIVATE */ |
1675 |
|
|
png_push_have_end(png_structp png_ptr, png_infop info_ptr) |
1676 |
|
|
{ |
1677 |
|
|
if (png_ptr->end_fn != NULL) |
1678 |
|
|
(*(png_ptr->end_fn))(png_ptr, info_ptr); |
1679 |
|
|
} |
1680 |
|
|
|
1681 |
|
|
void /* PRIVATE */ |
1682 |
|
|
png_push_have_row(png_structp png_ptr, png_bytep row) |
1683 |
|
|
{ |
1684 |
|
|
if (png_ptr->row_fn != NULL) |
1685 |
|
|
(*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number, |
1686 |
|
|
(int)png_ptr->pass); |
1687 |
|
|
} |
1688 |
|
|
|
1689 |
|
|
void PNGAPI |
1690 |
|
|
png_progressive_combine_row (png_structp png_ptr, |
1691 |
|
|
png_bytep old_row, png_bytep new_row) |
1692 |
|
|
{ |
1693 |
|
|
#ifdef PNG_USE_LOCAL_ARRAYS |
1694 |
|
|
PNG_CONST int FARDATA png_pass_dsp_mask[7] = |
1695 |
|
|
{0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff}; |
1696 |
|
|
#endif |
1697 |
|
|
if (png_ptr == NULL) |
1698 |
|
|
return; |
1699 |
|
|
|
1700 |
|
|
if (new_row != NULL) /* new_row must == png_ptr->row_buf here. */ |
1701 |
|
|
png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]); |
1702 |
|
|
} |
1703 |
|
|
|
1704 |
|
|
void PNGAPI |
1705 |
|
|
png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr, |
1706 |
|
|
png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn, |
1707 |
|
|
png_progressive_end_ptr end_fn) |
1708 |
|
|
{ |
1709 |
|
|
if (png_ptr == NULL) |
1710 |
|
|
return; |
1711 |
|
|
|
1712 |
|
|
png_ptr->info_fn = info_fn; |
1713 |
|
|
png_ptr->row_fn = row_fn; |
1714 |
|
|
png_ptr->end_fn = end_fn; |
1715 |
|
|
|
1716 |
|
|
png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer); |
1717 |
|
|
} |
1718 |
|
|
|
1719 |
|
|
png_voidp PNGAPI |
1720 |
|
|
png_get_progressive_ptr(png_structp png_ptr) |
1721 |
|
|
{ |
1722 |
|
|
if (png_ptr == NULL) |
1723 |
|
|
return (NULL); |
1724 |
|
|
|
1725 |
|
|
return png_ptr->io_ptr; |
1726 |
|
|
} |
1727 |
|
|
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ |