pngpread.c 30.6 KB
Newer Older
G
Guy Schalnat 已提交
1 2

/* pngpread.c - read a png file in push mode
3
 *
4
 * libpng 0.98
5 6 7
 * For conditions of distribution and use, see copyright notice in png.h
 * Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.
 * Copyright (c) 1996, 1997 Andreas Dilger
8
 * Copyright (c) 1998, Glenn Randers-Pehrson
9
 * January 16, 1998
10
 */
G
Guy Schalnat 已提交
11 12 13 14

#define PNG_INTERNAL
#include "png.h"

G
Guy Schalnat 已提交
15 16
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED

G
Guy Schalnat 已提交
17
void
A
Andreas Dilger 已提交
18
png_process_data(png_structp png_ptr, png_infop info_ptr,
A
Andreas Dilger 已提交
19
   png_bytep buffer, png_size_t buffer_size)
G
Guy Schalnat 已提交
20
{
G
Guy Schalnat 已提交
21
   png_push_restore_buffer(png_ptr, buffer, buffer_size);
G
Guy Schalnat 已提交
22

G
Guy Schalnat 已提交
23 24
   while (png_ptr->buffer_size)
   {
A
Andreas Dilger 已提交
25
      png_process_some_data(png_ptr, info_ptr);
G
Guy Schalnat 已提交
26
   }
G
Guy Schalnat 已提交
27 28
}

A
Andreas Dilger 已提交
29 30 31
/* What we do with the incoming data depends on what we were previously
 * doing before we ran out of data...
 */
G
Guy Schalnat 已提交
32
void
A
Andreas Dilger 已提交
33
png_process_some_data(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
34
{
G
Guy Schalnat 已提交
35 36 37 38
   switch (png_ptr->process_mode)
   {
      case PNG_READ_SIG_MODE:
      {
A
Andreas Dilger 已提交
39
         png_push_read_sig(png_ptr, info_ptr);
G
Guy Schalnat 已提交
40 41 42 43
         break;
      }
      case PNG_READ_CHUNK_MODE:
      {
A
Andreas Dilger 已提交
44
         png_push_read_chunk(png_ptr, info_ptr);
G
Guy Schalnat 已提交
45 46 47 48
         break;
      }
      case PNG_READ_IDAT_MODE:
      {
G
Guy Schalnat 已提交
49
         png_push_read_IDAT(png_ptr);
G
Guy Schalnat 已提交
50 51
         break;
      }
G
Guy Schalnat 已提交
52
#if defined(PNG_READ_tEXt_SUPPORTED)
G
Guy Schalnat 已提交
53 54
      case PNG_READ_tEXt_MODE:
      {
A
Andreas Dilger 已提交
55
         png_push_read_tEXt(png_ptr, info_ptr);
G
Guy Schalnat 已提交
56 57
         break;
      }
G
Guy Schalnat 已提交
58
#endif
G
Guy Schalnat 已提交
59 60 61
#if defined(PNG_READ_zTXt_SUPPORTED)
      case PNG_READ_zTXt_MODE:
      {
A
Andreas Dilger 已提交
62
         png_push_read_zTXt(png_ptr, info_ptr);
G
Guy Schalnat 已提交
63 64 65 66 67
         break;
      }
#endif
      case PNG_SKIP_MODE:
      {
A
Andreas Dilger 已提交
68
         png_push_crc_finish(png_ptr);
G
Guy Schalnat 已提交
69 70 71 72 73 74 75 76
         break;
      }
      default:
      {
         png_ptr->buffer_size = 0;
         break;
      }
   }
G
Guy Schalnat 已提交
77 78
}

A
Andreas Dilger 已提交
79 80 81 82 83
/* Read any remaining signature bytes from the stream and compare them with
 * the correct PNG signature.  It is possible that this routine is called
 * with bytes already read from the signature, whether because they have been
 * checked by the calling application, or from multiple calls to this routine.
 */
G
Guy Schalnat 已提交
84
void
A
Andreas Dilger 已提交
85
png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
86
{
A
Andreas Dilger 已提交
87 88
   png_size_t num_checked = png_ptr->sig_bytes,
             num_to_check = 8 - num_checked;
G
Guy Schalnat 已提交
89

A
Andreas Dilger 已提交
90
   if (png_ptr->buffer_size < num_to_check)
G
Guy Schalnat 已提交
91
   {
A
Andreas Dilger 已提交
92
      num_to_check = png_ptr->buffer_size;
G
Guy Schalnat 已提交
93 94
   }

A
Andreas Dilger 已提交
95
   png_push_fill_buffer(png_ptr, &(info_ptr->signature[num_checked]), 
A
Andreas Dilger 已提交
96
      num_to_check);
A
Andreas Dilger 已提交
97
   png_ptr->sig_bytes += num_to_check;
G
Guy Schalnat 已提交
98

A
Andreas Dilger 已提交
99
   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
G
Guy Schalnat 已提交
100
   {
A
Andreas Dilger 已提交
101 102 103 104 105
      if (num_checked < 4 &&
          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
         png_error(png_ptr, "Not a PNG file");
      else
         png_error(png_ptr, "PNG file corrupted by ASCII conversion");
G
Guy Schalnat 已提交
106 107 108
   }
   else
   {
A
Andreas Dilger 已提交
109 110 111 112
      if (png_ptr->sig_bytes >= 8)
      {
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
      }
G
Guy Schalnat 已提交
113
   }
G
Guy Schalnat 已提交
114 115 116
}

void
A
Andreas Dilger 已提交
117
png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
118
{
A
Andreas Dilger 已提交
119
   /* First we make sure we have enough data for the 4 byte chunk name
120 121 122 123 124
    * and the 4 byte chunk length before proceeding with decoding the
    * chunk data.  To fully decode each of these chunks, we also make
    * sure we have enough data in the buffer for the 4 byte CRC at the
    * end of every chunk (except IDAT, which is handled separately).
    */
G
Guy Schalnat 已提交
125
   if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
G
Guy Schalnat 已提交
126
   {
A
Andreas Dilger 已提交
127
      png_byte chunk_length[4];
G
Guy Schalnat 已提交
128 129 130 131 132 133 134

      if (png_ptr->buffer_size < 8)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
135 136
      png_push_fill_buffer(png_ptr, chunk_length, 4);
      png_ptr->push_length = png_get_uint_32(chunk_length);
G
Guy Schalnat 已提交
137
      png_reset_crc(png_ptr);
A
Andreas Dilger 已提交
138
      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
A
Andreas Dilger 已提交
139
      png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;
G
Guy Schalnat 已提交
140 141
   }

A
Andreas Dilger 已提交
142
   if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
G
Guy Schalnat 已提交
143 144 145 146 147 148 149
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
150
      png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
151
   }
A
Andreas Dilger 已提交
152
   else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
G
Guy Schalnat 已提交
153
   {
A
Andreas Dilger 已提交
154
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
G
Guy Schalnat 已提交
155
      {
A
Andreas Dilger 已提交
156 157
         png_push_save_buffer(png_ptr);
         return;
G
Guy Schalnat 已提交
158
      }
A
Andreas Dilger 已提交
159 160

      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
161
   }
A
Andreas Dilger 已提交
162
   else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
G
Guy Schalnat 已提交
163
   {
A
Andreas Dilger 已提交
164
      /* If we reach an IDAT chunk, this means we have read all of the
165 166 167
       * header chunks, and we can start reading the image (or if this
       * is called after the image has been read - we have an error).
       */
A
Andreas Dilger 已提交
168 169 170 171 172 173 174 175 176
      if (png_ptr->mode & PNG_HAVE_IDAT)
      {
         if (png_ptr->push_length == 0)
            return;

         if (png_ptr->mode & PNG_AFTER_IDAT)
            png_error(png_ptr, "Too many IDAT's found");
      }

G
Guy Schalnat 已提交
177
      png_ptr->idat_size = png_ptr->push_length;
A
Andreas Dilger 已提交
178
      png_ptr->mode |= PNG_HAVE_IDAT;
G
Guy Schalnat 已提交
179
      png_ptr->process_mode = PNG_READ_IDAT_MODE;
A
Andreas Dilger 已提交
180 181 182
      png_push_have_info(png_ptr, info_ptr);
      png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
      png_ptr->zstream.next_out = png_ptr->row_buf;
G
Guy Schalnat 已提交
183 184
      return;
   }
A
Andreas Dilger 已提交
185
   else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
G
Guy Schalnat 已提交
186
   {
A
Andreas Dilger 已提交
187 188 189 190 191 192 193 194 195
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

      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);
G
Guy Schalnat 已提交
196
   }
G
Guy Schalnat 已提交
197
#if defined(PNG_READ_gAMA_SUPPORTED)
A
Andreas Dilger 已提交
198
   else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
G
Guy Schalnat 已提交
199 200 201 202 203 204 205
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
206
      png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
207
   }
