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