pngpread.c 31.5 KB
Newer Older
G
Guy Schalnat 已提交
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 7
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (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
 */
G
Guy Schalnat 已提交
13

14
#include "pngpriv.h"
G
Guy Schalnat 已提交
15

16 17
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED

18
/* Push model modes */
19 20 21 22 23 24 25 26 27
#define PNG_READ_SIG_MODE   0
#define PNG_READ_CHUNK_MODE 1
#define PNG_READ_IDAT_MODE  2
#define PNG_READ_tEXt_MODE  4
#define PNG_READ_zTXt_MODE  5
#define PNG_READ_DONE_MODE  6
#define PNG_READ_iTXt_MODE  7
#define PNG_ERROR_MODE      8

28 29 30
#define PNG_PUSH_SAVE_BUFFER_IF_FULL \
if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
   { png_push_save_buffer(png_ptr); return; }
31
#define PNG_PUSH_SAVE_BUFFER_IF_LT(N) \
32 33 34
if (png_ptr->buffer_size < N) \
   { png_push_save_buffer(png_ptr); return; }

35
void PNGAPI
36
png_process_data(png_structrp png_ptr, png_inforp info_ptr,
37
    png_bytep buffer, png_size_t buffer_size)
G
Guy Schalnat 已提交
38
{
39 40 41
   if (png_ptr == NULL || info_ptr == NULL)
      return;

G
Guy Schalnat 已提交
42
   png_push_restore_buffer(png_ptr, buffer, buffer_size);
G
Guy Schalnat 已提交
43

G
Guy Schalnat 已提交
44 45
   while (png_ptr->buffer_size)
   {
A
Andreas Dilger 已提交
46
      png_process_some_data(png_ptr, info_ptr);
G
Guy Schalnat 已提交
47
   }
G
Guy Schalnat 已提交
48 49
}

50
png_size_t PNGAPI
51
png_process_data_pause(png_structrp png_ptr, int save)
52 53 54
{
   if (png_ptr != NULL)
   {
55
      /* It's easiest for the caller if we do the save; then the caller doesn't
56 57
       * have to supply the same data again:
       */
58
      if (save != 0)
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
         png_push_save_buffer(png_ptr);
      else
      {
         /* This includes any pending saved bytes: */
         png_size_t remaining = png_ptr->buffer_size;
         png_ptr->buffer_size = 0;

         /* So subtract the saved buffer size, unless all the data
          * is actually 'saved', in which case we just return 0
          */
         if (png_ptr->save_buffer_size < remaining)
            return remaining - png_ptr->save_buffer_size;
      }
   }

   return 0;
}

png_uint_32 PNGAPI
78
png_process_data_skip(png_structrp png_ptr)
79
{
80 81 82 83 84
/* TODO: Deprecate and remove this API.
 * Somewhere the implementation of this seems to have been lost,
 * or abandoned.  It was only to support some internal back-door access
 * to png_struct) in libpng-1.4.x.
 */
85 86 87
   png_app_warning(png_ptr,
"png_process_data_skip is not implemented in any current version of libpng");
   return 0;
88 89
}

A
Andreas Dilger 已提交
90 91 92
/* What we do with the incoming data depends on what we were previously
 * doing before we ran out of data...
 */
93
void /* PRIVATE */
94
png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
G
Guy Schalnat 已提交
95
{
96 97 98
   if (png_ptr == NULL)
      return;

G
Guy Schalnat 已提交
99 100 101 102
   switch (png_ptr->process_mode)
   {
      case PNG_READ_SIG_MODE:
      {
A
Andreas Dilger 已提交
103
         png_push_read_sig(png_ptr, info_ptr);
G
Guy Schalnat 已提交
104 105
         break;
      }
106

G
Guy Schalnat 已提交
107 108
      case PNG_READ_CHUNK_MODE:
      {
A
Andreas Dilger 已提交
109
         png_push_read_chunk(png_ptr, info_ptr);
G
Guy Schalnat 已提交
110 111
         break;
      }
112

G
Guy Schalnat 已提交
113 114
      case PNG_READ_IDAT_MODE:
      {
G
Guy Schalnat 已提交
115
         png_push_read_IDAT(png_ptr);
G
Guy Schalnat 已提交
116 117
         break;
      }
118

G
Guy Schalnat 已提交
119 120 121 122 123 124
      default:
      {
         png_ptr->buffer_size = 0;
         break;
      }
   }
G
Guy Schalnat 已提交
125 126
}

A
Andreas Dilger 已提交
127 128
/* Read any remaining signature bytes from the stream and compare them with
 * the correct PNG signature.  It is possible that this routine is called
129 130 131
 * with bytes already read from the signature, either because they have been
 * checked by the calling application, or because of multiple calls to this
 * routine.
A
Andreas Dilger 已提交
132
 */
133
void /* PRIVATE */
134
png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
G
Guy Schalnat 已提交
135
{
136
   png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */
137
       num_to_check = 8 - num_checked;
G
Guy Schalnat 已提交
138

A
Andreas Dilger 已提交
139
   if (png_ptr->buffer_size < num_to_check)
G
Guy Schalnat 已提交
140
   {
A
Andreas Dilger 已提交
141
      num_to_check = png_ptr->buffer_size;
G
Guy Schalnat 已提交
142 143
   }

144
   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]),