G
Guy Schalnat 已提交
208 209
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
A
Andreas Dilger 已提交
210
   else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
G
Guy Schalnat 已提交
211 212 213 214 215 216 217
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
218
      png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
219
   }
G
Guy Schalnat 已提交
220 221
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
A
Andreas Dilger 已提交
222
   else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
G
Guy Schalnat 已提交
223 224 225 226 227 228 229
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
230
      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
231
   }
G
Guy Schalnat 已提交
232
#endif
233 234 235 236 237 238 239 240 241 242 243 244
#if defined(PNG_READ_sRGB_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

      png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
   }
#endif
G
Guy Schalnat 已提交
245
#if defined(PNG_READ_tRNS_SUPPORTED)
A
Andreas Dilger 已提交
246
   else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
G
Guy Schalnat 已提交
247 248 249 250 251 252 253
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
254
      png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
255
   }
G
Guy Schalnat 已提交
256 257
#endif
#if defined(PNG_READ_bKGD_SUPPORTED)
A
Andreas Dilger 已提交
258
   else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
G
Guy Schalnat 已提交
259 260 261 262 263 264 265
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
266
      png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
267
   }
G
Guy Schalnat 已提交
268 269
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
A
Andreas Dilger 已提交
270
   else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
G
Guy Schalnat 已提交
271 272 273 274 275 276 277
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
278
      png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
279
   }
G
Guy Schalnat 已提交
280 281
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
A
Andreas Dilger 已提交
282
   else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
G
Guy Schalnat 已提交
283 284 285 286 287 288 289
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
290
      png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
291
   }
G
Guy Schalnat 已提交
292 293
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
A
Andreas Dilger 已提交
294
   else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
G
Guy Schalnat 已提交
295 296 297 298 299 300 301
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
302
      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
