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