145
       num_to_check);
146
   png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
G
Guy Schalnat 已提交
147

A
Andreas Dilger 已提交
148
   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
G
Guy Schalnat 已提交
149
   {
A
Andreas Dilger 已提交
150 151 152
      if (num_checked < 4 &&
          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
         png_error(png_ptr, "Not a PNG file");
153

A
Andreas Dilger 已提交
154 155
      else
         png_error(png_ptr, "PNG file corrupted by ASCII conversion");
G
Guy Schalnat 已提交
156 157 158
   }
   else
   {
A
Andreas Dilger 已提交
159 160 161 162
      if (png_ptr->sig_bytes >= 8)
      {
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
      }
G
Guy Schalnat 已提交
163
   }
G
Guy Schalnat 已提交
164 165
}

166
void /* PRIVATE */
167
png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
G
Guy Schalnat 已提交
168
{
169
   png_uint_32 chunk_name;
170
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
171 172
   int keep; /* unknown handling method */
#endif
173

174 175
   /* First we make sure we have enough data for the 4-byte chunk name
    * 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 179
    * end of every chunk (except IDAT, which is handled separately).
    */
180
   if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
G
Guy Schalnat 已提交
181
   {
A
Andreas Dilger 已提交
182
      png_byte chunk_length[4];
183
      png_byte chunk_tag[4];
G
Guy Schalnat 已提交
184

185
      PNG_PUSH_SAVE_BUFFER_IF_LT(8)
A
Andreas Dilger 已提交
186
      png_push_fill_buffer(png_ptr, chunk_length, 4);
187
      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
G
Guy Schalnat 已提交
188
      png_reset_crc(png_ptr);
189 190
      png_crc_read(png_ptr, chunk_tag, 4);
      png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
191
      png_check_chunk_name(png_ptr, png_ptr->chunk_name);
192
      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
G
Guy Schalnat 已提交
193 194
   }

195 196 197
   chunk_name = png_ptr->chunk_name;

   if (chunk_name == png_IDAT)
198
   {
199
      if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
200
         png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
201 202 203 204 205

      /* If we reach an IDAT chunk, this means we have read all of the
       * header chunks, and we can start reading the image (or if this
       * is called after the image has been read - we have an error).
       */
206
      if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
207 208 209
         png_error(png_ptr, "Missing IHDR before IDAT");

      else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
210
          (png_ptr->mode & PNG_HAVE_PLTE) == 0)
211 212
         png_error(png_ptr, "Missing PLTE before IDAT");

213
      png_ptr->process_mode = PNG_READ_IDAT_MODE;
214

215 216 217 218 219 220
      if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
         if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
            if (png_ptr->push_length == 0)
               return;

      png_ptr->mode |= PNG_HAVE_IDAT;
221

222
      if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
223
         png_benign_error(png_ptr, "Too many IDATs found");
224
   }
225

226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
   else
   {
      png_alloc_size_t limit = PNG_SIZE_MAX;
# ifdef PNG_SET_USER_LIMITS_SUPPORTED
      if (png_ptr->user_chunk_malloc_max > 0 &&
          png_ptr->user_chunk_malloc_max < limit)
         limit = png_ptr->user_chunk_malloc_max;
# elif PNG_USER_CHUNK_MALLOC_MAX > 0
      if (PNG_USER_CHUNK_MALLOC_MAX < limit)
         limit = PNG_USER_CHUNK_MALLOC_MAX;
# endif
      if (png_ptr->push_length > limit)
         png_chunk_error(png_ptr, "chunk data is too large");
   }

241
   if (chunk_name == png_IHDR)
G
Guy Schalnat 已提交
242
   {
243 244
      if (png_ptr->push_length != 13)
         png_error(png_ptr, "Invalid IHDR length");
245

246
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
247
      png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
248
   }
249

250
   else if (chunk_name == png_IEND)
251
   {
252
      PNG_PUSH_SAVE_BUFFER_IF_FULL
253 254 255 256 257
      png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);

      png_ptr->process_mode = PNG_READ_DONE_MODE;
      png_push_have_end(png_ptr, info_ptr);
   }
258

259
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
260
   else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
261
   {
262
      PNG_PUSH_SAVE_BUFFER_IF_FULL
263
      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
264

265
      if (chunk_name == png_PLTE)
266 267 268
         png_ptr->mode |= PNG_HAVE_PLTE;
   }
#endif
269

270
   else if (chunk_name == png_PLTE)
G
Guy Schalnat 已提交
271
   {
272
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
273
      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
274
   }
275

276
   else if (chunk_name == png_IDAT)
G
Guy Schalnat 已提交
277 278 279
   {
      png_ptr->idat_size = png_ptr->push_length;
      png_ptr->process_mode = PNG_READ_IDAT_MODE;
A
Andreas Dilger 已提交
280
      png_push_have_info(png_ptr, info_ptr);
281 282 283
      png_ptr->zstream.avail_out =
          (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
          png_ptr->iwidth) + 1;
A
Andreas Dilger 已提交
284
      png_ptr->zstream.next_out = png_ptr->row_buf;
G
Guy Schalnat 已提交
285 286
      return;
   }