303
   }
G
Guy Schalnat 已提交
304
#endif
A
Andreas Dilger 已提交
305 306 307 308 309 310 311 312 313 314 315 316
#if defined(PNG_READ_pCAL_SUPPORTED)
   else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

      png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
   }
#endif
G
Guy Schalnat 已提交
317
#if defined(PNG_READ_tIME_SUPPORTED)
A
Andreas Dilger 已提交
318
   else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
G
Guy Schalnat 已提交
319 320 321 322 323 324 325
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
326
      png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
327
   }
G
Guy Schalnat 已提交
328 329
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
A
Andreas Dilger 已提交
330
   else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
G
Guy Schalnat 已提交
331
   {
A
Andreas Dilger 已提交
332
      png_push_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
333
   }
G
Guy Schalnat 已提交
334 335
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
A
Andreas Dilger 已提交
336
   else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
G
Guy Schalnat 已提交
337
   {
A
Andreas Dilger 已提交
338
      png_push_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
339
   }
G
Guy Schalnat 已提交
340
#endif
G
Guy Schalnat 已提交
341 342
   else
   {
A
Andreas Dilger 已提交
343
      png_push_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
344
   }
G
Guy Schalnat 已提交
345

A
Andreas Dilger 已提交
346
   png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
G
Guy Schalnat 已提交
347 348 349
}

void
A
Andreas Dilger 已提交
350
png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
G
Guy Schalnat 已提交
351
{
G
Guy Schalnat 已提交
352
   png_ptr->process_mode = PNG_SKIP_MODE;
A
Andreas Dilger 已提交
353
   png_ptr->skip_length = skip;
G
Guy Schalnat 已提交
354 355 356
}

void
A
Andreas Dilger 已提交
357
png_push_crc_finish(png_structp png_ptr)
G
Guy Schalnat 已提交
358
{
G
Guy Schalnat 已提交
359 360
   if (png_ptr->skip_length && png_ptr->save_buffer_size)
   {
A
Andreas Dilger 已提交
361
      png_size_t save_size;
G
Guy Schalnat 已提交
362

A
Andreas Dilger 已提交
363 364
      if (png_ptr->skip_length < (png_uint_32)png_ptr->save_buffer_size)
         save_size = (png_size_t)png_ptr->skip_length;
G
Guy Schalnat 已提交
365 366 367 368 369 370 371 372
      else
         save_size = png_ptr->save_buffer_size;

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

      png_ptr->skip_length -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->save_buffer_size -= save_size;
A
Andreas Dilger 已提交
373
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
374 375 376
   }
   if (png_ptr->skip_length && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
377
      png_size_t save_size;
G
Guy Schalnat 已提交
378

A
Andreas Dilger 已提交
379 380
      if (png_ptr->skip_length < (png_uint_32)png_ptr->current_buffer_size)
         save_size = (png_size_t)png_ptr->skip_length;
G
Guy Schalnat 已提交
381 382 383 384 385 386 387 388
      else
         save_size = png_ptr->current_buffer_size;

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

      png_ptr->skip_length -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
389
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
390 391 392 393 394 395 396 397
   }
   if (!png_ptr->skip_length)
   {
      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }
A
Andreas Dilger 已提交
398 399

      png_crc_finish(png_ptr, 0);
A
Andreas Dilger 已提交
400
      png_ptr->process_mode = PNG_READ_CHUNK_MODE;
G
Guy Schalnat 已提交
401
   }
G
Guy Schalnat 已提交
402 403 404
}

void
A
Andreas Dilger 已提交
405
png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
G
Guy Schalnat 已提交
406
{
G
Guy Schalnat 已提交
407 408 409 410 411
   png_bytep ptr;

   ptr = buffer;
   if (png_ptr->save_buffer_size)
   {
A
Andreas Dilger 已提交
412
      png_size_t save_size;
G
Guy Schalnat 已提交
413 414 415 416 417 418

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

A
Andreas Dilger 已提交
419
      png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
G
Guy Schalnat 已提交
420
      length -= save_size;
A
Andreas Dilger 已提交
421
      ptr += save_size;
G
Guy Schalnat 已提交
422 423
      png_ptr->buffer_size -= save_size;
      png_ptr->save_buffer_size -= save_size;
A
Andreas Dilger 已提交
424
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
425 426 427
   }
   if (length && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
428
      png_size_t save_size;
G
Guy Schalnat 已提交
429 430 431 432 433 434

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

A
Andreas Dilger 已提交
435
      png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
G
Guy Schalnat 已提交
436 437
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
438
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
439
   }
G
Guy Schalnat 已提交
440 441 442 443 444
}

void
png_push_save_buffer(png_structp png_ptr)
{
G
Guy Schalnat 已提交
445 446 447 448
   if (png_ptr->save_buffer_size)
   {
      if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
      {
A
Andreas Dilger 已提交
449
         png_size_t i;
G
Guy Schalnat 已提交
450 451 452 453 454 455 456 457 458 459 460 461 462 463
         png_bytep sp;
         png_bytep dp;

         for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
            i < png_ptr->save_buffer_size;
            i++, sp++, dp++)
         {
            *dp = *sp;
         }
      }
   }
   if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
      png_ptr->save_buffer_max)
   {
A
Andreas Dilger 已提交
464
      png_size_t new_max;
G
Guy Schalnat 已提交
465 466
      png_bytep old_buffer;

A
Andreas Dilger 已提交
467
      new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
G
Guy Schalnat 已提交
468
      old_buffer = png_ptr->save_buffer;
A
Andreas Dilger 已提交
469 470
      png_ptr->save_buffer = (png_bytep)png_malloc(png_ptr, new_max);
      png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
A
Andreas Dilger 已提交
471
      png_free(png_ptr, old_buffer);
A
Andreas Dilger 已提交
472
      png_ptr->save_buffer_max = new_max;
G
Guy Schalnat 已提交
473 474 475
   }
   if (png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
476 477
      png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
         png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
G
Guy Schalnat 已提交
478 479 480 481 482
      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 已提交
483 484 485 486
}

