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