287

288
#ifdef PNG_READ_gAMA_SUPPORTED
289
   else if (png_ptr->chunk_name == png_gAMA)
G
Guy Schalnat 已提交
290
   {
291
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
292
      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
293
   }
294

G
Guy Schalnat 已提交
295
#endif
296
#ifdef PNG_READ_sBIT_SUPPORTED
297
   else if (png_ptr->chunk_name == png_sBIT)
G
Guy Schalnat 已提交
298
   {
299
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
300
      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
301
   }
302

G
Guy Schalnat 已提交
303
#endif
304
#ifdef PNG_READ_cHRM_SUPPORTED
305
   else if (png_ptr->chunk_name == png_cHRM)
G
Guy Schalnat 已提交
306
   {
307
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
308
      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
309
   }
310

G
Guy Schalnat 已提交
311
#endif
312
#ifdef PNG_READ_sRGB_SUPPORTED
313
   else if (chunk_name == png_sRGB)
314
   {
315
      PNG_PUSH_SAVE_BUFFER_IF_FULL
316 317
      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
   }
318

319
#endif
320
#ifdef PNG_READ_iCCP_SUPPORTED
321
   else if (png_ptr->chunk_name == png_iCCP)
322
   {
323
      PNG_PUSH_SAVE_BUFFER_IF_FULL
324 325
      png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
   }
326

327
#endif
328
#ifdef PNG_READ_sPLT_SUPPORTED
329
   else if (chunk_name == png_sPLT)
330
   {
331
      PNG_PUSH_SAVE_BUFFER_IF_FULL
332 333
      png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
   }
334

335
#endif
336
#ifdef PNG_READ_tRNS_SUPPORTED
337
   else if (chunk_name == png_tRNS)
G
Guy Schalnat 已提交
338
   {
339
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
340
      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
341
   }
342

G
Guy Schalnat 已提交
343
#endif
344
#ifdef PNG_READ_bKGD_SUPPORTED
345
   else if (chunk_name == png_bKGD)
G
Guy Schalnat 已提交
346
   {
347
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
348
      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
349
   }
350

G
Guy Schalnat 已提交
351
#endif
352
#ifdef PNG_READ_hIST_SUPPORTED
353
   else if (chunk_name == png_hIST)
G
Guy Schalnat 已提交
354
   {
355
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
356
      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
357
   }
358

G
Guy Schalnat 已提交
359
#endif
360
#ifdef PNG_READ_pHYs_SUPPORTED
361
   else if (chunk_name == png_pHYs)
G
Guy Schalnat 已提交
362
   {
363
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
364
      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
365
   }
366

G
Guy Schalnat 已提交
367
#endif
368
#ifdef PNG_READ_oFFs_SUPPORTED
369
   else if (chunk_name == png_oFFs)
G
Guy Schalnat 已提交
370
   {
371
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
372
      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
373
   }
G
Guy Schalnat 已提交
374
#endif
375

376
#ifdef PNG_READ_pCAL_SUPPORTED
377
   else if (chunk_name == png_pCAL)
A
Andreas Dilger 已提交
378
   {
379
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
380 381
      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
   }
382

A
Andreas Dilger 已提交
383
#endif
384
#ifdef PNG_READ_sCAL_SUPPORTED
385
   else if (chunk_name == png_sCAL)
386
   {
387
      PNG_PUSH_SAVE_BUFFER_IF_FULL
388 389
      png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
   }
390

391
#endif
392
#ifdef PNG_READ_tIME_SUPPORTED
393
   else if (chunk_name == png_tIME)
G
Guy Schalnat 已提交
394
   {
395
      PNG_PUSH_SAVE_BUFFER_IF_FULL
A
Andreas Dilger 已提交
396
      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
397
   }
398

G
Guy Schalnat 已提交
399
#endif
400
#ifdef PNG_READ_tEXt_SUPPORTED
401
   else if (chunk_name == png_tEXt)
G
Guy Schalnat 已提交
402
   {
403
      PNG_PUSH_SAVE_BUFFER_IF_FULL
404
      png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
405
   }
406

G
Guy Schalnat 已提交
407
#endif
408
#ifdef PNG_READ_zTXt_SUPPORTED
409
   else if (chunk_name == png_zTXt)
G
Guy Schalnat 已提交
410
   {
411
      PNG_PUSH_SAVE_BUFFER_IF_FULL
412
      png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
413
   }
414

415
#endif
416
#ifdef PNG_READ_iTXt_SUPPORTED
417
   else if (chunk_name == png_iTXt)
418
   {
419
      PNG_PUSH_SAVE_BUFFER_IF_FULL
420
      png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
421
   }
G
Guy Schalnat 已提交
422
#endif
423

G
Guy Schalnat 已提交
424 425
   else
   {
426
      PNG_PUSH_SAVE_BUFFER_IF_FULL
427
      png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
428
          PNG_HANDLE_CHUNK_AS_DEFAULT);
429
   }
G
Guy Schalnat 已提交
430