void
png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
A
Andreas Dilger 已提交
487
   png_size_t buffer_length)
G
Guy Schalnat 已提交
488
{
G
Guy Schalnat 已提交
489 490 491 492
   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 已提交
493 494 495
}

void
G
Guy Schalnat 已提交
496
png_push_read_IDAT(png_structp png_ptr)
G
Guy Schalnat 已提交
497
{
G
Guy Schalnat 已提交
498
   if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
G
Guy Schalnat 已提交
499
   {
A
Andreas Dilger 已提交
500
      png_byte chunk_length[4];
G
Guy Schalnat 已提交
501 502 503 504 505 506 507

      if (png_ptr->buffer_size < 8)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
508 509 510
      png_push_fill_buffer(png_ptr, chunk_length, 4);
      png_ptr->push_length = png_get_uint_32(chunk_length);

G
Guy Schalnat 已提交
511
      png_reset_crc(png_ptr);
A
Andreas Dilger 已提交
512
      png_crc_read(png_ptr, png_ptr->chunk_name, 4);
A
Andreas Dilger 已提交
513 514 515
      png_ptr->flags |= PNG_FLAG_HAVE_CHUNK_HEADER;

      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
G
Guy Schalnat 已提交
516
      {
A
Andreas Dilger 已提交
517
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
G
Guy Schalnat 已提交
518
         if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
G
Guy Schalnat 已提交
519 520 521 522 523 524 525 526
            png_error(png_ptr, "Not enough compressed data");
         return;
      }

      png_ptr->idat_size = png_ptr->push_length;
   }
   if (png_ptr->idat_size && png_ptr->save_buffer_size)
   {
A
Andreas Dilger 已提交
527
      png_size_t save_size;
G
Guy Schalnat 已提交
528

A
Andreas Dilger 已提交
529
      if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
G
Guy Schalnat 已提交
530 531 532 533 534 535 536 537 538 539
         save_size = png_ptr->idat_size;
      else
         save_size = png_ptr->save_buffer_size;

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

      png_ptr->idat_size -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->save_buffer_size -= save_size;
A
Andreas Dilger 已提交
540
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
541 542 543
   }
   if (png_ptr->idat_size && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
544
      png_size_t save_size;
G
Guy Schalnat 已提交
545

A
Andreas Dilger 已提交
546
      if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
G
Guy Schalnat 已提交
547 548 549 550 551 552 553 554 555 556
         save_size = png_ptr->idat_size;
      else
         save_size = png_ptr->current_buffer_size;

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

      png_ptr->idat_size -= save_size;
      png_ptr->buffer_size -= save_size;
      png_ptr->current_buffer_size -= save_size;
A
Andreas Dilger 已提交
557
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
558 559 560 561 562 563 564 565 566
   }
   if (!png_ptr->idat_size)
   {
      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
567
      png_crc_finish(png_ptr, 0);
G
Guy Schalnat 已提交
568
      png_ptr->flags &= ~PNG_FLAG_HAVE_CHUNK_HEADER;
G
Guy Schalnat 已提交
569
   }
G
Guy Schalnat 已提交
570 571 572 573
}

void
png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
A
Andreas Dilger 已提交
574
   png_size_t buffer_length)
G
Guy Schalnat 已提交
575
{
G
Guy Schalnat 已提交
576 577
   int ret;

G
Guy Schalnat 已提交
578
   if ((png_ptr->flags & PNG_FLAG_ZLIB_FINISHED) && buffer_length)
G
Guy Schalnat 已提交
579 580
      png_error(png_ptr, "Extra compression data");

A
Andreas Dilger 已提交
581 582
   png_ptr->zstream.next_in = buffer;
   png_ptr->zstream.avail_in = (uInt)buffer_length;
A
Andreas Dilger 已提交
583
   while(1)
G
Guy Schalnat 已提交
584
   {
A
Andreas Dilger 已提交
585
      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
G
Guy Schalnat 已提交
586 587
      if (ret == Z_STREAM_END)
      {
A
Andreas Dilger 已提交
588
         if (png_ptr->zstream.avail_in)
G
Guy Schalnat 已提交
589
            png_error(png_ptr, "Extra compressed data");
A
Andreas Dilger 已提交
590
         if (!(png_ptr->zstream.avail_out))
G
Guy Schalnat 已提交
591 592 593
         {
            png_push_process_row(png_ptr);
         }
A
Andreas Dilger 已提交
594 595

         png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
596
         png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
G
Guy Schalnat 已提交
597 598
         break;
      }
A
Andreas Dilger 已提交
599 600 601
      else if (ret == Z_BUF_ERROR)
         break;
      else if (ret != Z_OK)
G
Guy Schalnat 已提交
602
         png_error(png_ptr, "Decompression Error");
A
Andreas Dilger 已提交
603
      if (!(png_ptr->zstream.avail_out))
G
Guy Schalnat 已提交
604 605
      {
         png_push_process_row(png_ptr);
A
Andreas Dilger 已提交
606 607
         png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
         png_ptr->zstream.next_out = png_ptr->row_buf;
G
Guy Schalnat 已提交
608
      }
A
Andreas Dilger 已提交
609 610 611
      else
         break;
   }
G
Guy Schalnat 已提交
612 613 614 615 616
}

