pngread.c 29.7 KB
Newer Older
G
Guy Schalnat 已提交
1

A
Andreas Dilger 已提交
2
/* pngread.c - read a PNG file
3
 *
4
 * libpng 1.0.5c - November 27, 1999
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, 1999 Glenn Randers-Pehrson
9 10 11 12
 *
 * This file contains routines that an application calls directly to
 * read a PNG file or stream.
 */
G
Guy Schalnat 已提交
13 14 15 16

#define PNG_INTERNAL
#include "png.h"

A
Andreas Dilger 已提交
17
/* Create a PNG structure for reading, and allocate any memory needed. */
G
Guy Schalnat 已提交
18
png_structp
19
png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
A
Andreas Dilger 已提交
20
   png_error_ptr error_fn, png_error_ptr warn_fn)
G
Guy Schalnat 已提交
21
{
22 23 24 25 26 27 28 29 30 31 32 33 34 35

#ifdef PNG_USER_MEM_SUPPORTED
   return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
      warn_fn, NULL, NULL, NULL));
}

/* Alternate create PNG structure for reading, and allocate any memory needed. */
png_structp
png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr,
   png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
   png_malloc_ptr malloc_fn, png_free_ptr free_fn)
{
#endif /* PNG_USER_MEM_SUPPORTED */

G
Guy Schalnat 已提交
36
   png_structp png_ptr;
A
Andreas Dilger 已提交
37 38 39
#ifdef USE_FAR_KEYWORD
   jmp_buf jmpbuf;
#endif
A
Andreas Dilger 已提交
40
   png_debug(1, "in png_create_read_struct\n");
41 42 43 44
#ifdef PNG_USER_MEM_SUPPORTED
   if ((png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
      (png_malloc_ptr)malloc_fn)) == NULL)
#else
G
Guy Schalnat 已提交
45
   if ((png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG)) == NULL)
46
#endif
G
Guy Schalnat 已提交
47 48 49
   {
      return (png_structp)NULL;
   }
A
Andreas Dilger 已提交
50 51 52
#ifdef USE_FAR_KEYWORD
   if (setjmp(jmpbuf))
#else
G
Guy Schalnat 已提交
53
   if (setjmp(png_ptr->jmpbuf))
A
Andreas Dilger 已提交
54
#endif
G
Guy Schalnat 已提交
55
   {
A
Andreas Dilger 已提交
56
      png_free(png_ptr, png_ptr->zbuf);
G
Guy Schalnat 已提交
57 58 59
      png_destroy_struct(png_ptr);
      return (png_structp)NULL;
   }
A
Andreas Dilger 已提交
60 61 62
#ifdef USE_FAR_KEYWORD
   png_memcpy(png_ptr->jmpbuf,jmpbuf,sizeof(jmp_buf));
#endif
63 64 65 66 67

#ifdef PNG_USER_MEM_SUPPORTED
   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
#endif /* PNG_USER_MEM_SUPPORTED */

A
Andreas Dilger 已提交
68 69
   png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);

A
Andreas Dilger 已提交
70 71 72 73 74 75 76
   /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
    * we must recompile any applications that use any older library version.
    * For versions after libpng 1.0, we will be compatible, so we need
    * only check the first digit.
    */
   if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
       (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
G
Guy Schalnat 已提交
77
   {
A
Andreas Dilger 已提交
78
      png_error(png_ptr,
A
Andreas Dilger 已提交
79
         "Incompatible libpng version in application and library");
G
Guy Schalnat 已提交
80 81 82 83
   }

   /* initialize zbuf - compression buffer */
   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
84 85
   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
     (png_uint_32)png_ptr->zbuf_size);
A
Andreas Dilger 已提交
86 87 88
   png_ptr->zstream.zalloc = png_zalloc;
   png_ptr->zstream.zfree = png_zfree;
   png_ptr->zstream.opaque = (voidpf)png_ptr;
G
Guy Schalnat 已提交
89

A
Andreas Dilger 已提交
90
   switch (inflateInit(&png_ptr->zstream))
G
Guy Schalnat 已提交
91 92 93 94 95 96 97 98
   {
     case Z_OK: /* Do nothing */ break;
     case Z_MEM_ERROR:
     case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break;
     case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); break;
     default: png_error(png_ptr, "Unknown zlib error");
   }

A
Andreas Dilger 已提交
99 100
   png_ptr->zstream.next_out = png_ptr->zbuf;
   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
101 102 103 104 105 106

   png_set_read_fn(png_ptr, NULL, NULL);

   return (png_ptr);
}

A
Andreas Dilger 已提交
107
/* Initialize PNG structure for reading, and allocate any memory needed.
108
   This interface is deprecated in favour of the png_create_read_struct(),
A
Andreas Dilger 已提交
109
   and it will eventually disappear. */