431
   png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
G
Guy Schalnat 已提交
432 433
}

434
void PNGCBAPI
A
Andreas Dilger 已提交
435
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
G
Guy Schalnat 已提交
436
{
G
Guy Schalnat 已提交
437 438
   png_bytep ptr;

439 440 441
   if (png_ptr == NULL)
      return;

G
Guy Schalnat 已提交
442
   ptr = buffer;
443
   if (png_ptr->save_buffer_size != 0)
G
Guy Schalnat 已提交
444
   {
A
Andreas Dilger 已提交
445
      png_size_t save_size;
G
Guy Schalnat 已提交
446 447 448

      if (length < png_ptr->save_buffer_size)
         save_size = length;
449

G
Guy Schalnat 已提交
450 451 452
      else
         save_size = png_ptr->save_buffer_size;

453
      memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
G
Guy Schalnat 已提交
454
      length -= save_size;
A
Andreas Dilger 已提交
455
      ptr += save_size;
G
Guy Schalnat 已提交
456 457
      png_ptr->buffer_size -= save_size;
      png_ptr->save_buffer_size -= save_size;
A
Andreas Dilger 已提交
458
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
459
   }
460
   if (length != 0 && png_ptr->current_buffer_size != 0)
G
Guy Schalnat 已提交
461
   {
A
Andreas Dilger 已提交
462
      png_size_t save_size;
G
Guy Schalnat 已提交
463 464 465

      if (length < png_ptr->current_buffer_size)
         save_size = length;
466

G
Guy Schalnat 已提交
467 468 469
      else
         save_size = png_ptr->current_buffer_size;

470
      memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
G
Guy Schalnat 已提交
471 472
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
473
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
474
   }
G
Guy Schalnat 已提交
475 476
}

477
void /* PRIVATE */
478
png_push_save_buffer(png_structrp png_ptr)
G
Guy Schalnat 已提交
479
{
480
   if (png_ptr->save_buffer_size != 0)
G
Guy Schalnat 已提交
481 482 483
   {
      if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
      {
484
         png_size_t i, istop;
G
Guy Schalnat 已提交
485 486 487
         png_bytep sp;
         png_bytep dp;

488
         istop = png_ptr->save_buffer_size;
G
Guy Schalnat 已提交
489
         for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
490
             i < istop; i++, sp++, dp++)
G
Guy Schalnat 已提交
491 492 493 494 495
         {
            *dp = *sp;
         }
      }
   }
496
   if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
497
       png_ptr->save_buffer_max)
G
Guy Schalnat 已提交
498
   {
A
Andreas Dilger 已提交
499
      png_size_t new_max;
G
Guy Schalnat 已提交
500 501
      png_bytep old_buffer;

502
      if (png_ptr->save_buffer_size > PNG_SIZE_MAX -
503
          (png_ptr->current_buffer_size + 256))
504
      {
505
         png_error(png_ptr, "Potential overflow of save_buffer");
506
      }
507

508
      new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
G
Guy Schalnat 已提交
509
      old_buffer = png_ptr->save_buffer;
510
      png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
511
          (png_size_t)new_max);
512

513 514
      if (png_ptr->save_buffer == NULL)
      {
515 516
         png_free(png_ptr, old_buffer);
         png_error(png_ptr, "Insufficient memory for save_buffer");
517
      }
518

519 520 521 522
      if (old_buffer)
         memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
      else if (png_ptr->save_buffer_size)
         png_error(png_ptr, "save_buffer error");
523 524
      png_free(png_ptr, old_buffer);
      png_ptr->save_buffer_max = new_max;
G
Guy Schalnat 已提交
525 526 527
   }
   if (png_ptr->current_buffer_size)
   {
528
      memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
A
Andreas Dilger 已提交
529
         png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
G
Guy Schalnat 已提交
530 531 532 533 534
      png_ptr->save_buffer_size += png_ptr->current_buffer_size;
      png_ptr->current_buffer_size = 0;
   }
   png_ptr->save_buffer_ptr = png_ptr->save_buffer;
   png_ptr->buffer_size = 0;
G
Guy Schalnat 已提交
535 536
}

537
void /* PRIVATE */
538
png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
539
    png_size_t buffer_length)
G
Guy Schalnat 已提交
540
{
G
Guy Schalnat 已提交
541 542 543 544
   png_ptr->current_buffer = buffer;
   png_ptr->current_buffer_size = buffer_length;
   png_ptr->buffer_size = buffer_length + png_ptr->save_buffer_size;
   png_ptr->current_buffer_ptr = png_ptr->current_buffer;
G
Guy Schalnat 已提交
545 546
}