void
png_push_process_row(png_structp png_ptr)
{
G
Guy Schalnat 已提交
617
   png_ptr->row_info.color_type = png_ptr->color_type;
G
Guy Schalnat 已提交
618 619 620 621 622 623 624
   png_ptr->row_info.width = png_ptr->iwidth;
   png_ptr->row_info.channels = png_ptr->channels;
   png_ptr->row_info.bit_depth = png_ptr->bit_depth;
   png_ptr->row_info.pixel_depth = png_ptr->pixel_depth;
   png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
      (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);

G
Guy Schalnat 已提交
625 626 627
   png_read_filter_row(png_ptr, &(png_ptr->row_info),
      png_ptr->row_buf + 1, png_ptr->prev_row + 1,
      (int)(png_ptr->row_buf[0]));
G
Guy Schalnat 已提交
628

A
Andreas Dilger 已提交
629
   png_memcpy(png_ptr->prev_row, png_ptr->row_buf, png_ptr->rowbytes + 1);
G
Guy Schalnat 已提交
630 631 632 633 634

   if (png_ptr->transformations)
      png_do_read_transformations(png_ptr);

#if defined(PNG_READ_INTERLACING_SUPPORTED)
G
Guy Schalnat 已提交
635
   /* blow up interlaced rows to full size */
A
Andreas Dilger 已提交
636
   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
G
Guy Schalnat 已提交
637 638 639
   {
      if (png_ptr->pass < 6)
         png_do_read_interlace(&(png_ptr->row_info),
A
Andreas Dilger 已提交
640
            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
G
Guy Schalnat 已提交
641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746

      switch (png_ptr->pass)
      {
         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);
               png_read_push_finish_row(png_ptr);
            }
            break;
         }
         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);
            }
            if (png_ptr->pass == 2)
            {
               for (i = 0; i < 4 && png_ptr->pass == 2; i++)
               {
                  png_push_have_row(png_ptr, NULL);
                  png_read_push_finish_row(png_ptr);
               }
            }
            break;
         }
         case 2:
         {
            int i;
            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);
            }
            for (i = 0; i < 4 && png_ptr->pass == 2; i++)
            {
               png_push_have_row(png_ptr, NULL);
               png_read_push_finish_row(png_ptr);
            }
            break;
         }
         case 3:
         {
            int i;
            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);
            }
            if (png_ptr->pass == 4)
            {
               for (i = 0; i < 2 && png_ptr->pass == 4; i++)
               {
                  png_push_have_row(png_ptr, NULL);
                  png_read_push_finish_row(png_ptr);
               }
            }
            break;
         }
         case 4:
         {
            int i;
            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);
            }
            for (i = 0; i < 2 && png_ptr->pass == 4; i++)
            {
               png_push_have_row(png_ptr, NULL);
               png_read_push_finish_row(png_ptr);
            }
            break;
         }
         case 5:
         {
            int i;
            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);
            }
            if (png_ptr->pass == 6)
            {
               png_push_have_row(png_ptr, NULL);
               png_read_push_finish_row(png_ptr);
            }
            break;
         }
         case 6:
         {
            png_push_have_row(png_ptr, png_ptr->row_buf + 1);
            png_read_push_finish_row(png_ptr);
            if (png_ptr->pass != 6)
               break;
            png_push_have_row(png_ptr, NULL);
            png_read_push_finish_row(png_ptr);
         }
      }
   }
   else
G
Guy Schalnat 已提交
747
#endif
G
Guy Schalnat 已提交
748 749 750 751
   {
      png_push_have_row(png_ptr, png_ptr->row_buf + 1);
      png_read_push_finish_row(png_ptr);
   }
G
Guy Schalnat 已提交
752 753 754 755 756 757 758
}

void
png_read_push_finish_row(png_structp png_ptr)
{
   png_ptr->row_number++;
   if (png_ptr->row_number < png_ptr->num_rows)
G
Guy Schalnat 已提交
759
      return;
G
Guy Schalnat 已提交
760 761 762 763

   if (png_ptr->interlaced)
   {
      png_ptr->row_number = 0;
A
Andreas Dilger 已提交
764
      png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
G
Guy Schalnat 已提交
765 766 767 768 769 770 771 772 773 774 775 776
      do
      {
         png_ptr->pass++;
         if (png_ptr->pass >= 7)
            break;
         png_ptr->iwidth = (png_ptr->width +
            png_pass_inc[png_ptr->pass] - 1 -
            png_pass_start[png_ptr->pass]) /
            png_pass_inc[png_ptr->pass];
         png_ptr->irowbytes = ((png_ptr->iwidth *
            png_ptr->pixel_depth + 7) >> 3) + 1;
         if (!(png_ptr->transformations & PNG_INTERLACE))
G
Guy Schalnat 已提交
777
         {
G
Guy Schalnat 已提交
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792
            png_ptr->num_rows = (png_ptr->height +
               png_pass_yinc[png_ptr->pass] - 1 -
               png_pass_ystart[png_ptr->pass]) /
               png_pass_yinc[png_ptr->pass];
            if (!(png_ptr->num_rows))
               continue;
         }
         if (png_ptr->transformations & PNG_INTERLACE)
            break;
      } while (png_ptr->iwidth == 0);
   }
}