G
Guy Schalnat 已提交
110
void
G
Guy Schalnat 已提交
111
png_read_init(png_structp png_ptr)
G
Guy Schalnat 已提交
112
{
G
Guy Schalnat 已提交
113
   jmp_buf tmp_jmp;  /* to save current jump buffer */
G
Guy Schalnat 已提交
114

A
Andreas Dilger 已提交
115
   png_debug(1, "in png_read_init\n");
G
Guy Schalnat 已提交
116
   /* save jump buffer and error functions */
G
Guy Schalnat 已提交
117
   png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
G
Guy Schalnat 已提交
118

G
Guy Schalnat 已提交
119
   /* reset all variables to 0 */
G
Guy Schalnat 已提交
120
   png_memset(png_ptr, 0, sizeof (png_struct));
G
Guy Schalnat 已提交
121

G
Guy Schalnat 已提交
122
   /* restore jump buffer */
G
Guy Schalnat 已提交
123
   png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
G
Guy Schalnat 已提交
124

G
Guy Schalnat 已提交
125
   /* initialize zbuf - compression buffer */
G
Guy Schalnat 已提交
126
   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
127 128
   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
     (png_uint_32)png_ptr->zbuf_size);
A
Andreas Dilger 已提交
129 130 131
   png_ptr->zstream.zalloc = png_zalloc;
   png_ptr->zstream.zfree = png_zfree;
   png_ptr->zstream.opaque = (voidpf)png_ptr;
G
Guy Schalnat 已提交
132

A
Andreas Dilger 已提交
133
   switch (inflateInit(&png_ptr->zstream))
G
Guy Schalnat 已提交
134 135 136 137 138 139 140 141
   {
     case Z_OK: /* Do nothing */ break;
     case Z_MEM_ERROR:
     case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory"); break;
     case Z_VERSION_ERROR: png_error(png_ptr, "zlib version"); break;
     default: png_error(png_ptr, "Unknown zlib error");
   }

A
Andreas Dilger 已提交
142 143
   png_ptr->zstream.next_out = png_ptr->zbuf;
   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
144 145

   png_set_read_fn(png_ptr, NULL, NULL);
G
Guy Schalnat 已提交
146 147
}

A
Andreas Dilger 已提交
148
/* Read the information before the actual image data.  This has been
149
 * changed in v0.90 to allow reading a file that already has the magic
A
Andreas Dilger 已提交
150
 * bytes read from the stream.  You can tell libpng how many bytes have
151
 * been read from the beginning of the stream (up to the maximum of 8)
A
Andreas Dilger 已提交
152 153 154 155
 * via png_set_sig_bytes(), and we will only check the remaining bytes
 * here.  The application can then have access to the signature bytes we
 * read if it is determined that this isn't a valid PNG file.
 */