547
void /* PRIVATE */
548
png_push_read_IDAT(png_structrp png_ptr)
G
Guy Schalnat 已提交
549
{
550
   if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
G
Guy Schalnat 已提交
551
   {
A
Andreas Dilger 已提交
552
      png_byte chunk_length[4];
553
      png_byte chunk_tag[4];
G
Guy Schalnat 已提交
554

555
      /* TODO: this code can be commoned up with the same code in push_read */
556
      PNG_PUSH_SAVE_BUFFER_IF_LT(8)
A
Andreas Dilger 已提交
557
      png_push_fill_buffer(png_ptr, chunk_length, 4);
558
      png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
G
Guy Schalnat 已提交
559
      png_reset_crc(png_ptr);
560 561
      png_crc_read(png_ptr, chunk_tag, 4);
      png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(chunk_tag);
562
      png_ptr->mode |= PNG_HAVE_CHUNK_HEADER;
A
Andreas Dilger 已提交
563

564
      if (png_ptr->chunk_name != png_IDAT)
G
Guy Schalnat 已提交
565
      {
A
Andreas Dilger 已提交
566
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
567

568
         if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
G
Guy Schalnat 已提交
569
            png_error(png_ptr, "Not enough compressed data");
570

G
Guy Schalnat 已提交
571 572 573 574 575
         return;
      }

      png_ptr->idat_size = png_ptr->push_length;
   }
576

577
   if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
G
Guy Schalnat 已提交
578
   {
579 580
      png_size_t save_size = png_ptr->save_buffer_size;
      png_uint_32 idat_size = png_ptr->idat_size;
581

582 583 584 585
      /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
       * are of different types and we don't know which variable has the fewest
       * bits.  Carefully select the smaller and cast it to the type of the
       * larger - this cannot overflow.  Do not cast in the following test - it
586
       * will break on either 16-bit or 64-bit platforms.
587 588 589
       */
      if (idat_size < save_size)
         save_size = (png_size_t)idat_size;
590

G
Guy Schalnat 已提交
591
      else
592
         idat_size = (png_uint_32)save_size;
G
Guy Schalnat 已提交
593 594

      png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size);
595

596
      png_process_IDAT_data(png_ptr, png_ptr->save_buffer_ptr, save_size);
597

598
      png_ptr->idat_size -= idat_size;
G
Guy Schalnat 已提交
599 600
      png_ptr->buffer_size -= save_size;
      png_ptr->save_buffer_size -= save_size;
A
Andreas Dilger 已提交
601
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
602
   }
603

604
   if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0)
G
Guy Schalnat 已提交
605
   {
606 607
      png_size_t save_size = png_ptr->current_buffer_size;
      png_uint_32 idat_size = png_ptr->idat_size;
G
Guy Schalnat 已提交
608

609 610 611 612 613 614 615
      /* We want the smaller of 'idat_size' and 'current_buffer_size', but they
       * are of different types and we don't know which variable has the fewest
       * bits.  Carefully select the smaller and cast it to the type of the
       * larger - this cannot overflow.
       */
      if (idat_size < save_size)
         save_size = (png_size_t)idat_size;
616

G
Guy Schalnat 已提交
617
      else
618
         idat_size = (png_uint_32)save_size;
G
Guy Schalnat 已提交
619 620

      png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size);
621

622
      png_process_IDAT_data(png_ptr, png_ptr->current_buffer_ptr, save_size);
G
Guy Schalnat 已提交
623

624
      png_ptr->idat_size -= idat_size;
G
Guy Schalnat 已提交
625 626
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
627
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
628
   }
629

630
   if (png_ptr->idat_size == 0)
G
Guy Schalnat 已提交
631
   {
632
      PNG_PUSH_SAVE_BUFFER_IF_LT(4)
A
Andreas Dilger 已提交
633
      png_crc_finish(png_ptr, 0);
634
      png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
635
      png_ptr->mode |= PNG_AFTER_IDAT;
636
      png_ptr->zowner = 0;
G
Guy Schalnat 已提交
637
   }
G
Guy Schalnat 已提交
638 639
}

640
void /* PRIVATE */
641
png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
642
    png_size_t buffer_length)