#if defined(PNG_READ_tEXt_SUPPORTED)
void
A
Andreas Dilger 已提交
793
png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
794
{
A
Andreas Dilger 已提交
795 796 797
   if (png_ptr->mode == PNG_BEFORE_IHDR || png_ptr->mode & PNG_HAVE_IEND)
      png_error(png_ptr, "Out of place tEXt");

A
Andreas Dilger 已提交
798 799 800
#ifdef PNG_MAX_MALLOC_64K
   png_ptr->skip_length = 0;  /* This may not be necessary */

801
   if (length > (png_uint_32)65535L) /* Can't hold the entire string in memory */
A
Andreas Dilger 已提交
802 803
   {
      png_warning(png_ptr, "tEXt chunk too large to fit in memory");
804 805
      png_ptr->skip_length = length - (png_uint_32)65535L;
      length = (png_uint_32)65535L;
A
Andreas Dilger 已提交
806 807 808 809 810
   }
#endif

   png_ptr->current_text = (png_charp)png_malloc(png_ptr, length+1);
   png_ptr->current_text[length] = '\0';
G
Guy Schalnat 已提交
811 812 813 814
   png_ptr->current_text_ptr = png_ptr->current_text;
   png_ptr->current_text_size = length;
   png_ptr->current_text_left = length;
   png_ptr->process_mode = PNG_READ_tEXt_MODE;
G
Guy Schalnat 已提交
815 816 817
}