G
Guy Schalnat 已提交
156
void
A
Andreas Dilger 已提交
157
png_read_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
158
{
159
#include "pngtypes.h"
A
Andreas Dilger 已提交
160 161
   png_debug(1, "in png_read_info\n");
   /* save jump buffer and error functions */
A
Andreas Dilger 已提交
162 163
   /* If we haven't checked all of the PNG signature bytes, do so now. */
   if (png_ptr->sig_bytes < 8)
G
Guy Schalnat 已提交
164
   {
A
Andreas Dilger 已提交
165 166
      png_size_t num_checked = png_ptr->sig_bytes,
                 num_to_check = 8 - num_checked;
A
Andreas Dilger 已提交
167

A
Andreas Dilger 已提交
168
      png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
A
Andreas Dilger 已提交
169 170 171 172 173 174 175 176 177 178
      png_ptr->sig_bytes = 8;

      if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
      {
         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 已提交
179
   }
G
Guy Schalnat 已提交
180

181
   for(;;)
G
Guy Schalnat 已提交
182
   {
A
Andreas Dilger 已提交
183 184
      png_byte chunk_length[4];
      png_uint_32 length;
G
Guy Schalnat 已提交
185

A
Andreas Dilger 已提交
186 187
      png_read_data(png_ptr, chunk_length, 4);
      length = png_get_uint_32(chunk_length);
G
Guy Schalnat 已提交
188

A
Andreas Dilger 已提交
189 190 191
      png_reset_crc(png_ptr);
      png_crc_read(png_ptr, png_ptr->chunk_name, 4);

192 193
      png_debug2(0, "Reading %s chunk, length=%d.\n", png_ptr->chunk_name,
         length);
A
Andreas Dilger 已提交
194 195 196 197

      /* This should be a binary subdivision search or a hash for
       * matching the chunk name rather than a linear search.
       */
A
Andreas Dilger 已提交
198 199 200 201 202 203
      if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
         png_handle_IHDR(png_ptr, info_ptr, length);
      else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
         png_handle_PLTE(png_ptr, info_ptr, length);
      else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
         png_handle_IEND(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
      else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
      {
         if (!(png_ptr->mode & PNG_HAVE_IHDR))
            png_error(png_ptr, "Missing IHDR before IDAT");
         else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
                  !(png_ptr->mode & PNG_HAVE_PLTE))
            png_error(png_ptr, "Missing PLTE before IDAT");

         png_ptr->idat_size = length;
         png_ptr->mode |= PNG_HAVE_IDAT;
         break;
      }
#if defined(PNG_READ_bKGD_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
         png_handle_bKGD(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
219 220
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
A
Andreas Dilger 已提交
221 222
      else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
         png_handle_cHRM(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
223
#endif
A
Andreas Dilger 已提交
224 225 226
#if defined(PNG_READ_gAMA_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
         png_handle_gAMA(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
227 228
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
A
Andreas Dilger 已提交
229 230
      else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
         png_handle_hIST(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
231
#endif
A
Andreas Dilger 已提交
232 233 234 235 236 237 238 239
#if defined(PNG_READ_oFFs_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
         png_handle_oFFs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
         png_handle_pCAL(png_ptr, info_ptr, length);
#endif
G
Guy Schalnat 已提交
240
#if defined(PNG_READ_pHYs_SUPPORTED)
A
Andreas Dilger 已提交
241 242
      else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
         png_handle_pHYs(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
243
#endif
A
Andreas Dilger 已提交
244 245 246 247
#if defined(PNG_READ_sBIT_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
         png_handle_sBIT(png_ptr, info_ptr, length);
#endif
248 249 250 251
#if defined(PNG_READ_sRGB_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
         png_handle_sRGB(png_ptr, info_ptr, length);
#endif
A
Andreas Dilger 已提交
252 253 254
#if defined(PNG_READ_tEXt_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
         png_handle_tEXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
255 256
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
A
Andreas Dilger 已提交
257 258
      else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
         png_handle_tIME(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
259
#endif
A
Andreas Dilger 已提交
260 261 262
#if defined(PNG_READ_tRNS_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
         png_handle_tRNS(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
263 264
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
A
Andreas Dilger 已提交
265 266
      else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
         png_handle_zTXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
267
#endif
A
Andreas Dilger 已提交
268 269
      else
         png_handle_unknown(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
270 271 272
   }
}

A
Andreas Dilger 已提交
273
/* optional call to update the users info_ptr structure */
G
Guy Schalnat 已提交
274
void
A
Andreas Dilger 已提交
275
png_read_update_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
276
{
A
Andreas Dilger 已提交
277 278
   png_debug(1, "in png_read_update_info\n");
   /* save jump buffer and error functions */
G
Guy Schalnat 已提交
279
   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
G
Guy Schalnat 已提交
280
      png_read_start_row(png_ptr);
A
Andreas Dilger 已提交
281
   png_read_transform_info(png_ptr, info_ptr);
G
Guy Schalnat 已提交
282 283
}

284 285
/* Initialize palette, background, etc, after transformations
 * are set, but before any reading takes place.  This allows
286
 * the user to obtain a gamma-corrected palette, for example.
287 288
 * If the user doesn't call this, we will do it ourselves.
 */
G
Guy Schalnat 已提交
289
void
G
Guy Schalnat 已提交
290
png_start_read_image(png_structp png_ptr)
G
Guy Schalnat 已提交
291
{
A
Andreas Dilger 已提交
292 293
   png_debug(1, "in png_start_read_image\n");
   /* save jump buffer and error functions */
G
Guy Schalnat 已提交
294
   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
G
Guy Schalnat 已提交
295
      png_read_start_row(png_ptr);
G
Guy Schalnat 已提交
296 297 298
}

void
G
Guy Schalnat 已提交
299
png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
G
Guy Schalnat 已提交
300
{
301 302 303
   const png_byte png_IDAT[5] = { 73,  68,  65,  84, '\0'};
   const int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 0xff};
   const int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
G
Guy Schalnat 已提交
304
   int ret;
A
Andreas Dilger 已提交
305 306 307
   png_debug2(1, "in png_read_row (row %d, pass %d)\n",
      png_ptr->row_number, png_ptr->pass);
   /* save jump buffer and error functions */
G
Guy Schalnat 已提交
308
   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
G
Guy Schalnat 已提交
309
      png_read_start_row(png_ptr);
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
   {
   /* check for transforms that have been set but were defined out */
#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
   if (png_ptr->transformations & PNG_INVERT_MONO)
      png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined.");
#endif
#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
   if (png_ptr->transformations & PNG_FILLER)
      png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined.");
#endif
#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && !defined(PNG_READ_PACKSWAP_SUPPORTED)
   if (png_ptr->transformations & PNG_PACKSWAP)
      png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined.");
#endif
#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
   if (png_ptr->transformations & PNG_PACK)
      png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined.");
#endif
#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
   if (png_ptr->transformations & PNG_SHIFT)
      png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined.");
#endif
#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
   if (png_ptr->transformations & PNG_BGR)
      png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined.");
#endif
#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
   if (png_ptr->transformations & PNG_SWAP_BYTES)
      png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined.");
#endif
   }
G
Guy Schalnat 已提交
342

G
Guy Schalnat 已提交
343
#if defined(PNG_READ_INTERLACING_SUPPORTED)
G
Guy Schalnat 已提交
344 345 346 347 348 349 350 351
   /* if interlaced and we do not need a new row, combine row and return */
   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
   {
      switch (png_ptr->pass)
      {
         case 0:
            if (png_ptr->row_number & 7)
            {
A
Andreas Dilger 已提交
352
               if (dsp_row != NULL)
G
Guy Schalnat 已提交
353 354
                  png_combine_row(png_ptr, dsp_row,
                     png_pass_dsp_mask[png_ptr->pass]);
G
Guy Schalnat 已提交
355
               png_read_finish_row(png_ptr);
G
Guy Schalnat 已提交
356 357 358 359 360 361
               return;
            }
            break;
         case 1:
            if ((png_ptr->row_number & 7) || png_ptr->width < 5)
            {
A
Andreas Dilger 已提交
362
               if (dsp_row != NULL)
G
Guy Schalnat 已提交
363 364 365 366 367 368 369 370 371
                  png_combine_row(png_ptr, dsp_row,
                     png_pass_dsp_mask[png_ptr->pass]);
               png_read_finish_row(png_ptr);
               return;
            }
            break;
         case 2:
            if ((png_ptr->row_number & 7) != 4)
            {
A
Andreas Dilger 已提交
372
               if (dsp_row != NULL && (png_ptr->row_number & 4))
G
Guy Schalnat 已提交
373
                  png_combine_row(png_ptr, dsp_row,
G
Guy Schalnat 已提交
374 375 376 377 378 379 380 381
                     png_pass_dsp_mask[png_ptr->pass]);
               png_read_finish_row(png_ptr);
               return;
            }
            break;
         case 3:
            if ((png_ptr->row_number & 3) || png_ptr->width < 3)
            {
A
Andreas Dilger 已提交
382
               if (dsp_row != NULL)
G
Guy Schalnat 已提交
383 384 385 386 387 388 389 390
                  png_combine_row(png_ptr, dsp_row,
                     png_pass_dsp_mask[png_ptr->pass]);
               png_read_finish_row(png_ptr);
               return;
            }
            break;
         case 4:
            if ((png_ptr->row_number & 3) != 2)
G
Guy Schalnat 已提交
391
            {
A
Andreas Dilger 已提交
392
               if (dsp_row != NULL && (png_ptr->row_number & 2))
G
Guy Schalnat 已提交
393 394 395 396 397 398 399 400 401
                  png_combine_row(png_ptr, dsp_row,
                     png_pass_dsp_mask[png_ptr->pass]);
               png_read_finish_row(png_ptr);
               return;
            }
            break;
         case 5:
            if ((png_ptr->row_number & 1) || png_ptr->width < 2)
            {
A
Andreas Dilger 已提交
402
               if (dsp_row != NULL)
G
Guy Schalnat 已提交
403 404 405 406 407 408
                  png_combine_row(png_ptr, dsp_row,
                     png_pass_dsp_mask[png_ptr->pass]);
               png_read_finish_row(png_ptr);
               return;
            }
            break;
G
Guy Schalnat 已提交
409
         case 6:
G
Guy Schalnat 已提交
410 411 412 413 414 415 416 417
            if (!(png_ptr->row_number & 1))
            {
               png_read_finish_row(png_ptr);
               return;
            }
            break;
      }
   }
G
Guy Schalnat 已提交
418
#endif
G
Guy Schalnat 已提交
419

G
Guy Schalnat 已提交
420 421
   if (!(png_ptr->mode & PNG_HAVE_IDAT))
      png_error(png_ptr, "Invalid attempt to read row data");
G
Guy Schalnat 已提交
422

A
Andreas Dilger 已提交
423 424
   png_ptr->zstream.next_out = png_ptr->row_buf;
   png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
G
Guy Schalnat 已提交
425 426
   do
   {
A
Andreas Dilger 已提交
427
      if (!(png_ptr->zstream.avail_in))
G
Guy Schalnat 已提交
428 429 430
      {
         while (!png_ptr->idat_size)
         {
A
Andreas Dilger 已提交
431
            png_byte chunk_length[4];
G
Guy Schalnat 已提交
432

A
Andreas Dilger 已提交
433
            png_crc_finish(png_ptr, 0);
G
Guy Schalnat 已提交
434

A
Andreas Dilger 已提交
435 436
            png_read_data(png_ptr, chunk_length, 4);
            png_ptr->idat_size = png_get_uint_32(chunk_length);
G
Guy Schalnat 已提交
437

A
Andreas Dilger 已提交
438 439 440 441
            png_reset_crc(png_ptr);
            png_crc_read(png_ptr, png_ptr->chunk_name, 4);
            if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
               png_error(png_ptr, "Not enough image data");
G
Guy Schalnat 已提交
442
         }
A
Andreas Dilger 已提交
443 444
         png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
         png_ptr->zstream.next_in = png_ptr->zbuf;
G
Guy Schalnat 已提交
445
         if (png_ptr->zbuf_size > png_ptr->idat_size)
A
Andreas Dilger 已提交
446
            png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
A
Andreas Dilger 已提交
447 448
         png_crc_read(png_ptr, png_ptr->zbuf,
            (png_size_t)png_ptr->zstream.avail_in);
A
Andreas Dilger 已提交
449
         png_ptr->idat_size -= png_ptr->zstream.avail_in;
G
Guy Schalnat 已提交
450
      }
A
Andreas Dilger 已提交
451
      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
G
Guy Schalnat 已提交
452 453
      if (ret == Z_STREAM_END)
      {
A
Andreas Dilger 已提交
454
         if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
G
Guy Schalnat 已提交
455
            png_ptr->idat_size)
G
Guy Schalnat 已提交
456
            png_error(png_ptr, "Extra compressed data");
A
Andreas Dilger 已提交
457
         png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
458
         png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
G
Guy Schalnat 已提交
459
         break;
G
Guy Schalnat 已提交
460 461
      }
      if (ret != Z_OK)
A
Andreas Dilger 已提交
462
         png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
G
Guy Schalnat 已提交
463
                   "Decompression error");
A
Andreas Dilger 已提交
464 465

   } while (png_ptr->zstream.avail_out);
G
Guy Schalnat 已提交
466 467 468 469 470 471

   png_ptr->row_info.color_type = png_ptr->color_type;
   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;
472 473
   png_ptr->row_info.rowbytes = ((png_ptr->row_info.width *
      (png_uint_32)png_ptr->row_info.pixel_depth + 7) >> 3);
G
Guy Schalnat 已提交
474

G
Guy Schalnat 已提交
475 476 477
   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 已提交
478

479
   png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
480
      png_ptr->rowbytes + 1);
G
Guy Schalnat 已提交
481 482 483 484

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

G
Guy Schalnat 已提交
485
#if defined(PNG_READ_INTERLACING_SUPPORTED)
G
Guy Schalnat 已提交
486 487 488 489 490 491
   /* blow up interlaced rows to full size */
   if (png_ptr->interlaced &&
      (png_ptr->transformations & PNG_INTERLACE))
   {
      if (png_ptr->pass < 6)
         png_do_read_interlace(&(png_ptr->row_info),
A
Andreas Dilger 已提交
492
            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
G
Guy Schalnat 已提交
493

A
Andreas Dilger 已提交
494
      if (dsp_row != NULL)
G
Guy Schalnat 已提交
495 496
         png_combine_row(png_ptr, dsp_row,
            png_pass_dsp_mask[png_ptr->pass]);
A
Andreas Dilger 已提交
497
      if (row != NULL)
G
Guy Schalnat 已提交
498 499 500 501
         png_combine_row(png_ptr, row,
            png_pass_mask[png_ptr->pass]);
   }
   else
G
Guy Schalnat 已提交
502
#endif
G
Guy Schalnat 已提交
503
   {
A
Andreas Dilger 已提交
504
      if (row != NULL)
G
Guy Schalnat 已提交
505
         png_combine_row(png_ptr, row, 0xff);
A
Andreas Dilger 已提交
506
      if (dsp_row != NULL)
G
Guy Schalnat 已提交
507 508 509
         png_combine_row(png_ptr, dsp_row, 0xff);
   }
   png_read_finish_row(png_ptr);
510 511 512

   if (png_ptr->read_row_fn != NULL)
      (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
G
Guy Schalnat 已提交
513 514
}

A
Andreas Dilger 已提交
515
/* Read one or more rows of image data.  If the image is interlaced,
516 517
 * and png_set_interlace_handling() has been called, the rows need to
 * contain the contents of the rows from the previous pass.  If the
518
 * image has alpha or transparency, and png_handle_alpha()[*] has been
519 520
 * called, the rows contents must be initialized to the contents of the
 * screen.
521
 *
522 523 524 525 526 527 528 529 530 531 532 533 534
 * "row" holds the actual image, and pixels are placed in it
 * as they arrive.  If the image is displayed after each pass, it will
 * appear to "sparkle" in.  "display_row" can be used to display a
 * "chunky" progressive image, with finer detail added as it becomes
 * available.  If you do not want this "chunky" display, you may pass
 * NULL for display_row.  If you do not want the sparkle display, and
 * you have not called png_handle_alpha(), you may pass NULL for rows.
 * If you have called png_handle_alpha(), and the image has either an
 * alpha channel or a transparency chunk, you must provide a buffer for
 * rows.  In this case, you do not have to provide a display_row buffer
 * also, but you may.  If the image is not interlaced, or if you have
 * not called png_set_interlace_handling(), the display_row buffer will
 * be ignored, so pass NULL to it.
535
 *
536
 * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.5c.
537
 */
G
Guy Schalnat 已提交
538

G
Guy Schalnat 已提交
539
void
G
Guy Schalnat 已提交
540
png_read_rows(png_structp png_ptr, png_bytepp row,
G
Guy Schalnat 已提交
541
   png_bytepp display_row, png_uint_32 num_rows)
G
Guy Schalnat 已提交
542
{
G
Guy Schalnat 已提交
543 544 545
   png_uint_32 i;
   png_bytepp rp;
   png_bytepp dp;
G
Guy Schalnat 已提交
546

A
Andreas Dilger 已提交
547 548
   png_debug(1, "in png_read_rows\n");
   /* save jump buffer and error functions */
G
Guy Schalnat 已提交
549 550
   rp = row;
   dp = display_row;
551
   if (rp != NULL && dp != NULL)
552 553 554 555
      for (i = 0; i < num_rows; i++)
      {
         png_bytep rptr = *rp++;
         png_bytep dptr = *dp++;
556

557 558
         png_read_row(png_ptr, rptr, dptr);
      }
559
   else if(rp != NULL)
560 561
      for (i = 0; i < num_rows; i++)
      {
562 563 564 565 566 567 568 569 570 571
         png_bytep rptr = *rp;
         png_read_row(png_ptr, rptr, NULL);
         rp++;
      }
   else if(dp != NULL)
      for (i = 0; i < num_rows; i++)
      {
         png_bytep dptr = *dp;
         png_read_row(png_ptr, NULL, dptr);
         dp++;
572
      }
G
Guy Schalnat 已提交
573 574
}

A
Andreas Dilger 已提交
575
/* Read the entire image.  If the image has an alpha channel or a tRNS
576
 * chunk, and you have called png_handle_alpha()[*], you will need to
577 578 579 580 581 582 583
 * initialize the image to the current image that PNG will be overlaying.
 * We set the num_rows again here, in case it was incorrectly set in
 * png_read_start_row() by a call to png_read_update_info() or
 * png_start_read_image() if png_set_interlace_handling() wasn't called
 * prior to either of these functions like it should have been.  You can
 * only call this function once.  If you desire to have an image for
 * each pass of a interlaced image, use png_read_rows() instead.
584
 *
585
 * [*] png_handle_alpha() does not exist yet, as of libpng version 1.0.5c.
586
 */
G
Guy Schalnat 已提交
587
void
G
Guy Schalnat 已提交
588
png_read_image(png_structp png_ptr, png_bytepp image)
G
Guy Schalnat 已提交
589
{
590
   png_uint_32 i,image_height;
G
Guy Schalnat 已提交
591
   int pass, j;
G
Guy Schalnat 已提交
592
   png_bytepp rp;
G
Guy Schalnat 已提交
593

A
Andreas Dilger 已提交
594 595
   png_debug(1, "in png_read_image\n");
   /* save jump buffer and error functions */
596 597

#ifdef PNG_READ_INTERLACING_SUPPORTED
G
Guy Schalnat 已提交
598
   pass = png_set_interlace_handling(png_ptr);
599 600 601 602 603 604 605
#else
   if (png_ptr->interlaced)
      png_error(png_ptr,
        "Cannot read interlaced image -- interlace handler disabled.");
   pass = 1;
#endif

G
Guy Schalnat 已提交
606

607 608
   image_height=png_ptr->height;
   png_ptr->num_rows = image_height; /* Make sure this is set correctly */
G
Guy Schalnat 已提交
609

G
Guy Schalnat 已提交
610 611 612
   for (j = 0; j < pass; j++)
   {
      rp = image;
613
      for (i = 0; i < image_height; i++)
G
Guy Schalnat 已提交
614 615 616 617 618 619 620
      {
         png_read_row(png_ptr, *rp, NULL);
         rp++;
      }
   }
}

A
Andreas Dilger 已提交
621
/* Read the end of the PNG file.  Will not read past the end of the
622 623 624
 * file, will verify the end is accurate, and will read any comments
 * or time information at the end of the file, if info is not NULL.
 */
G
Guy Schalnat 已提交
625
void
A
Andreas Dilger 已提交
626
png_read_end(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
627
{
628
#include "pngtypes.h"
A
Andreas Dilger 已提交
629
   png_byte chunk_length[4];
G
Guy Schalnat 已提交
630 631
   png_uint_32 length;

A
Andreas Dilger 已提交
632 633 634
   png_debug(1, "in png_read_end\n");
   /* save jump buffer and error functions */
   png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
G
Guy Schalnat 已提交
635 636 637

   do
   {
A
Andreas Dilger 已提交
638 639
      png_read_data(png_ptr, chunk_length, 4);
      length = png_get_uint_32(chunk_length);
G
Guy Schalnat 已提交
640

A
Andreas Dilger 已提交
641 642 643
      png_reset_crc(png_ptr);
      png_crc_read(png_ptr, png_ptr->chunk_name, 4);

A
Andreas Dilger 已提交
644 645
      png_debug1(0, "Reading %s chunk.\n", png_ptr->chunk_name);

A
Andreas Dilger 已提交
646 647
      if (!png_memcmp(png_ptr->chunk_name, png_IHDR, 4))
         png_handle_IHDR(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
648 649 650 651 652 653 654 655 656 657
      else if (!png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
      {
         /* Zero length IDATs are legal after the last IDAT has been
          * read, but not after other chunks have been read.
          */
         if (length > 0 || png_ptr->mode & PNG_AFTER_IDAT)
            png_error(png_ptr, "Too many IDAT's found");
         else
            png_crc_finish(png_ptr, 0);
      }
A
Andreas Dilger 已提交
658 659
      else if (!png_memcmp(png_ptr->chunk_name, png_PLTE, 4))
         png_handle_PLTE(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
660 661 662
      else if (!png_memcmp(png_ptr->chunk_name, png_IEND, 4))
         png_handle_IEND(png_ptr, info_ptr, length);
#if defined(PNG_READ_bKGD_SUPPORTED)
A
Andreas Dilger 已提交
663 664
      else if (!png_memcmp(png_ptr->chunk_name, png_bKGD, 4))
         png_handle_bKGD(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
665 666 667 668 669 670 671 672 673 674
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_cHRM, 4))
         png_handle_cHRM(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_gAMA_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_gAMA, 4))
         png_handle_gAMA(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
A
Andreas Dilger 已提交
675 676
      else if (!png_memcmp(png_ptr->chunk_name, png_hIST, 4))
         png_handle_hIST(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
677 678
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
A
Andreas Dilger 已提交
679 680
      else if (!png_memcmp(png_ptr->chunk_name, png_oFFs, 4))
         png_handle_oFFs(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
681 682 683 684 685 686 687 688 689 690 691 692
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_pCAL, 4))
         png_handle_pCAL(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_pHYs, 4))
         png_handle_pHYs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_sBIT, 4))
         png_handle_sBIT(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
693
#endif
694 695 696 697
#if defined(PNG_READ_sRGB_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_sRGB, 4))
         png_handle_sRGB(png_ptr, info_ptr, length);
#endif
G
Guy Schalnat 已提交
698
#if defined(PNG_READ_tEXt_SUPPORTED)
A
Andreas Dilger 已提交
699 700
      else if (!png_memcmp(png_ptr->chunk_name, png_tEXt, 4))
         png_handle_tEXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
701
#endif
A
Andreas Dilger 已提交
702 703 704 705 706 707 708 709
#if defined(PNG_READ_tIME_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_tIME, 4))
         png_handle_tIME(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
      else if (!png_memcmp(png_ptr->chunk_name, png_tRNS, 4))
         png_handle_tRNS(png_ptr, info_ptr, length);
#endif
G
Guy Schalnat 已提交
710
#if defined(PNG_READ_zTXt_SUPPORTED)
A
Andreas Dilger 已提交
711 712
      else if (!png_memcmp(png_ptr->chunk_name, png_zTXt, 4))
         png_handle_zTXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
713
#endif
G
Guy Schalnat 已提交
714
      else
A
Andreas Dilger 已提交
715 716
         png_handle_unknown(png_ptr, info_ptr, length);
   } while (!(png_ptr->mode & PNG_HAVE_IEND));
G
Guy Schalnat 已提交
717 718 719 720
}

/* free all memory used by the read */
void
G
Guy Schalnat 已提交
721
png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
A
Andreas Dilger 已提交
722
   png_infopp end_info_ptr_ptr)
G
Guy Schalnat 已提交
723 724
{
   png_structp png_ptr = NULL;
A
Andreas Dilger 已提交
725
   png_infop info_ptr = NULL, end_info_ptr = NULL;
726 727 728
#ifdef PNG_USER_MEM_SUPPORTED
   png_free_ptr free_fn = NULL;
#endif /* PNG_USER_MEM_SUPPORTED */
G
Guy Schalnat 已提交
729

A
Andreas Dilger 已提交
730 731 732
   png_debug(1, "in png_destroy_read_struct\n");
   /* save jump buffer and error functions */
   if (png_ptr_ptr != NULL)
G
Guy Schalnat 已提交
733 734
      png_ptr = *png_ptr_ptr;

A
Andreas Dilger 已提交
735
   if (info_ptr_ptr != NULL)
G
Guy Schalnat 已提交
736 737
      info_ptr = *info_ptr_ptr;

A
Andreas Dilger 已提交
738
   if (end_info_ptr_ptr != NULL)
A
Andreas Dilger 已提交
739
      end_info_ptr = *end_info_ptr_ptr;
G
Guy Schalnat 已提交
740

741 742 743 744
#ifdef PNG_USER_MEM_SUPPORTED
   free_fn = png_ptr->free_fn;
#endif

A
Andreas Dilger 已提交
745
   png_read_destroy(png_ptr, info_ptr, end_info_ptr);
G
Guy Schalnat 已提交
746

A
Andreas Dilger 已提交
747
   if (info_ptr != NULL)
G
Guy Schalnat 已提交
748
   {
749 750 751
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
      png_free(png_ptr, info_ptr->text);
#endif
752 753 754 755

#ifdef PNG_USER_MEM_SUPPORTED
      png_destroy_struct_2((png_voidp)info_ptr, free_fn);
#else
A
Andreas Dilger 已提交
756
      png_destroy_struct((png_voidp)info_ptr);
757
#endif
G
Guy Schalnat 已提交
758 759 760
      *info_ptr_ptr = (png_infop)NULL;
   }

A
Andreas Dilger 已提交
761
   if (end_info_ptr != NULL)
G
Guy Schalnat 已提交
762
   {
763
#if defined(PNG_READ_tEXt_SUPPORTED) || defined(PNG_READ_zTXt_SUPPORTED)
764
      png_free(png_ptr, end_info_ptr->text);
765
#endif
766 767 768
#ifdef PNG_USER_MEM_SUPPORTED
      png_destroy_struct_2((png_voidp)end_info_ptr, free_fn);
#else
A
Andreas Dilger 已提交
769
      png_destroy_struct((png_voidp)end_info_ptr);
770
#endif
A
Andreas Dilger 已提交
771
      *end_info_ptr_ptr = (png_infop)NULL;
G
Guy Schalnat 已提交
772 773
   }

A
Andreas Dilger 已提交
774
   if (png_ptr != NULL)
G
Guy Schalnat 已提交
775
   {
776 777 778
#ifdef PNG_USER_MEM_SUPPORTED
      png_destroy_struct_2((png_voidp)png_ptr, free_fn);
#else
A
Andreas Dilger 已提交
779
      png_destroy_struct((png_voidp)png_ptr);
780
#endif
G
Guy Schalnat 已提交
781 782 783 784
      *png_ptr_ptr = (png_structp)NULL;
   }
}

A
Andreas Dilger 已提交
785
/* free all memory used by the read (old method) */
G
Guy Schalnat 已提交
786
void
A
Andreas Dilger 已提交
787
png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)
G
Guy Schalnat 已提交
788 789
{
   jmp_buf tmp_jmp;
G
Guy Schalnat 已提交
790 791 792
   png_error_ptr error_fn;
   png_error_ptr warning_fn;
   png_voidp error_ptr;
793 794 795
#ifdef PNG_USER_MEM_SUPPORTED
   png_free_ptr free_fn;
#endif
G
Guy Schalnat 已提交
796

A
Andreas Dilger 已提交
797 798 799
   png_debug(1, "in png_read_destroy\n");
   /* save jump buffer and error functions */
   if (info_ptr != NULL)
A
Andreas Dilger 已提交
800
      png_info_destroy(png_ptr, info_ptr);
G
Guy Schalnat 已提交
801

A
Andreas Dilger 已提交
802
   if (end_info_ptr != NULL)
A
Andreas Dilger 已提交
803
      png_info_destroy(png_ptr, end_info_ptr);
G
Guy Schalnat 已提交
804

A
Andreas Dilger 已提交
805 806 807
   png_free(png_ptr, png_ptr->zbuf);
   png_free(png_ptr, png_ptr->row_buf);
   png_free(png_ptr, png_ptr->prev_row);
G
Guy Schalnat 已提交
808
#if defined(PNG_READ_DITHER_SUPPORTED)
A
Andreas Dilger 已提交
809 810
   png_free(png_ptr, png_ptr->palette_lookup);
   png_free(png_ptr, png_ptr->dither_index);
G
Guy Schalnat 已提交
811 812
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
813
   png_free(png_ptr, png_ptr->gamma_table);
G
Guy Schalnat 已提交
814 815
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
A
Andreas Dilger 已提交
816 817
   png_free(png_ptr, png_ptr->gamma_from_1);
   png_free(png_ptr, png_ptr->gamma_to_1);
G
Guy Schalnat 已提交
818
#endif
A
Andreas Dilger 已提交
819
   if (png_ptr->flags & PNG_FLAG_FREE_PALETTE)
820
      png_zfree(png_ptr, png_ptr->palette);
821 822
#if defined(PNG_READ_tRNS_SUPPORTED) || defined(PNG_WRITE_tRNS_SUPPORTED) || \
    defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
A
Andreas Dilger 已提交
823 824
   if (png_ptr->flags & PNG_FLAG_FREE_TRANS)
      png_free(png_ptr, png_ptr->trans);
825
#endif
G
Guy Schalnat 已提交
826
#if defined(PNG_READ_hIST_SUPPORTED)
A
Andreas Dilger 已提交
827 828
   if (png_ptr->flags & PNG_FLAG_FREE_HIST)
      png_free(png_ptr, png_ptr->hist);
G
Guy Schalnat 已提交
829 830
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
831
   if (png_ptr->gamma_16_table != NULL)
G
Guy Schalnat 已提交
832
   {
833 834
      int i;
      int istop = (1 << (8 - png_ptr->gamma_shift));
835
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
836
      {
A
Andreas Dilger 已提交
837
         png_free(png_ptr, png_ptr->gamma_16_table[i]);
G
Guy Schalnat 已提交
838
      }
839
   png_free(png_ptr, png_ptr->gamma_16_table);
G
Guy Schalnat 已提交
840
   }
G
Guy Schalnat 已提交
841
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
A
Andreas Dilger 已提交
842
   if (png_ptr->gamma_16_from_1 != NULL)
G
Guy Schalnat 已提交
843
   {
844 845
      int i;
      int istop = (1 << (8 - png_ptr->gamma_shift));
846
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
847
      {
A
Andreas Dilger 已提交
848
         png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
G
Guy Schalnat 已提交
849
      }
A
Andreas Dilger 已提交
850
   png_free(png_ptr, png_ptr->gamma_16_from_1);
851
   }
A
Andreas Dilger 已提交
852
   if (png_ptr->gamma_16_to_1 != NULL)
G
Guy Schalnat 已提交
853
   {
854 855
      int i;
      int istop = (1 << (8 - png_ptr->gamma_shift));
856
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
857
      {
A
Andreas Dilger 已提交
858
         png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
G
Guy Schalnat 已提交
859
      }
A
Andreas Dilger 已提交
860
   png_free(png_ptr, png_ptr->gamma_16_to_1);
861
   }
G
Guy Schalnat 已提交
862
#endif
863 864 865 866
#endif
#if defined(PNG_TIME_RFC1123_SUPPORTED)
   png_free(png_ptr, png_ptr->time_buffer);
#endif /* PNG_TIME_RFC1123_SUPPORTED */
G
Guy Schalnat 已提交
867

A
Andreas Dilger 已提交
868
   inflateEnd(&png_ptr->zstream);
G
Guy Schalnat 已提交
869
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
A
Andreas Dilger 已提交
870
   png_free(png_ptr, png_ptr->save_buffer);
G
Guy Schalnat 已提交
871
#endif
G
Guy Schalnat 已提交
872 873 874 875

   /* Save the important info out of the png_struct, in case it is
    * being used again.
    */
G
Guy Schalnat 已提交
876
   png_memcpy(tmp_jmp, png_ptr->jmpbuf, sizeof (jmp_buf));
G
Guy Schalnat 已提交
877 878 879 880

   error_fn = png_ptr->error_fn;
   warning_fn = png_ptr->warning_fn;
   error_ptr = png_ptr->error_ptr;
881 882 883
#ifdef PNG_USER_MEM_SUPPORTED
   free_fn = png_ptr->free_fn;
#endif
G
Guy Schalnat 已提交
884

G
Guy Schalnat 已提交
885
   png_memset(png_ptr, 0, sizeof (png_struct));
G
Guy Schalnat 已提交
886 887 888 889

   png_ptr->error_fn = error_fn;
   png_ptr->warning_fn = warning_fn;
   png_ptr->error_ptr = error_ptr;
890 891 892
#ifdef PNG_USER_MEM_SUPPORTED
   png_ptr->free_fn = free_fn;
#endif
G
Guy Schalnat 已提交
893

G
Guy Schalnat 已提交
894
   png_memcpy(png_ptr->jmpbuf, tmp_jmp, sizeof (jmp_buf));
G
Guy Schalnat 已提交
895
}
896 897 898 899 900 901

void
png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
{
   png_ptr->read_row_fn = read_row_fn;
}