G
Guy Schalnat 已提交
643
{
644
   /* The caller checks for a non-zero buffer length. */
645
   if (!(buffer_length > 0) || buffer == NULL)
646
      png_error(png_ptr, "No IDAT data (internal error)");
G
Guy Schalnat 已提交
647

648 649
   /* This routine must process all the data it has been given
    * before returning, calling the row callback as required to
650
    * handle the uncompressed results.
651
    */
A
Andreas Dilger 已提交
652
   png_ptr->zstream.next_in = buffer;
653
   /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
A
Andreas Dilger 已提交
654
   png_ptr->zstream.avail_in = (uInt)buffer_length;
655 656 657 658 659

   /* Keep going until the decompressed data is all processed
    * or the stream marked as finished.
    */
   while (png_ptr->zstream.avail_in > 0 &&
660
      (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
G
Guy Schalnat 已提交
661
   {
662 663 664
      int ret;

      /* We have data for zlib, but we must check that zlib
665
       * has someplace to put the results.  It doesn't matter
666
       * if we don't expect any results -- it may be the input
667 668 669
       * data is just the LZ end code.
       */
      if (!(png_ptr->zstream.avail_out > 0))
G
Guy Schalnat 已提交
670
      {
671 672 673
         /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
         png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
             png_ptr->iwidth) + 1);
674

675 676 677 678
         png_ptr->zstream.next_out = png_ptr->row_buf;
      }

      /* Using Z_SYNC_FLUSH here means that an unterminated
679 680 681 682 683
       * LZ stream (a stream with a missing end code) can still
       * be handled, otherwise (Z_NO_FLUSH) a future zlib
       * implementation might defer output and therefore
       * change the current behavior (see comments in inflate.c
       * for why this doesn't happen at present with zlib 1.2.5).
684
       */
685
      ret = PNG_INFLATE(png_ptr, Z_SYNC_FLUSH);
686

687 688 689
      /* Check for any failure before proceeding. */
      if (ret != Z_OK && ret != Z_STREAM_END)
      {
690
         /* Terminate the decompression. */
691 692
         png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
         png_ptr->zowner = 0;
693

694
         /* This may be a truncated stream (missing or
695 696
          * damaged end code).  Treat that as a warning.
          */
697
         if (png_ptr->row_number >= png_ptr->num_rows ||
698 699
             png_ptr->pass > 6)
            png_warning(png_ptr, "Truncated compressed data in IDAT");
700

701
         else
702 703 704 705 706 707
         {
            if (ret == Z_DATA_ERROR)
               png_benign_error(png_ptr, "IDAT: ADLER32 checksum mismatch");
            else
               png_error(png_ptr, "Decompression error in IDAT");
         }
708

709
         /* Skip the check on unprocessed input */
710
         return;
G
Guy Schalnat 已提交
711
      }
712 713 714

      /* Did inflate output any data? */
      if (png_ptr->zstream.next_out != png_ptr->row_buf)
G
Guy Schalnat 已提交
715
      {
716 717 718 719
         /* Is this unexpected data after the last row?
          * If it is, artificially terminate the LZ output
          * here.
          */
720
         if (png_ptr->row_number >= png_ptr->num_rows ||
721
             png_ptr->pass > 6)
722
         {
723 724
            /* Extra data. */
            png_warning(png_ptr, "Extra compressed data in IDAT");
725 726
            png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
            png_ptr->zowner = 0;
727

728 729 730
            /* Do no more processing; skip the unprocessed
             * input check below.
             */
731
            return;
732
         }
733

734 735 736
         /* Do we have a complete row? */
         if (png_ptr->zstream.avail_out == 0)
            png_push_process_row(png_ptr);
G
Guy Schalnat 已提交
737
      }
738 739 740

      /* And check for the end of the stream. */
      if (ret == Z_STREAM_END)
741
         png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
A
Andreas Dilger 已提交
742
   }
743 744 745 746 747 748

   /* All the data should have been processed, if anything
    * is left at this point we have bytes of IDAT data
    * after the zlib end code.
    */
   if (png_ptr->zstream.avail_in > 0)
749
      png_warning(png_ptr, "Extra compression data in IDAT");
G
Guy Schalnat 已提交
750 751
}

752
void /* PRIVATE */
753
png_push_process_row(png_structrp png_ptr)
G
Guy Schalnat 已提交
754
{
755 756
   /* 1.5.6: row_info moved out of png_struct to a local here. */
   png_row_info row_info;
757

758 759 760 761 762 763
   row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
   row_info.color_type = png_ptr->color_type;
   row_info.bit_depth = png_ptr->bit_depth;
   row_info.channels = png_ptr->channels;
   row_info.pixel_depth = png_ptr->pixel_depth;
   row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
G
Guy Schalnat 已提交
764

765 766 767
   if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
   {
      if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
768
         png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
769 770 771 772
            png_ptr->prev_row + 1, png_ptr->row_buf[0]);
      else
         png_error(png_ptr, "bad adaptive filter value");
   }
G
Guy Schalnat 已提交
773

774 775 776 777 778
   /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
    * 1.5.6, while the buffer really is this big in current versions of libpng
    * it may not be in the future, so this was changed just to copy the
    * interlaced row count:
    */
779
   memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
G
Guy Schalnat 已提交
780

781
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
782
   if (png_ptr->transformations != 0)
783
      png_do_read_transformations(png_ptr, &row_info);
784
#endif
G
Guy Schalnat 已提交
785

786 787 788 789 790 791 792 793 794 795 796 797
   /* The transformed pixel depth should match the depth now in row_info. */
   if (png_ptr->transformed_pixel_depth == 0)
   {
      png_ptr->transformed_pixel_depth = row_info.pixel_depth;
      if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
         png_error(png_ptr, "progressive row overflow");
   }

   else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth)
      png_error(png_ptr, "internal progressive row size calculation error");


798
#ifdef PNG_READ_INTERLACING_SUPPORTED
799
   /* Expand interlaced rows to full size */
800 801
   if (png_ptr->interlaced != 0 &&
       (png_ptr->transformations & PNG_INTERLACE) != 0)
G
Guy Schalnat 已提交
802 803
   {
      if (png_ptr->pass < 6)
804
         png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
805
             png_ptr->transformations);
G
Guy Schalnat 已提交
806