void
A
Andreas Dilger 已提交
818
png_push_read_tEXt(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
819
{
G
Guy Schalnat 已提交
820 821
   if (png_ptr->buffer_size && png_ptr->current_text_left)
   {
A
Andreas Dilger 已提交
822
      png_size_t text_size;
G
Guy Schalnat 已提交
823 824 825 826 827

      if (png_ptr->buffer_size < png_ptr->current_text_left)
         text_size = png_ptr->buffer_size;
      else
         text_size = png_ptr->current_text_left;
A
Andreas Dilger 已提交
828
      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
G
Guy Schalnat 已提交
829
      png_ptr->current_text_left -= text_size;
A
Andreas Dilger 已提交
830
      png_ptr->current_text_ptr += text_size;
G
Guy Schalnat 已提交
831 832 833
   }
   if (!(png_ptr->current_text_left))
   {
A
Andreas Dilger 已提交
834
      png_textp text_ptr;
G
Guy Schalnat 已提交
835 836 837 838 839 840 841 842 843
      png_charp text;
      png_charp key;

      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
844 845 846 847 848 849
      png_push_crc_finish(png_ptr);

#if defined(PNG_MAX_MALLOC_64K)
      if (png_ptr->skip_length)
         return;
#endif
G
Guy Schalnat 已提交
850 851 852 853 854 855 856

      key = png_ptr->current_text;
      png_ptr->current_text = 0;

      for (text = key; *text; text++)
         /* empty loop */ ;

A
Andreas Dilger 已提交
857
      if (text != key + png_ptr->current_text_size)
G
Guy Schalnat 已提交
858 859
         text++;

A
Andreas Dilger 已提交
860 861 862 863
      text_ptr = (png_textp)png_malloc(png_ptr, sizeof(png_text));
      text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
      text_ptr->key = key;
      text_ptr->text = text;
G
Guy Schalnat 已提交
864

A
Andreas Dilger 已提交
865 866 867
      png_set_text(png_ptr, info_ptr, text_ptr, 1);

      png_free(png_ptr, text_ptr);
G
Guy Schalnat 已提交
868
   }
G
Guy Schalnat 已提交
869 870 871 872 873
}
#endif

#if defined(PNG_READ_zTXt_SUPPORTED)
void
A
Andreas Dilger 已提交
874
png_push_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
875
{
A
Andreas Dilger 已提交
876 877 878
   if (png_ptr->mode == PNG_BEFORE_IHDR || png_ptr->mode & PNG_HAVE_IEND)
      png_error(png_ptr, "Out of place zTXt");

A
Andreas Dilger 已提交
879 880 881 882 883
#ifdef PNG_MAX_MALLOC_64K
   /* We can't handle zTXt chunks > 64K, since we don't have enough space
    * to be able to store the uncompressed data.  Actually, the threshold
    * is probably around 32K, but it isn't as definite as 64K is.
    */
884
   if (length > (png_uint_32)65535L)
A
Andreas Dilger 已提交
885 886 887 888 889 890 891 892 893
   {
      png_warning(png_ptr, "zTXt chunk too large to fit in memory");
      png_push_crc_skip(png_ptr, length);
      return;
   }
#endif

   png_ptr->current_text = (png_charp)png_malloc(png_ptr, length+1);
   png_ptr->current_text[length] = '\0';
G
Guy Schalnat 已提交
894 895 896 897
   png_ptr->current_text_ptr = png_ptr->current_text;
   png_ptr->current_text_size = length;
   png_ptr->current_text_left = length;
   png_ptr->process_mode = PNG_READ_zTXt_MODE;
G
Guy Schalnat 已提交
898 899 900
}

void
A
Andreas Dilger 已提交
901
png_push_read_zTXt(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
902
{
G
Guy Schalnat 已提交
903 904
   if (png_ptr->buffer_size && png_ptr->current_text_left)
   {
A
Andreas Dilger 已提交
905
      png_size_t text_size;
G
Guy Schalnat 已提交
906

A
Andreas Dilger 已提交
907
      if (png_ptr->buffer_size < (png_uint_32)png_ptr->current_text_left)
G
Guy Schalnat 已提交
908 909 910
         text_size = png_ptr->buffer_size;
      else
         text_size = png_ptr->current_text_left;
A
Andreas Dilger 已提交
911
      png_crc_read(png_ptr, (png_bytep)png_ptr->current_text_ptr, text_size);
G
Guy Schalnat 已提交
912
      png_ptr->current_text_left -= text_size;
A
Andreas Dilger 已提交
913
      png_ptr->current_text_ptr += text_size;
G
Guy Schalnat 已提交
914 915 916
   }
   if (!(png_ptr->current_text_left))
   {
A
Andreas Dilger 已提交
917
      png_textp text_ptr;
G
Guy Schalnat 已提交
918 919 920
      png_charp text;
      png_charp key;
      int ret;
A
Andreas Dilger 已提交
921
      png_size_t text_size, key_size;
G
Guy Schalnat 已提交
922 923 924 925 926 927 928

      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

A
Andreas Dilger 已提交
929
      png_push_crc_finish(png_ptr);
G
Guy Schalnat 已提交
930 931 932 933 934 935 936 937

      key = png_ptr->current_text;
      png_ptr->current_text = 0;

      for (text = key; *text; text++)
         /* empty loop */ ;

      /* zTXt can't have zero text */
A
Andreas Dilger 已提交
938
      if (text == key + png_ptr->current_text_size)
G
Guy Schalnat 已提交
939
      {
A
Andreas Dilger 已提交
940
         png_free(png_ptr, key);
G
Guy Schalnat 已提交
941 942 943 944 945
         return;
      }

      text++;

A
Andreas Dilger 已提交
946
      if (*text != PNG_TEXT_COMPRESSION_zTXt) /* check compression byte */
G
Guy Schalnat 已提交
947
      {
A
Andreas Dilger 已提交
948
         png_free(png_ptr, key);
G
Guy Schalnat 已提交
949 950 951 952 953
         return;
      }

      text++;

A
Andreas Dilger 已提交
954 955
      png_ptr->zstream.next_in = (png_bytep )text;
      png_ptr->zstream.avail_in = (uInt)(png_ptr->current_text_size -
G
Guy Schalnat 已提交
956
         (text - key));
A
Andreas Dilger 已提交
957
      png_ptr->zstream.next_out = png_ptr->zbuf;
A
Andreas Dilger 已提交
958
      png_ptr->zstream.avail_out = png_ptr->zbuf_size;
G
Guy Schalnat 已提交
959 960 961 962 963 964

      key_size = text - key;
      text_size = 0;
      text = NULL;
      ret = Z_STREAM_END;

A
Andreas Dilger 已提交
965
      while (png_ptr->zstream.avail_in)
G
Guy Schalnat 已提交
966
      {
A
Andreas Dilger 已提交
967
         ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
G
Guy Schalnat 已提交
968 969
         if (ret != Z_OK && ret != Z_STREAM_END)
         {
A
Andreas Dilger 已提交
970 971 972 973
            inflateReset(&png_ptr->zstream);
            png_ptr->zstream.avail_in = 0;
            png_free(png_ptr, key);
            png_free(png_ptr, text);
G
Guy Schalnat 已提交
974 975
            return;
         }
A
Andreas Dilger 已提交
976
         if (!(png_ptr->zstream.avail_out) || ret == Z_STREAM_END)
G
Guy Schalnat 已提交
977
         {
A
Andreas Dilger 已提交
978
            if (text == NULL)
G
Guy Schalnat 已提交
979
            {
A
Andreas Dilger 已提交
980 981
               text = (png_charp)png_malloc(png_ptr,
                  png_ptr->zbuf_size - png_ptr->zstream.avail_out +
G
Guy Schalnat 已提交
982
                     key_size + 1);
A
Andreas Dilger 已提交
983 984 985 986
               png_memcpy(text + key_size, png_ptr->zbuf,
                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
               png_memcpy(text, key, key_size);
               text_size = key_size + png_ptr->zbuf_size -
A
Andreas Dilger 已提交
987
                  png_ptr->zstream.avail_out;
A
Andreas Dilger 已提交
988
               *(text + text_size) = '\0';
G
Guy Schalnat 已提交
989 990 991 992 993 994
            }
            else
            {
               png_charp tmp;

               tmp = text;
A
Andreas Dilger 已提交
995 996
               text = png_malloc(png_ptr, text_size +
                  png_ptr->zbuf_size - png_ptr->zstream.avail_out + 1);
A
Andreas Dilger 已提交
997
               png_memcpy(text, tmp, text_size);
A
Andreas Dilger 已提交
998
               png_free(png_ptr, tmp);
A
Andreas Dilger 已提交
999 1000
               png_memcpy(text + text_size, png_ptr->zbuf,
                  png_ptr->zbuf_size - png_ptr->zstream.avail_out);
A
Andreas Dilger 已提交
1001
               text_size += png_ptr->zbuf_size - png_ptr->zstream.avail_out;
A
Andreas Dilger 已提交
1002
               *(text + text_size) = '\0';
G
Guy Schalnat 已提交
1003 1004 1005
            }
            if (ret != Z_STREAM_END)
            {
A
Andreas Dilger 已提交
1006 1007
               png_ptr->zstream.next_out = png_ptr->zbuf;
               png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
            }
         }
         else
         {
            break;
         }

         if (ret == Z_STREAM_END)
            break;
      }

A
Andreas Dilger 已提交
1019 1020
      inflateReset(&png_ptr->zstream);
      png_ptr->zstream.avail_in = 0;
G
Guy Schalnat 已提交
1021 1022 1023

      if (ret != Z_STREAM_END)
      {
A
Andreas Dilger 已提交
1024 1025
         png_free(png_ptr, key);
         png_free(png_ptr, text);
G
Guy Schalnat 已提交
1026 1027 1028
         return;
      }

A
Andreas Dilger 已提交
1029
      png_free(png_ptr, key);
G
Guy Schalnat 已提交
1030
      key = text;
A
Andreas Dilger 已提交
1031
      text += key_size;
G
Guy Schalnat 已提交
1032 1033
      text_size -= key_size;

A
Andreas Dilger 已提交
1034 1035 1036 1037 1038 1039 1040 1041
      text_ptr = (png_textp)png_malloc(png_ptr, sizeof(png_text));
      text_ptr->compression = PNG_TEXT_COMPRESSION_zTXt;
      text_ptr->key = key;
      text_ptr->text = text;

      png_set_text(png_ptr, info_ptr, text_ptr, 1);

      png_free(png_ptr, text_ptr);
G
Guy Schalnat 已提交
1042
   }
G
Guy Schalnat 已提交
1043 1044 1045
}
#endif

A
Andreas Dilger 已提交
1046
/* This function is called when we haven't found a handler for this
1047 1048 1049 1050 1051 1052
 * chunk.  In the future we will have code here which can handle
 * user-defined callback functions for unknown chunks before they are
 * ignored or cause an error.  If there isn't a problem with the
 * chunk itself (ie a bad chunk name or a critical chunk), the chunk
 * is (currently) silently ignored.
 */
G
Guy Schalnat 已提交
1053
void
A
Andreas Dilger 已提交
1054 1055 1056 1057 1058 1059
png_push_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
   png_check_chunk_name(png_ptr, png_ptr->chunk_name);

   if (!(png_ptr->chunk_name[0] & 0x20))
   {
1060
      png_chunk_error(png_ptr, "unknown critical chunk");
A
Andreas Dilger 已提交
1061 1062 1063 1064 1065 1066 1067
   }

   png_push_crc_skip(png_ptr, length);
}

void
png_push_have_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1068
{
A
Andreas Dilger 已提交
1069
   if (png_ptr->info_fn != NULL)
A
Andreas Dilger 已提交
1070
      (*(png_ptr->info_fn))(png_ptr, info_ptr);
G
Guy Schalnat 已提交
1071 1072 1073
}

void
A
Andreas Dilger 已提交
1074
png_push_have_end(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
1075
{
A
Andreas Dilger 已提交
1076
   if (png_ptr->end_fn != NULL)
A
Andreas Dilger 已提交
1077
      (*(png_ptr->end_fn))(png_ptr, info_ptr);
G
Guy Schalnat 已提交
1078 1079 1080 1081 1082
}

void
png_push_have_row(png_structp png_ptr, png_bytep row)
{
A
Andreas Dilger 已提交
1083
   if (png_ptr->row_fn != NULL)
G
Guy Schalnat 已提交
1084 1085
      (*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
         (int)png_ptr->pass);
G
Guy Schalnat 已提交
1086 1087 1088
}

void
A
Andreas Dilger 已提交
1089 1090
png_progressive_combine_row (png_structp png_ptr,
   png_bytep old_row, png_bytep new_row)
G
Guy Schalnat 已提交
1091
{
A
Andreas Dilger 已提交
1092
   if (new_row != NULL)
A
Andreas Dilger 已提交
1093
      png_combine_row(png_ptr, old_row, png_pass_dsp_mask[png_ptr->pass]);
G
Guy Schalnat 已提交
1094 1095 1096 1097
}

void
png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
G
Guy Schalnat 已提交
1098 1099
   png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
   png_progressive_end_ptr end_fn)
G
Guy Schalnat 已提交
1100
{
G
Guy Schalnat 已提交
1101 1102
   png_ptr->info_fn = info_fn;
   png_ptr->row_fn = row_fn;
G
Guy Schalnat 已提交
1103
   png_ptr->end_fn = end_fn;
G
Guy Schalnat 已提交
1104 1105

   png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
G
Guy Schalnat 已提交
1106 1107
}

A
Andreas Dilger 已提交
1108 1109
png_voidp
png_get_progressive_ptr(png_structp png_ptr)
G
Guy Schalnat 已提交
1110
{
A
Andreas Dilger 已提交
1111
   return png_ptr->io_ptr;
G
Guy Schalnat 已提交
1112 1113
}

G
Guy Schalnat 已提交
1114 1115
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */