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

/* pngpread.c - read a png file in push mode
3 4 5 6 7 8 9
 *
 * libpng 1.00.97
 * 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
 * May 28, 1997
 */
G
Guy Schalnat 已提交
10 11 12 13

#define PNG_INTERNAL
#include "png.h"

G
Guy Schalnat 已提交
14 15
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED

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

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

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

A
Andreas Dilger 已提交
78 79 80 81 82
/* 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 已提交
83
void
A
Andreas Dilger 已提交
84
png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
85
{
A
Andreas Dilger 已提交
86 87
   png_size_t num_checked = png_ptr->sig_bytes,
             num_to_check = 8 - num_checked;
G
Guy Schalnat 已提交
88

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

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

A
Andreas Dilger 已提交
98
   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
G
Guy Schalnat 已提交
99
   {
A
Andreas Dilger 已提交
100 101 102 103 104
      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 已提交
105 106 107
   }
   else
   {
A
Andreas Dilger 已提交
108 109 110 111
      if (png_ptr->sig_bytes >= 8)
      {
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
      }
G
Guy Schalnat 已提交
112
   }
G
Guy Schalnat 已提交
113 114 115
}

void
A
Andreas Dilger 已提交
116
png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
117
{
A
Andreas Dilger 已提交
118
   /* First we make sure we have enough data for the 4 byte chunk name
119 120 121 122 123
    * 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 已提交
124
   if (!(png_ptr->flags & PNG_FLAG_HAVE_CHUNK_HEADER))
G
Guy Schalnat 已提交
125
   {
A
Andreas Dilger 已提交
126
      png_byte chunk_length[4];
G
Guy Schalnat 已提交
127 128 129 130 131 132 133

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

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

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

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

      png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
160
   }
A
Andreas Dilger 已提交
161
   else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
G
Guy Schalnat 已提交
162
   {
A
Andreas Dilger 已提交
163
      /* If we reach an IDAT chunk, this means we have read all of the
164 165 166
       * 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 已提交
167 168 169 170 171 172 173 174 175
      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 已提交
176
      png_ptr->idat_size = png_ptr->push_length;
A
Andreas Dilger 已提交
177
      png_ptr->mode |= PNG_HAVE_IDAT;
G
Guy Schalnat 已提交
178
      png_ptr->process_mode = PNG_READ_IDAT_MODE;
A
Andreas Dilger 已提交
179 180 181
      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 已提交
182 183
      return;
   }
A
Andreas Dilger 已提交
184
   else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
G
Guy Schalnat 已提交
185
   {
A
Andreas Dilger 已提交
186 187 188 189 190 191 192 193 194
      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 已提交
195
   }
G
Guy Schalnat 已提交
196
#if defined(PNG_READ_gAMA_SUPPORTED)
A
Andreas Dilger 已提交
197
   else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
G
Guy Schalnat 已提交
198 199 200 201 202 203 204
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

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

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

A
Andreas Dilger 已提交
229
      png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
230
   }
G
Guy Schalnat 已提交
231
#endif
232 233 234 235 236 237 238 239 240 241 242 243
#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 已提交
244
#if defined(PNG_READ_tRNS_SUPPORTED)
A
Andreas Dilger 已提交
245
   else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
G
Guy Schalnat 已提交
246 247 248 249 250 251 252
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

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

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

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

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

A
Andreas Dilger 已提交
301
      png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
G
Guy Schalnat 已提交
302
   }
G
Guy Schalnat 已提交
303
#endif
A
Andreas Dilger 已提交
304 305 306 307 308 309 310 311 312 313 314 315
#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 已提交
316
#if defined(PNG_READ_tIME_SUPPORTED)
A
Andreas Dilger 已提交
317
   else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
G
Guy Schalnat 已提交
318 319 320 321 322 323 324
   {
      if (png_ptr->push_length + 4 > png_ptr->buffer_size)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

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

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

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

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

A
Andreas Dilger 已提交
362 363
      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 已提交
364 365 366 367 368 369 370 371
      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 已提交
372
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
373 374 375
   }
   if (png_ptr->skip_length && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
376
      png_size_t save_size;
G
Guy Schalnat 已提交
377

A
Andreas Dilger 已提交
378 379
      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 已提交
380 381 382 383 384 385 386 387
      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 已提交
388
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
389 390 391 392 393 394 395 396
   }
   if (!png_ptr->skip_length)
   {
      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }
A
Andreas Dilger 已提交
397 398

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

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

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

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

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

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

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

void
png_push_save_buffer(png_structp png_ptr)
{
G
Guy Schalnat 已提交
444 445 446 447
   if (png_ptr->save_buffer_size)
   {
      if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
      {
A
Andreas Dilger 已提交
448
         png_size_t i;
G
Guy Schalnat 已提交
449 450 451 452 453 454 455 456 457 458 459 460 461 462
         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 已提交
463
      png_size_t new_max;
G
Guy Schalnat 已提交
464 465
      png_bytep old_buffer;

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

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

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

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

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

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

      if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
G
Guy Schalnat 已提交
515
      {
A
Andreas Dilger 已提交
516
         png_ptr->process_mode = PNG_READ_CHUNK_MODE;
G
Guy Schalnat 已提交
517
         if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
G
Guy Schalnat 已提交
518 519 520 521 522 523 524 525
            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 已提交
526
      png_size_t save_size;
G
Guy Schalnat 已提交
527

A
Andreas Dilger 已提交
528
      if (png_ptr->idat_size < (png_uint_32)png_ptr->save_buffer_size)
G
Guy Schalnat 已提交
529 530 531 532 533 534 535 536 537 538
         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 已提交
539
      png_ptr->save_buffer_ptr += save_size;
G
Guy Schalnat 已提交
540 541 542
   }
   if (png_ptr->idat_size && png_ptr->current_buffer_size)
   {
A
Andreas Dilger 已提交
543
      png_size_t save_size;
G
Guy Schalnat 已提交
544

A
Andreas Dilger 已提交
545
      if (png_ptr->idat_size < (png_uint_32)png_ptr->current_buffer_size)
G
Guy Schalnat 已提交
546 547 548 549 550 551 552 553 554 555
         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 已提交
556
      png_ptr->current_buffer_ptr += save_size;
G
Guy Schalnat 已提交
557 558 559 560 561 562 563 564 565
   }
   if (!png_ptr->idat_size)
   {
      if (png_ptr->buffer_size < 4)
      {
         png_push_save_buffer(png_ptr);
         return;
      }

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

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

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

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

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

void
png_push_process_row(png_structp png_ptr)
{
G
Guy Schalnat 已提交
616
   png_ptr->row_info.color_type = png_ptr->color_type;
G
Guy Schalnat 已提交
617 618 619 620 621 622 623
   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 已提交
624 625 626
   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 已提交
627

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

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

#if defined(PNG_READ_INTERLACING_SUPPORTED)
G
Guy Schalnat 已提交
634
   /* blow up interlaced rows to full size */