807 808
      switch (png_ptr->pass)
      {
G
Guy Schalnat 已提交
809 810 811 812 813 814
         case 0:
         {
            int i;
            for (i = 0; i < 8 && png_ptr->pass == 0; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
815
               png_read_push_finish_row(png_ptr); /* Updates png_ptr->pass */
G
Guy Schalnat 已提交
816
            }
817

818
            if (png_ptr->pass == 2) /* Pass 1 might be empty */
819 820 821
            {
               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
               {
822
                  png_push_have_row(png_ptr, NULL);
823 824 825
                  png_read_push_finish_row(png_ptr);
               }
            }
826

827 828 829 830
            if (png_ptr->pass == 4 && png_ptr->height <= 4)
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
831
                  png_push_have_row(png_ptr, NULL);
832 833
                  png_read_push_finish_row(png_ptr);
               }
834
            }
835

836 837
            if (png_ptr->pass == 6 && png_ptr->height <= 4)
            {
838
                png_push_have_row(png_ptr, NULL);
839 840
                png_read_push_finish_row(png_ptr);
            }
841

G
Guy Schalnat 已提交
842 843
            break;
         }
844

G
Guy Schalnat 已提交
845 846 847 848 849 850 851 852
         case 1:
         {
            int i;
            for (i = 0; i < 8 && png_ptr->pass == 1; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
               png_read_push_finish_row(png_ptr);
            }
853

854
            if (png_ptr->pass == 2) /* Skip top 4 generated rows */
G
Guy Schalnat 已提交
855 856 857
            {
               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
               {
858
                  png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
859 860 861
                  png_read_push_finish_row(png_ptr);
               }
            }
862

G
Guy Schalnat 已提交
863 864
            break;
         }
865

G
Guy Schalnat 已提交
866 867 868
         case 2:
         {
            int i;
869

G
Guy Schalnat 已提交
870 871 872 873 874
            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
               png_read_push_finish_row(png_ptr);
            }
875

G
Guy Schalnat 已提交
876 877
            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
            {
878
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
879 880
               png_read_push_finish_row(png_ptr);
            }
881

882
            if (png_ptr->pass == 4) /* Pass 3 might be empty */
883 884 885
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
886
                  png_push_have_row(png_ptr, NULL);
887 888 889
                  png_read_push_finish_row(png_ptr);
               }
            }
890

G
Guy Schalnat 已提交
891 892
            break;
         }
893

G
Guy Schalnat 已提交
894 895 896
         case 3:
         {
            int i;
897

G
Guy Schalnat 已提交
898 899 900 901 902
            for (i = 0; i < 4 && png_ptr->pass == 3; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
               png_read_push_finish_row(png_ptr);
            }
903

904
            if (png_ptr->pass == 4) /* Skip top two generated rows */
G
Guy Schalnat 已提交
905 906 907
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
908
                  png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
909 910 911
                  png_read_push_finish_row(png_ptr);
               }
            }
912

G
Guy Schalnat 已提交
913 914
            break;
         }
915

G
Guy Schalnat 已提交
916 917 918
         case 4:
         {
            int i;
919

G
Guy Schalnat 已提交
920 921 922 923 924
            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
               png_read_push_finish_row(png_ptr);
            }
925

G
Guy Schalnat 已提交
926 927
            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
            {
928
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
929 930
               png_read_push_finish_row(png_ptr);
            }
931

932
            if (png_ptr->pass == 6) /* Pass 5 might be empty */
933
            {
934
               png_push_have_row(png_ptr, NULL);
935 936
               png_read_push_finish_row(png_ptr);
            }
937

G
Guy Schalnat 已提交
938 939
            break;
         }
940

G
Guy Schalnat 已提交
941 942 943
         case 5:
         {
            int i;
944

G
Guy Schalnat 已提交
945 946 947 948 949
            for (i = 0; i < 2 && png_ptr->pass == 5; i++)
            {
               png_push_have_row(png_ptr, png_ptr->row_buf + 1);
               png_read_push_finish_row(png_ptr);
            }
950

951
            if (png_ptr->pass == 6) /* Skip top generated row */
G
Guy Schalnat 已提交
952
            {
953
               png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
954 955
               png_read_push_finish_row(png_ptr);
            }
956

G
Guy Schalnat 已提交
957 958
            break;
         }
959

960
         default:
G
Guy Schalnat 已提交
961 962 963 964
         case 6:
         {
            png_push_have_row(png_ptr, png_ptr->row_buf + 1);
            png_read_push_finish_row(png_ptr);
965

G
Guy Schalnat 已提交
966 967
            if (png_ptr->pass != 6)
               break;
968

969
            png_push_have_row(png_ptr, NULL);
G
Guy Schalnat 已提交
970 971 972 973 974
            png_read_push_finish_row(png_ptr);
         }
      }
   }
   else
975
#endif
G
Guy Schalnat 已提交
976 977 978 979
   {
      png_push_have_row(png_ptr, png_ptr->row_buf + 1);
      png_read_push_finish_row(png_ptr);
   }
G
Guy Schalnat 已提交
980 981
}

982
void /* PRIVATE */
983
png_read_push_finish_row(png_structrp png_ptr)
G
Guy Schalnat 已提交
984
{
985
#ifdef PNG_READ_INTERLACING_SUPPORTED
986
   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
987

988
   /* Start of interlace block */
989
   static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
990

991
   /* Offset to next interlace block */
992
   static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
993

994
   /* Start of interlace block in the y direction */
995
   static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
996

997
   /* Offset to next interlace block in the y direction */
998
   static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
999

1000 1001
   /* Height of interlace block.  This is not currently used - if you need
    * it, uncomment it here and in png.h
1002
   static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
1003
   */
1004
#endif
1005

G
Guy Schalnat 已提交
1006 1007
   png_ptr->row_number++;
   if (png_ptr->row_number < png_ptr->num_rows)
G
Guy Schalnat 已提交
1008
      return;
G
Guy Schalnat 已提交
1009

1010
#ifdef PNG_READ_INTERLACING_SUPPORTED
1011
   if (png_ptr->interlaced != 0)
G
Guy Schalnat 已提交
1012 1013
   {
      png_ptr->row_number = 0;
1014
      memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
1015

G
Guy Schalnat 已提交
1016 1017 1018
      do
      {
         png_ptr->pass++;
1019 1020 1021
         if ((png_ptr->pass == 1 && png_ptr->width < 5) ||
             (png_ptr->pass == 3 && png_ptr->width < 3) ||
             (png_ptr->pass == 5 && png_ptr->width < 2))
1022
            png_ptr->pass++;
1023

1024 1025
         if (png_ptr->pass > 7)
            png_ptr->pass--;
1026

G
Guy Schalnat 已提交
1027 1028
         if (png_ptr->pass >= 7)
            break;
1029

G
Guy Schalnat 已提交
1030
         png_ptr->iwidth = (png_ptr->width +
1031 1032 1033
             png_pass_inc[png_ptr->pass] - 1 -
             png_pass_start[png_ptr->pass]) /
             png_pass_inc[png_ptr->pass];
1034

1035
         if ((png_ptr->transformations & PNG_INTERLACE) != 0)
G
Guy Schalnat 已提交
1036
            break;
1037 1038

         png_ptr->num_rows = (png_ptr->height +
1039 1040 1041
             png_pass_yinc[png_ptr->pass] - 1 -
             png_pass_ystart[png_ptr->pass]) /
             png_pass_yinc[png_ptr->pass];
1042 1043

      } while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
G
Guy Schalnat 已提交
1044
   }
1045
#endif /* READ_INTERLACING */
G
Guy Schalnat 已提交
1046 1047
}

1048
void /* PRIVATE */
1049
png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
G
Guy Schalnat 已提交
1050
{
A
Andreas Dilger 已提交
1051
   if (png_ptr->info_fn != NULL)
A
Andreas Dilger 已提交
1052
      (*(png_ptr->info_fn))(png_ptr, info_ptr);
G
Guy Schalnat 已提交
1053 1054
}

1055
void /* PRIVATE */
1056
png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
G
Guy Schalnat 已提交
1057
{
A
Andreas Dilger 已提交
1058
   if (png_ptr->end_fn != NULL)
A
Andreas Dilger 已提交
1059
      (*(png_ptr->end_fn))(png_ptr, info_ptr);
G
Guy Schalnat 已提交
1060 1061
}

1062
void /* PRIVATE */
1063
png_push_have_row(png_structrp png_ptr, png_bytep row)
G
Guy Schalnat 已提交
1064
{
1065
   if (png_ptr->row_fn != NULL)
G
Guy Schalnat 已提交
1066
      (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
1067
          (int)png_ptr->pass);
G
Guy Schalnat 已提交
1068 1069
}

1070
#ifdef PNG_READ_INTERLACING_SUPPORTED
1071
void PNGAPI
1072
png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
1073
    png_const_bytep new_row)
G
Guy Schalnat 已提交
1074
{
1075 1076 1077
   if (png_ptr == NULL)
      return;

1078 1079 1080 1081 1082
   /* new_row is a flag here - if it is NULL then the app callback was called
    * from an empty row (see the calls to png_struct::row_fn below), otherwise
    * it must be png_ptr->row_buf+1
    */
   if (new_row != NULL)
1083
      png_combine_row(png_ptr, old_row, 1/*blocky display*/);
G
Guy Schalnat 已提交
1084
}
1085
#endif /* READ_INTERLACING */
G
Guy Schalnat 已提交
1086

1087
void PNGAPI
1088
png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
1089 1090
    png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
    png_progressive_end_ptr end_fn)
G
Guy Schalnat 已提交
1091
{
1092 1093 1094
   if (png_ptr == NULL)
      return;

G
Guy Schalnat 已提交
1095 1096
   png_ptr->info_fn = info_fn;
   png_ptr->row_fn = row_fn;
G
Guy Schalnat 已提交
1097
   png_ptr->end_fn = end_fn;
G
Guy Schalnat 已提交
1098

1099
   png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
G
Guy Schalnat 已提交
1100 1101
}

1102
png_voidp PNGAPI
1103
png_get_progressive_ptr(png_const_structrp png_ptr)
G
Guy Schalnat 已提交
1104
{
1105 1106 1107
   if (png_ptr == NULL)
      return (NULL);

A
Andreas Dilger 已提交
1108
   return png_ptr->io_ptr;
G
Guy Schalnat 已提交
1109
}
1110
#endif /* PROGRESSIVE_READ */