A
Andreas Dilger 已提交
635
   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
G
Guy Schalnat 已提交
636 637 638
   {
      if (png_ptr->pass < 6)
         png_do_read_interlace(&(png_ptr->row_info),
A
Andreas Dilger 已提交
639
            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
G
Guy Schalnat 已提交
640 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

      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 已提交
746
#endif
G
Guy Schalnat 已提交
747 748 749 750
   {
      png_push_have_row(png_ptr, png_ptr->row_buf + 1);
      png_read_push_finish_row(png_ptr);
   }
G
Guy Schalnat 已提交
751 752 753 754 755 756 757
}

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 已提交
758
      return;
G
Guy Schalnat 已提交
759 760 761 762

   if (png_ptr->interlaced)
   {
      png_ptr->row_number = 0;
A
Andreas Dilger 已提交
763
      png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
G
Guy Schalnat 已提交
764 765 766 767 768 769 770 771 772 773 774 775
      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 已提交
776
         {
G
Guy Schalnat 已提交
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
            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 已提交
792
png_push_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
G
Guy Schalnat 已提交
793
{
A
Andreas Dilger 已提交
794 795 796
   if (png_ptr->mode == PNG_BEFORE_IHDR || png_ptr->mode & PNG_HAVE_IEND)
      png_error(png_ptr, "Out of place tEXt");

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

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

   png_ptr->current_text = (png_charp)png_malloc(png_ptr, length+1);
   png_ptr->current_text[length] = '\0';
G
Guy Schalnat 已提交
810 811 812 813
   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 已提交
814 815 816
}

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

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

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

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

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

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

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

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

A
Andreas Dilger 已提交
859 860 861 862
      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 已提交
863

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

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

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

A
Andreas Dilger 已提交
878 879 880 881 882
#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.
    */
883
   if (length > (png_uint_32)65535L)
A
Andreas Dilger 已提交
884 885 886 887 888 889 890 891 892
   {
      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 已提交
893 894 895 896
   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 已提交
897 898 899
}

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

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

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

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

      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 已提交
937
      if (text == key + png_ptr->current_text_size)
G
Guy Schalnat 已提交
938
      {
A
Andreas Dilger 已提交
939
         png_free(png_ptr, key);
G
Guy Schalnat 已提交
940 941 942 943 944
         return;
      }

      text++;

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

      text++;

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

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

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

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

         if (ret == Z_STREAM_END)
            break;
      }

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

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

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

A
Andreas Dilger 已提交
1033 1034 1035 1036 1037 1038 1039 1040
      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 已提交
1041
   }
G
Guy Schalnat 已提交
1042 1043 1044
}
#endif

A
Andreas Dilger 已提交
1045
/* This function is called when we haven't found a handler for this
1046 1047 1048 1049 1050 1051
 * 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 已提交
1052
void
A
Andreas Dilger 已提交
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069
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))
   {
      char msg[40];

      sprintf(msg, "Unknown critical chunk %s", png_ptr->chunk_name);
      png_error(png_ptr, msg);
   }

   png_push_crc_skip(png_ptr, length);
}

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

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

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

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

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

   png_set_read_fn(png_ptr, progressive_ptr, png_push_fill_buffer);
G
Guy Schalnat 已提交
1108 1109
}

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

G
Guy Schalnat 已提交
1116 1117
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */