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

A
Andreas Dilger 已提交
2
/* pngread.c - read a PNG file
3
 *
4
 * Last changed in libpng 1.2.30 [August 15, 2008]
5
 * For conditions of distribution and use, see copyright notice in png.h
6
 * Copyright (c) 1998-2008 Glenn Randers-Pehrson
7 8
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
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

#define PNG_INTERNAL
#include "png.h"
16 17
#if defined(PNG_READ_SUPPORTED)

A
Andreas Dilger 已提交
18
/* Create a PNG structure for reading, and allocate any memory needed. */
19
png_structp PNGAPI
20
png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr,
A
Andreas Dilger 已提交
21
   png_error_ptr error_fn, png_error_ptr warn_fn)
G
Guy Schalnat 已提交
22
{
23 24 25

#ifdef PNG_USER_MEM_SUPPORTED
   return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
26
      warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL));
27 28 29
}

/* Alternate create PNG structure for reading, and allocate any memory needed. */
30
png_structp PNGAPI
31 32 33 34 35 36
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 */

37 38 39 40
#ifdef PNG_SETJMP_SUPPORTED
   volatile
#endif
   png_structp png_ptr;
41 42

#ifdef PNG_SETJMP_SUPPORTED
A
Andreas Dilger 已提交
43 44 45
#ifdef USE_FAR_KEYWORD
   jmp_buf jmpbuf;
#endif
46 47
#endif

48 49
   int i;

A
Andreas Dilger 已提交
50
   png_debug(1, "in png_create_read_struct\n");
51
#ifdef PNG_USER_MEM_SUPPORTED
52 53
   png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
      (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
54
#else
55
   png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
56
#endif
57
   if (png_ptr == NULL)
58
      return (NULL);
59

60 61 62 63 64 65
   /* added at libpng-1.2.6 */
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
   png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
   png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
#endif

66
#ifdef PNG_SETJMP_SUPPORTED
A
Andreas Dilger 已提交
67 68 69
#ifdef USE_FAR_KEYWORD
   if (setjmp(jmpbuf))
#else
G
Guy Schalnat 已提交
70
   if (setjmp(png_ptr->jmpbuf))
A
Andreas Dilger 已提交
71
#endif
G
Guy Schalnat 已提交
72
   {
A
Andreas Dilger 已提交
73
      png_free(png_ptr, png_ptr->zbuf);
74
      png_ptr->zbuf = NULL;
75
#ifdef PNG_USER_MEM_SUPPORTED
76
      png_destroy_struct_2((png_voidp)png_ptr,
77
         (png_free_ptr)free_fn, (png_voidp)mem_ptr);
78 79 80
#else
      png_destroy_struct((png_voidp)png_ptr);
#endif
81
      return (NULL);
G
Guy Schalnat 已提交
82
   }
A
Andreas Dilger 已提交
83
#ifdef USE_FAR_KEYWORD
84
   png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
A
Andreas Dilger 已提交
85
#endif
86
#endif
87 88 89

#ifdef PNG_USER_MEM_SUPPORTED
   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
90
#endif
91

A
Andreas Dilger 已提交
92 93
   png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);

94
   if (user_png_ver)
G
Guy Schalnat 已提交
95
   {
96
     i = 0;
97 98
     do
     {
99
       if (user_png_ver[i] != png_libpng_ver[i])
100 101 102 103
          png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
     } while (png_libpng_ver[i++]);
   }
   else
104
        png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
105
   
106

107
   if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
108
   {
109 110 111 112 113 114
     /* 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] ||
115
         (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
116 117
         (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
     {
118 119 120 121
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
        char msg[80];
        if (user_png_ver)
        {
122 123
          png_snprintf(msg, 80,
             "Application was compiled with png.h from libpng-%.20s",
124 125 126
             user_png_ver);
          png_warning(png_ptr, msg);
        }
127 128
        png_snprintf(msg, 80,
             "Application  is  running with png.c from libpng-%.20s",
129 130 131 132
           png_libpng_ver);
        png_warning(png_ptr, msg);
#endif
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
133
        png_ptr->flags = 0;
134
#endif
135 136 137
        png_error(png_ptr,
           "Incompatible libpng version in application and library");
     }
138 139
   }

G
Guy Schalnat 已提交
140 141
   /* initialize zbuf - compression buffer */
   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
142 143
   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
     (png_uint_32)png_ptr->zbuf_size);
A
Andreas Dilger 已提交
144 145 146
   png_ptr->zstream.zalloc = png_zalloc;
   png_ptr->zstream.zfree = png_zfree;
   png_ptr->zstream.opaque = (voidpf)png_ptr;
G
Guy Schalnat 已提交
147

A
Andreas Dilger 已提交
148
   switch (inflateInit(&png_ptr->zstream))
G
Guy Schalnat 已提交
149 150 151 152 153 154 155 156
   {
     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 已提交
157 158
   png_ptr->zstream.next_out = png_ptr->zbuf;
   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
159

160
   png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL);
G
Guy Schalnat 已提交
161

162 163 164 165 166 167 168
#ifdef PNG_SETJMP_SUPPORTED
/* Applications that neglect to set up their own setjmp() and then encounter
   a png_error() will longjmp here.  Since the jmpbuf is then meaningless we
   abort instead of returning. */
#ifdef USE_FAR_KEYWORD
   if (setjmp(jmpbuf))
      PNG_ABORT();
169
   png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf));
170 171 172 173 174
#else
   if (setjmp(png_ptr->jmpbuf))
      PNG_ABORT();
#endif
#endif
G
Guy Schalnat 已提交
175 176 177
   return (png_ptr);
}

178
#if defined(PNG_1_0_X) || defined(PNG_1_2_X)
A
Andreas Dilger 已提交
179
/* Initialize PNG structure for reading, and allocate any memory needed.
180
   This interface is deprecated in favour of the png_create_read_struct(),
181
   and it will disappear as of libpng-1.3.0. */
182
#undef png_read_init
183
void PNGAPI
G
Guy Schalnat 已提交
184
png_read_init(png_structp png_ptr)
185 186
{
   /* We only come here via pre-1.0.7-compiled applications */
187
   png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0);
188 189
}

190
void PNGAPI
191 192
png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver,
   png_size_t png_struct_size, png_size_t png_info_size)
193 194
{
   /* We only come here via pre-1.0.12-compiled applications */
195
   if (png_ptr == NULL) return;
196
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
197
   if (png_sizeof(png_struct) > png_struct_size ||
198
      png_sizeof(png_info) > png_info_size)
199 200
   {
      char msg[80];
201
      png_ptr->warning_fn = NULL;
202 203
      if (user_png_ver)
      {
204 205
        png_snprintf(msg, 80,
           "Application was compiled with png.h from libpng-%.20s",
206 207 208
           user_png_ver);
        png_warning(png_ptr, msg);
      }
209 210
      png_snprintf(msg, 80,
         "Application  is  running with png.c from libpng-%.20s",
211 212 213 214
         png_libpng_ver);
      png_warning(png_ptr, msg);
   }
#endif
215
   if (png_sizeof(png_struct) > png_struct_size)
216
     {
217
       png_ptr->error_fn = NULL;
218
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
219
       png_ptr->flags = 0;
220
#endif
221 222 223
       png_error(png_ptr,
       "The png struct allocated by the application for reading is too small.");
     }
224
   if (png_sizeof(png_info) > png_info_size)
225
     {
226
       png_ptr->error_fn = NULL;
227
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
228
       png_ptr->flags = 0;
229
#endif
230 231 232 233 234
       png_error(png_ptr,
         "The info struct allocated by application for reading is too small.");
     }
   png_read_init_3(&png_ptr, user_png_ver, png_struct_size);
}
235
#endif /* PNG_1_0_X || PNG_1_2_X */
236 237 238 239

void PNGAPI
png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver,
   png_size_t png_struct_size)
G
Guy Schalnat 已提交
240
{
241
#ifdef PNG_SETJMP_SUPPORTED
G
Guy Schalnat 已提交
242
   jmp_buf tmp_jmp;  /* to save current jump buffer */
243
#endif
G
Guy Schalnat 已提交
244

245
   int i = 0;
246 247 248

   png_structp png_ptr=*ptr_ptr;

249
   if (png_ptr == NULL) return;
250

251 252
   do
   {
253
     if (user_png_ver[i] != png_libpng_ver[i])
254
     {
255 256 257
#ifdef PNG_LEGACY_SUPPORTED
       png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
#else
258
       png_ptr->warning_fn = NULL;
259 260 261
       png_warning(png_ptr,
        "Application uses deprecated png_read_init() and should be recompiled.");
       break;
262
#endif
263 264 265
     }
   } while (png_libpng_ver[i++]);

266
   png_debug(1, "in png_read_init_3\n");
267 268

#ifdef PNG_SETJMP_SUPPORTED
G
Guy Schalnat 已提交
269
   /* save jump buffer and error functions */
270
   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
271
#endif
G
Guy Schalnat 已提交
272

273 274 275 276 277 278
   if (png_sizeof(png_struct) > png_struct_size)
   {
      png_destroy_struct(png_ptr);
      *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
      png_ptr = *ptr_ptr;
   }
279

G
Guy Schalnat 已提交
280
   /* reset all variables to 0 */
281
   png_memset(png_ptr, 0, png_sizeof(png_struct));
G
Guy Schalnat 已提交
282

283
#ifdef PNG_SETJMP_SUPPORTED
G
Guy Schalnat 已提交
284
   /* restore jump buffer */
285
   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
286
#endif
G
Guy Schalnat 已提交
287

288 289 290 291 292 293
   /* added at libpng-1.2.6 */
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
   png_ptr->user_width_max=PNG_USER_WIDTH_MAX;
   png_ptr->user_height_max=PNG_USER_HEIGHT_MAX;
#endif

G
Guy Schalnat 已提交
294
   /* initialize zbuf - compression buffer */
G
Guy Schalnat 已提交
295
   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
296 297
   png_ptr->zbuf = (png_bytep)png_malloc(png_ptr,
     (png_uint_32)png_ptr->zbuf_size);
A
Andreas Dilger 已提交
298 299 300
   png_ptr->zstream.zalloc = png_zalloc;
   png_ptr->zstream.zfree = png_zfree;
   png_ptr->zstream.opaque = (voidpf)png_ptr;
G
Guy Schalnat 已提交
301

A
Andreas Dilger 已提交
302
   switch (inflateInit(&png_ptr->zstream))
G
Guy Schalnat 已提交
303 304 305 306 307 308 309 310
   {
     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 已提交
311 312
   png_ptr->zstream.next_out = png_ptr->zbuf;
   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
313

314
   png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL);
G
Guy Schalnat 已提交
315 316
}

317
#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
A
Andreas Dilger 已提交
318
/* Read the information before the actual image data.  This has been
319
 * changed in v0.90 to allow reading a file that already has the magic
A
Andreas Dilger 已提交
320
 * bytes read from the stream.  You can tell libpng how many bytes have
321
 * been read from the beginning of the stream (up to the maximum of 8)
A
Andreas Dilger 已提交
322 323 324 325
 * 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.
 */
326
void PNGAPI
A
Andreas Dilger 已提交
327
png_read_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
328
{
329
   if (png_ptr == NULL || info_ptr == NULL) return;
A
Andreas Dilger 已提交
330
   png_debug(1, "in png_read_info\n");
A
Andreas Dilger 已提交
331 332
   /* If we haven't checked all of the PNG signature bytes, do so now. */
   if (png_ptr->sig_bytes < 8)
G
Guy Schalnat 已提交
333
   {
A
Andreas Dilger 已提交
334 335
      png_size_t num_checked = png_ptr->sig_bytes,
                 num_to_check = 8 - num_checked;
A
Andreas Dilger 已提交
336

A
Andreas Dilger 已提交
337
      png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
A
Andreas Dilger 已提交
338 339 340 341 342 343 344 345 346 347
      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");
      }
348 349
      if (num_checked < 3)
         png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
G
Guy Schalnat 已提交
350
   }
G
Guy Schalnat 已提交
351

352
   for (;;)
G
Guy Schalnat 已提交
353
   {
354
#ifdef PNG_USE_LOCAL_ARRAYS
355 356 357 358
      PNG_CONST PNG_IHDR;
      PNG_CONST PNG_IDAT;
      PNG_CONST PNG_IEND;
      PNG_CONST PNG_PLTE;
359
#if defined(PNG_READ_bKGD_SUPPORTED)
360
      PNG_CONST PNG_bKGD;
361 362
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
363
      PNG_CONST PNG_cHRM;
364 365
#endif
#if defined(PNG_READ_gAMA_SUPPORTED)
366
      PNG_CONST PNG_gAMA;
367 368
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
369
      PNG_CONST PNG_hIST;
370
#endif
371
#if defined(PNG_READ_iCCP_SUPPORTED)
372
      PNG_CONST PNG_iCCP;
373 374
#endif
#if defined(PNG_READ_iTXt_SUPPORTED)
375
      PNG_CONST PNG_iTXt;
376
#endif
377
#if defined(PNG_READ_oFFs_SUPPORTED)
378
      PNG_CONST PNG_oFFs;
379 380
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
381
      PNG_CONST PNG_pCAL;
382 383
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
384
      PNG_CONST PNG_pHYs;
385 386
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
387
      PNG_CONST PNG_sBIT;
388
#endif
389
#if defined(PNG_READ_sCAL_SUPPORTED)
390
      PNG_CONST PNG_sCAL;
391 392
#endif
#if defined(PNG_READ_sPLT_SUPPORTED)
393
      PNG_CONST PNG_sPLT;
394
#endif
395
#if defined(PNG_READ_sRGB_SUPPORTED)
396
      PNG_CONST PNG_sRGB;
397 398
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
399
      PNG_CONST PNG_tEXt;
400 401
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
402
      PNG_CONST PNG_tIME;
403 404
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
405
      PNG_CONST PNG_tRNS;
406 407
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
408
      PNG_CONST PNG_zTXt;
409
#endif
410
#endif /* PNG_USE_LOCAL_ARRAYS */
411
      png_uint_32 length = png_read_chunk_header(png_ptr);
412
      PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;
A
Andreas Dilger 已提交
413

A
Andreas Dilger 已提交
414 415 416
      /* This should be a binary subdivision search or a hash for
       * matching the chunk name rather than a linear search.
       */
417
      if (!png_memcmp(chunk_name, png_IDAT, 4))
418
        if (png_ptr->mode & PNG_AFTER_IDAT)
419 420
          png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;

421
      if (!png_memcmp(chunk_name, png_IHDR, 4))
A
Andreas Dilger 已提交
422
         png_handle_IHDR(png_ptr, info_ptr, length);
423
      else if (!png_memcmp(chunk_name, png_IEND, 4))
A
Andreas Dilger 已提交
424
         png_handle_IEND(png_ptr, info_ptr, length);
425
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
426
      else if (png_handle_as_unknown(png_ptr, chunk_name))
427
      {
428
         if (!png_memcmp(chunk_name, png_IDAT, 4))
429 430
            png_ptr->mode |= PNG_HAVE_IDAT;
         png_handle_unknown(png_ptr, info_ptr, length);
431
         if (!png_memcmp(chunk_name, png_PLTE, 4))
432
            png_ptr->mode |= PNG_HAVE_PLTE;
433
         else if (!png_memcmp(chunk_name, png_IDAT, 4))
434 435 436 437 438 439 440 441 442 443
         {
            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");
            break;
         }
      }
#endif
444
      else if (!png_memcmp(chunk_name, png_PLTE, 4))
445
         png_handle_PLTE(png_ptr, info_ptr, length);
446
      else if (!png_memcmp(chunk_name, png_IDAT, 4))
A
Andreas Dilger 已提交
447 448 449 450 451 452 453 454 455 456 457 458
      {
         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)
459
      else if (!png_memcmp(chunk_name, png_bKGD, 4))
A
Andreas Dilger 已提交
460
         png_handle_bKGD(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
461 462
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
463
      else if (!png_memcmp(chunk_name, png_cHRM, 4))
A
Andreas Dilger 已提交
464
         png_handle_cHRM(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
465
#endif
A
Andreas Dilger 已提交
466
#if defined(PNG_READ_gAMA_SUPPORTED)
467
      else if (!png_memcmp(chunk_name, png_gAMA, 4))
A
Andreas Dilger 已提交
468
         png_handle_gAMA(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
469 470
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
471
      else if (!png_memcmp(chunk_name, png_hIST, 4))
A
Andreas Dilger 已提交
472
         png_handle_hIST(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
473
#endif
A
Andreas Dilger 已提交
474
#if defined(PNG_READ_oFFs_SUPPORTED)
475
      else if (!png_memcmp(chunk_name, png_oFFs, 4))
A
Andreas Dilger 已提交
476 477 478
         png_handle_oFFs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
479
      else if (!png_memcmp(chunk_name, png_pCAL, 4))
A
Andreas Dilger 已提交
480 481
         png_handle_pCAL(png_ptr, info_ptr, length);
#endif
482
#if defined(PNG_READ_sCAL_SUPPORTED)
483
      else if (!png_memcmp(chunk_name, png_sCAL, 4))
484 485
         png_handle_sCAL(png_ptr, info_ptr, length);
#endif
G
Guy Schalnat 已提交
486
#if defined(PNG_READ_pHYs_SUPPORTED)
487
      else if (!png_memcmp(chunk_name, png_pHYs, 4))
A
Andreas Dilger 已提交
488
         png_handle_pHYs(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
489
#endif
A
Andreas Dilger 已提交
490
#if defined(PNG_READ_sBIT_SUPPORTED)
491
      else if (!png_memcmp(chunk_name, png_sBIT, 4))
A
Andreas Dilger 已提交
492 493
         png_handle_sBIT(png_ptr, info_ptr, length);
#endif
494
#if defined(PNG_READ_sRGB_SUPPORTED)
495
      else if (!png_memcmp(chunk_name, png_sRGB, 4))
496 497
         png_handle_sRGB(png_ptr, info_ptr, length);
#endif
498
#if defined(PNG_READ_iCCP_SUPPORTED)
499
      else if (!png_memcmp(chunk_name, png_iCCP, 4))
500 501 502
         png_handle_iCCP(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_sPLT_SUPPORTED)
503
      else if (!png_memcmp(chunk_name, png_sPLT, 4))
504 505
         png_handle_sPLT(png_ptr, info_ptr, length);
#endif
A
Andreas Dilger 已提交
506
#if defined(PNG_READ_tEXt_SUPPORTED)
507
      else if (!png_memcmp(chunk_name, png_tEXt, 4))
A
Andreas Dilger 已提交
508
         png_handle_tEXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
509 510
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
511
      else if (!png_memcmp(chunk_name, png_tIME, 4))
A
Andreas Dilger 已提交
512
         png_handle_tIME(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
513
#endif
A
Andreas Dilger 已提交
514
#if defined(PNG_READ_tRNS_SUPPORTED)
515
      else if (!png_memcmp(chunk_name, png_tRNS, 4))
A
Andreas Dilger 已提交
516
         png_handle_tRNS(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
517 518
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
519
      else if (!png_memcmp(chunk_name, png_zTXt, 4))
A
Andreas Dilger 已提交
520
         png_handle_zTXt(png_ptr, info_ptr, length);
521 522
#endif
#if defined(PNG_READ_iTXt_SUPPORTED)
523
      else if (!png_memcmp(chunk_name, png_iTXt, 4))
524
         png_handle_iTXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
525
#endif
A
Andreas Dilger 已提交
526 527
      else
         png_handle_unknown(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
528 529
   }
}
530
#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
531

A
Andreas Dilger 已提交
532
/* optional call to update the users info_ptr structure */
533
void PNGAPI
A
Andreas Dilger 已提交
534
png_read_update_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
535
{
A
Andreas Dilger 已提交
536
   png_debug(1, "in png_read_update_info\n");
537
   if (png_ptr == NULL) return;
G
Guy Schalnat 已提交
538
   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
G
Guy Schalnat 已提交
539
      png_read_start_row(png_ptr);
540 541 542
   else
      png_warning(png_ptr,
      "Ignoring extra png_read_update_info() call; row buffer not reallocated");
A
Andreas Dilger 已提交
543
   png_read_transform_info(png_ptr, info_ptr);
G
Guy Schalnat 已提交
544 545
}

546
#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
547 548
/* Initialize palette, background, etc, after transformations
 * are set, but before any reading takes place.  This allows
549
 * the user to obtain a gamma-corrected palette, for example.
550 551
 * If the user doesn't call this, we will do it ourselves.
 */
552
void PNGAPI
G
Guy Schalnat 已提交
553
png_start_read_image(png_structp png_ptr)
G
Guy Schalnat 已提交
554
{
A
Andreas Dilger 已提交
555
   png_debug(1, "in png_start_read_image\n");
556
   if (png_ptr == NULL) return;
G
Guy Schalnat 已提交
557
   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
G
Guy Schalnat 已提交
558
      png_read_start_row(png_ptr);
G
Guy Schalnat 已提交
559
}
560
#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
561

562
#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
563
void PNGAPI
G
Guy Schalnat 已提交
564
png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
G
Guy Schalnat 已提交
565
{
566
#ifdef PNG_USE_LOCAL_ARRAYS
567
   PNG_CONST PNG_IDAT;
568
   PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55,
569
      0xff};
570
   PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff};
571
#endif
G
Guy Schalnat 已提交
572
   int ret;
573
   if (png_ptr == NULL) return;
574
   png_debug2(1, "in png_read_row (row %lu, pass %d)\n",
A
Andreas Dilger 已提交
575
      png_ptr->row_number, png_ptr->pass);
G
Guy Schalnat 已提交
576
   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
G
Guy Schalnat 已提交
577
      png_read_start_row(png_ptr);
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609
   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 已提交
610

G
Guy Schalnat 已提交
611
#if defined(PNG_READ_INTERLACING_SUPPORTED)
G
Guy Schalnat 已提交
612 613 614 615 616 617
   /* 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:
618
            if (png_ptr->row_number & 0x07)
G
Guy Schalnat 已提交
619
            {
A
Andreas Dilger 已提交
620
               if (dsp_row != NULL)
G
Guy Schalnat 已提交
621 622
                  png_combine_row(png_ptr, dsp_row,
                     png_pass_dsp_mask[png_ptr->pass]);
G
Guy Schalnat 已提交
623
               png_read_finish_row(png_ptr);
G
Guy Schalnat 已提交
624 625 626 627
               return;
            }
            break;
         case 1:
628
            if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
G
Guy Schalnat 已提交
629
            {
A
Andreas Dilger 已提交
630
               if (dsp_row != NULL)
G
Guy Schalnat 已提交
631 632 633 634 635 636 637
                  png_combine_row(png_ptr, dsp_row,
                     png_pass_dsp_mask[png_ptr->pass]);
               png_read_finish_row(png_ptr);
               return;
            }
            break;
         case 2:
638
            if ((png_ptr->row_number & 0x07) != 4)
G
Guy Schalnat 已提交
639
            {
A
Andreas Dilger 已提交
640
               if (dsp_row != NULL && (png_ptr->row_number & 4))
G
Guy Schalnat 已提交
641
                  png_combine_row(png_ptr, dsp_row,
G
Guy Schalnat 已提交
642 643 644 645 646 647 648 649
                     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 已提交
650
               if (dsp_row != NULL)
G
Guy Schalnat 已提交
651 652 653 654 655 656 657 658
                  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 已提交
659
            {
A
Andreas Dilger 已提交
660
               if (dsp_row != NULL && (png_ptr->row_number & 2))
G
Guy Schalnat 已提交
661 662 663 664 665 666 667 668 669
                  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 已提交
670
               if (dsp_row != NULL)
G
Guy Schalnat 已提交
671 672 673 674 675 676
                  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 已提交
677
         case 6:
G
Guy Schalnat 已提交
678 679 680 681 682 683 684 685
            if (!(png_ptr->row_number & 1))
            {
               png_read_finish_row(png_ptr);
               return;
            }
            break;
      }
   }
G
Guy Schalnat 已提交
686
#endif
G
Guy Schalnat 已提交
687

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

A
Andreas Dilger 已提交
691 692
   png_ptr->zstream.next_out = png_ptr->row_buf;
   png_ptr->zstream.avail_out = (uInt)png_ptr->irowbytes;
G
Guy Schalnat 已提交
693 694
   do
   {
A
Andreas Dilger 已提交
695
      if (!(png_ptr->zstream.avail_in))
G
Guy Schalnat 已提交
696 697 698
      {
         while (!png_ptr->idat_size)
         {
A
Andreas Dilger 已提交
699
            png_crc_finish(png_ptr, 0);
G
Guy Schalnat 已提交
700

701
            png_ptr->idat_size = png_read_chunk_header(png_ptr);
A
Andreas Dilger 已提交
702 703
            if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4))
               png_error(png_ptr, "Not enough image data");
G
Guy Schalnat 已提交
704
         }
A
Andreas Dilger 已提交
705 706
         png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
         png_ptr->zstream.next_in = png_ptr->zbuf;
G
Guy Schalnat 已提交
707
         if (png_ptr->zbuf_size > png_ptr->idat_size)
A
Andreas Dilger 已提交
708
            png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
A
Andreas Dilger 已提交
709 710
         png_crc_read(png_ptr, png_ptr->zbuf,
            (png_size_t)png_ptr->zstream.avail_in);
A
Andreas Dilger 已提交
711
         png_ptr->idat_size -= png_ptr->zstream.avail_in;
G
Guy Schalnat 已提交
712
      }
A
Andreas Dilger 已提交
713
      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
G
Guy Schalnat 已提交
714 715
      if (ret == Z_STREAM_END)
      {
A
Andreas Dilger 已提交
716
         if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
G
Guy Schalnat 已提交
717
            png_ptr->idat_size)
G
Guy Schalnat 已提交
718
            png_error(png_ptr, "Extra compressed data");
A
Andreas Dilger 已提交
719
         png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
720
         png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
G
Guy Schalnat 已提交
721
         break;
G
Guy Schalnat 已提交
722 723
      }
      if (ret != Z_OK)
A
Andreas Dilger 已提交
724
         png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
G
Guy Schalnat 已提交
725
                   "Decompression error");
A
Andreas Dilger 已提交
726 727

   } while (png_ptr->zstream.avail_out);
G
Guy Schalnat 已提交
728 729 730 731 732 733

   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;
734 735
   png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth,
       png_ptr->row_info.width);
G
Guy Schalnat 已提交
736

737
   if (png_ptr->row_buf[0])
G
Guy Schalnat 已提交
738 739 740
   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 已提交
741

742
   png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf,
743
      png_ptr->rowbytes + 1);
744

745
#if defined(PNG_MNG_FEATURES_SUPPORTED)
746
   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
747 748 749 750 751 752
      (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
   {
      /* Intrapixel differencing */
      png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1);
   }
#endif
G
Guy Schalnat 已提交
753

754 755

   if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA))
G
Guy Schalnat 已提交
756 757
      png_do_read_transformations(png_ptr);

G
Guy Schalnat 已提交
758
#if defined(PNG_READ_INTERLACING_SUPPORTED)
G
Guy Schalnat 已提交
759 760 761 762 763
   /* blow up interlaced rows to full size */
   if (png_ptr->interlaced &&
      (png_ptr->transformations & PNG_INTERLACE))
   {
      if (png_ptr->pass < 6)
764
/*       old interface (pre-1.0.9):
G
Guy Schalnat 已提交
765
         png_do_read_interlace(&(png_ptr->row_info),
A
Andreas Dilger 已提交
766
            png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations);
767 768
 */
         png_do_read_interlace(png_ptr);
G
Guy Schalnat 已提交
769

A
Andreas Dilger 已提交
770
      if (dsp_row != NULL)
G
Guy Schalnat 已提交
771 772
         png_combine_row(png_ptr, dsp_row,
            png_pass_dsp_mask[png_ptr->pass]);
A
Andreas Dilger 已提交
773
      if (row != NULL)
G
Guy Schalnat 已提交
774 775 776 777
         png_combine_row(png_ptr, row,
            png_pass_mask[png_ptr->pass]);
   }
   else
G
Guy Schalnat 已提交
778
#endif
G
Guy Schalnat 已提交
779
   {
A
Andreas Dilger 已提交
780
      if (row != NULL)
G
Guy Schalnat 已提交
781
         png_combine_row(png_ptr, row, 0xff);
A
Andreas Dilger 已提交
782
      if (dsp_row != NULL)
G
Guy Schalnat 已提交
783 784 785
         png_combine_row(png_ptr, dsp_row, 0xff);
   }
   png_read_finish_row(png_ptr);
786 787 788

   if (png_ptr->read_row_fn != NULL)
      (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
G
Guy Schalnat 已提交
789
}
790
#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
791

792
#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
A
Andreas Dilger 已提交
793
/* Read one or more rows of image data.  If the image is interlaced,
794 795
 * and png_set_interlace_handling() has been called, the rows need to
 * contain the contents of the rows from the previous pass.  If the
796
 * image has alpha or transparency, and png_handle_alpha()[*] has been
797 798
 * called, the rows contents must be initialized to the contents of the
 * screen.
799
 *
800 801 802 803 804 805 806 807 808 809 810 811 812
 * "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.
813
 *
814
 * [*] png_handle_alpha() does not exist yet, as of this version of libpng
815
 */
G
Guy Schalnat 已提交
816

817
void PNGAPI
G
Guy Schalnat 已提交
818
png_read_rows(png_structp png_ptr, png_bytepp row,
G
Guy Schalnat 已提交
819
   png_bytepp display_row, png_uint_32 num_rows)
G
Guy Schalnat 已提交
820
{
G
Guy Schalnat 已提交
821 822 823
   png_uint_32 i;
   png_bytepp rp;
   png_bytepp dp;
G
Guy Schalnat 已提交
824

A
Andreas Dilger 已提交
825
   png_debug(1, "in png_read_rows\n");
826
   if (png_ptr == NULL) return;
G
Guy Schalnat 已提交
827 828
   rp = row;
   dp = display_row;
829
   if (rp != NULL && dp != NULL)
830 831 832 833
      for (i = 0; i < num_rows; i++)
      {
         png_bytep rptr = *rp++;
         png_bytep dptr = *dp++;
834

835 836
         png_read_row(png_ptr, rptr, dptr);
      }
837
   else if (rp != NULL)
838 839
      for (i = 0; i < num_rows; i++)
      {
840
         png_bytep rptr = *rp;
841
         png_read_row(png_ptr, rptr, png_bytep_NULL);
842 843
         rp++;
      }
844
   else if (dp != NULL)
845 846 847
      for (i = 0; i < num_rows; i++)
      {
         png_bytep dptr = *dp;
848
         png_read_row(png_ptr, png_bytep_NULL, dptr);
849
         dp++;
850
      }
G
Guy Schalnat 已提交
851
}
852
#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
853

854
#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
A
Andreas Dilger 已提交
855
/* Read the entire image.  If the image has an alpha channel or a tRNS
856
 * chunk, and you have called png_handle_alpha()[*], you will need to
857 858 859 860 861 862 863
 * 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.
864
 *
865
 * [*] png_handle_alpha() does not exist yet, as of this version of libpng
866
 */
867
void PNGAPI
G
Guy Schalnat 已提交
868
png_read_image(png_structp png_ptr, png_bytepp image)
G
Guy Schalnat 已提交
869
{
870
   png_uint_32 i, image_height;
G
Guy Schalnat 已提交
871
   int pass, j;
G
Guy Schalnat 已提交
872
   png_bytepp rp;
G
Guy Schalnat 已提交
873

A
Andreas Dilger 已提交
874
   png_debug(1, "in png_read_image\n");
875
   if (png_ptr == NULL) return;
876 877

#ifdef PNG_READ_INTERLACING_SUPPORTED
G
Guy Schalnat 已提交
878
   pass = png_set_interlace_handling(png_ptr);
879 880 881 882 883 884 885
#else
   if (png_ptr->interlaced)
      png_error(png_ptr,
        "Cannot read interlaced image -- interlace handler disabled.");
   pass = 1;
#endif

G
Guy Schalnat 已提交
886

887 888
   image_height=png_ptr->height;
   png_ptr->num_rows = image_height; /* Make sure this is set correctly */
G
Guy Schalnat 已提交
889

G
Guy Schalnat 已提交
890 891 892
   for (j = 0; j < pass; j++)
   {
      rp = image;
893
      for (i = 0; i < image_height; i++)
G
Guy Schalnat 已提交
894
      {
895
         png_read_row(png_ptr, *rp, png_bytep_NULL);
G
Guy Schalnat 已提交
896 897 898 899
         rp++;
      }
   }
}
900
#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
901

902
#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
A
Andreas Dilger 已提交
903
/* Read the end of the PNG file.  Will not read past the end of the
904 905 906
 * 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.
 */
907
void PNGAPI
A
Andreas Dilger 已提交
908
png_read_end(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
909
{
A
Andreas Dilger 已提交
910
   png_debug(1, "in png_read_end\n");
911
   if (png_ptr == NULL) return;
A
Andreas Dilger 已提交
912
   png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
G
Guy Schalnat 已提交
913 914 915

   do
   {
916
#ifdef PNG_USE_LOCAL_ARRAYS
917 918 919 920
      PNG_CONST PNG_IHDR;
      PNG_CONST PNG_IDAT;
      PNG_CONST PNG_IEND;
      PNG_CONST PNG_PLTE;
921
#if defined(PNG_READ_bKGD_SUPPORTED)
922
      PNG_CONST PNG_bKGD;
923 924
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
925
      PNG_CONST PNG_cHRM;
926 927
#endif
#if defined(PNG_READ_gAMA_SUPPORTED)
928
      PNG_CONST PNG_gAMA;
929 930
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
931
      PNG_CONST PNG_hIST;
932
#endif
933
#if defined(PNG_READ_iCCP_SUPPORTED)
934
      PNG_CONST PNG_iCCP;
935 936
#endif
#if defined(PNG_READ_iTXt_SUPPORTED)
937
      PNG_CONST PNG_iTXt;
938
#endif
939
#if defined(PNG_READ_oFFs_SUPPORTED)
940
      PNG_CONST PNG_oFFs;
941 942
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
943
      PNG_CONST PNG_pCAL;
944 945
#endif
#if defined(PNG_READ_pHYs_SUPPORTED)
946
      PNG_CONST PNG_pHYs;
947 948
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
949
      PNG_CONST PNG_sBIT;
950
#endif
951
#if defined(PNG_READ_sCAL_SUPPORTED)
952
      PNG_CONST PNG_sCAL;
953 954
#endif
#if defined(PNG_READ_sPLT_SUPPORTED)
955
      PNG_CONST PNG_sPLT;
956
#endif
957
#if defined(PNG_READ_sRGB_SUPPORTED)
958
      PNG_CONST PNG_sRGB;
959 960
#endif
#if defined(PNG_READ_tEXt_SUPPORTED)
961
      PNG_CONST PNG_tEXt;
962 963
#endif
#if defined(PNG_READ_tIME_SUPPORTED)
964
      PNG_CONST PNG_tIME;
965 966
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
967
      PNG_CONST PNG_tRNS;
968 969
#endif
#if defined(PNG_READ_zTXt_SUPPORTED)
970
      PNG_CONST PNG_zTXt;
971
#endif
972
#endif /* PNG_USE_LOCAL_ARRAYS */
973 974
      png_uint_32 length = png_read_chunk_header(png_ptr);
      PNG_CONST png_bytep chunk_name = png_ptr->chunk_name;
A
Andreas Dilger 已提交
975

976
      if (!png_memcmp(chunk_name, png_IHDR, 4))
A
Andreas Dilger 已提交
977
         png_handle_IHDR(png_ptr, info_ptr, length);
978
      else if (!png_memcmp(chunk_name, png_IEND, 4))
979 980
         png_handle_IEND(png_ptr, info_ptr, length);
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
981
      else if (png_handle_as_unknown(png_ptr, chunk_name))
982
      {
983
         if (!png_memcmp(chunk_name, png_IDAT, 4))
984
         {
985
            if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
986 987 988
               png_error(png_ptr, "Too many IDAT's found");
         }
         png_handle_unknown(png_ptr, info_ptr, length);
989
         if (!png_memcmp(chunk_name, png_PLTE, 4))
990 991 992
            png_ptr->mode |= PNG_HAVE_PLTE;
      }
#endif
993
      else if (!png_memcmp(chunk_name, png_IDAT, 4))
A
Andreas Dilger 已提交
994 995 996 997
      {
         /* Zero length IDATs are legal after the last IDAT has been
          * read, but not after other chunks have been read.
          */
998
         if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
A
Andreas Dilger 已提交
999
            png_error(png_ptr, "Too many IDAT's found");
1000
         png_crc_finish(png_ptr, length);
A
Andreas Dilger 已提交
1001
      }
1002
      else if (!png_memcmp(chunk_name, png_PLTE, 4))
A
Andreas Dilger 已提交
1003
         png_handle_PLTE(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
1004
#if defined(PNG_READ_bKGD_SUPPORTED)
1005
      else if (!png_memcmp(chunk_name, png_bKGD, 4))
A
Andreas Dilger 已提交
1006
         png_handle_bKGD(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
1007 1008
#endif
#if defined(PNG_READ_cHRM_SUPPORTED)
1009
      else if (!png_memcmp(chunk_name, png_cHRM, 4))
A
Andreas Dilger 已提交
1010 1011 1012
         png_handle_cHRM(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_gAMA_SUPPORTED)
1013
      else if (!png_memcmp(chunk_name, png_gAMA, 4))
A
Andreas Dilger 已提交
1014 1015 1016
         png_handle_gAMA(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_hIST_SUPPORTED)
1017
      else if (!png_memcmp(chunk_name, png_hIST, 4))
A
Andreas Dilger 已提交
1018
         png_handle_hIST(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
1019 1020
#endif
#if defined(PNG_READ_oFFs_SUPPORTED)
1021
      else if (!png_memcmp(chunk_name, png_oFFs, 4))
A
Andreas Dilger 已提交
1022
         png_handle_oFFs(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
1023 1024
#endif
#if defined(PNG_READ_pCAL_SUPPORTED)
1025
      else if (!png_memcmp(chunk_name, png_pCAL, 4))
A
Andreas Dilger 已提交
1026 1027
         png_handle_pCAL(png_ptr, info_ptr, length);
#endif
1028
#if defined(PNG_READ_sCAL_SUPPORTED)
1029
      else if (!png_memcmp(chunk_name, png_sCAL, 4))
1030 1031
         png_handle_sCAL(png_ptr, info_ptr, length);
#endif
A
Andreas Dilger 已提交
1032
#if defined(PNG_READ_pHYs_SUPPORTED)
1033
      else if (!png_memcmp(chunk_name, png_pHYs, 4))
A
Andreas Dilger 已提交
1034 1035 1036
         png_handle_pHYs(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_sBIT_SUPPORTED)
1037
      else if (!png_memcmp(chunk_name, png_sBIT, 4))
A
Andreas Dilger 已提交
1038
         png_handle_sBIT(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
1039
#endif
1040
#if defined(PNG_READ_sRGB_SUPPORTED)
1041
      else if (!png_memcmp(chunk_name, png_sRGB, 4))
1042 1043
         png_handle_sRGB(png_ptr, info_ptr, length);
#endif
1044
#if defined(PNG_READ_iCCP_SUPPORTED)
1045
      else if (!png_memcmp(chunk_name, png_iCCP, 4))
1046 1047 1048
         png_handle_iCCP(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_sPLT_SUPPORTED)
1049
      else if (!png_memcmp(chunk_name, png_sPLT, 4))
1050 1051
         png_handle_sPLT(png_ptr, info_ptr, length);
#endif
G
Guy Schalnat 已提交
1052
#if defined(PNG_READ_tEXt_SUPPORTED)
1053
      else if (!png_memcmp(chunk_name, png_tEXt, 4))
A
Andreas Dilger 已提交
1054
         png_handle_tEXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
1055
#endif
A
Andreas Dilger 已提交
1056
#if defined(PNG_READ_tIME_SUPPORTED)
1057
      else if (!png_memcmp(chunk_name, png_tIME, 4))
A
Andreas Dilger 已提交
1058 1059 1060
         png_handle_tIME(png_ptr, info_ptr, length);
#endif
#if defined(PNG_READ_tRNS_SUPPORTED)
1061
      else if (!png_memcmp(chunk_name, png_tRNS, 4))
A
Andreas Dilger 已提交
1062 1063
         png_handle_tRNS(png_ptr, info_ptr, length);
#endif
G
Guy Schalnat 已提交
1064
#if defined(PNG_READ_zTXt_SUPPORTED)
1065
      else if (!png_memcmp(chunk_name, png_zTXt, 4))
A
Andreas Dilger 已提交
1066
         png_handle_zTXt(png_ptr, info_ptr, length);
1067 1068
#endif
#if defined(PNG_READ_iTXt_SUPPORTED)
1069
      else if (!png_memcmp(chunk_name, png_iTXt, 4))
1070
         png_handle_iTXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
1071
#endif
G
Guy Schalnat 已提交
1072
      else
A
Andreas Dilger 已提交
1073 1074
         png_handle_unknown(png_ptr, info_ptr, length);
   } while (!(png_ptr->mode & PNG_HAVE_IEND));
G
Guy Schalnat 已提交
1075
}
1076
#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
1077 1078

/* free all memory used by the read */
1079
void PNGAPI
G
Guy Schalnat 已提交
1080
png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
A
Andreas Dilger 已提交
1081
   png_infopp end_info_ptr_ptr)
G
Guy Schalnat 已提交
1082 1083
{
   png_structp png_ptr = NULL;
A
Andreas Dilger 已提交
1084
   png_infop info_ptr = NULL, end_info_ptr = NULL;
1085
#ifdef PNG_USER_MEM_SUPPORTED
1086 1087
   png_free_ptr free_fn = NULL;
   png_voidp mem_ptr = NULL;
1088
#endif
G
Guy Schalnat 已提交
1089

A
Andreas Dilger 已提交
1090 1091
   png_debug(1, "in png_destroy_read_struct\n");
   if (png_ptr_ptr != NULL)
G
Guy Schalnat 已提交
1092
      png_ptr = *png_ptr_ptr;
1093
   if (png_ptr == NULL)
1094
      return;
G
Guy Schalnat 已提交
1095

1096 1097 1098 1099 1100
#ifdef PNG_USER_MEM_SUPPORTED
   free_fn = png_ptr->free_fn;
   mem_ptr = png_ptr->mem_ptr;
#endif

A
Andreas Dilger 已提交
1101
   if (info_ptr_ptr != NULL)
G
Guy Schalnat 已提交
1102 1103
      info_ptr = *info_ptr_ptr;

A
Andreas Dilger 已提交
1104
   if (end_info_ptr_ptr != NULL)
A
Andreas Dilger 已提交
1105
      end_info_ptr = *end_info_ptr_ptr;
G
Guy Schalnat 已提交
1106

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

A
Andreas Dilger 已提交
1109
   if (info_ptr != NULL)
G
Guy Schalnat 已提交
1110
   {
1111
#if defined(PNG_TEXT_SUPPORTED)
1112
      png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);
1113
#endif
1114 1115

#ifdef PNG_USER_MEM_SUPPORTED
1116 1117
      png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
          (png_voidp)mem_ptr);
1118
#else
A
Andreas Dilger 已提交
1119
      png_destroy_struct((png_voidp)info_ptr);
1120
#endif
1121
      *info_ptr_ptr = NULL;
G
Guy Schalnat 已提交
1122 1123
   }

A
Andreas Dilger 已提交
1124
   if (end_info_ptr != NULL)
G
Guy Schalnat 已提交
1125
   {
1126
#if defined(PNG_READ_TEXT_SUPPORTED)
1127
      png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);
1128
#endif
1129
#ifdef PNG_USER_MEM_SUPPORTED
1130 1131
      png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn,
         (png_voidp)mem_ptr);
1132
#else
A
Andreas Dilger 已提交
1133
      png_destroy_struct((png_voidp)end_info_ptr);
1134
#endif
1135
      *end_info_ptr_ptr = NULL;
G
Guy Schalnat 已提交
1136 1137
   }

1138 1139
   if (png_ptr != NULL)
   {
1140
#ifdef PNG_USER_MEM_SUPPORTED
1141 1142
      png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
          (png_voidp)mem_ptr);
1143
#else
1144
      png_destroy_struct((png_voidp)png_ptr);
1145
#endif
1146 1147
      *png_ptr_ptr = NULL;
   }
G
Guy Schalnat 已提交
1148 1149
}

A
Andreas Dilger 已提交
1150
/* free all memory used by the read (old method) */
1151
void /* PRIVATE */
A
Andreas Dilger 已提交
1152
png_read_destroy(png_structp png_ptr, png_infop info_ptr, png_infop end_info_ptr)
G
Guy Schalnat 已提交
1153
{
1154
#ifdef PNG_SETJMP_SUPPORTED
G
Guy Schalnat 已提交
1155
   jmp_buf tmp_jmp;
1156
#endif
G
Guy Schalnat 已提交
1157 1158 1159
   png_error_ptr error_fn;
   png_error_ptr warning_fn;
   png_voidp error_ptr;
1160 1161 1162
#ifdef PNG_USER_MEM_SUPPORTED
   png_free_ptr free_fn;
#endif
G
Guy Schalnat 已提交
1163

A
Andreas Dilger 已提交
1164 1165
   png_debug(1, "in png_read_destroy\n");
   if (info_ptr != NULL)
A
Andreas Dilger 已提交
1166
      png_info_destroy(png_ptr, info_ptr);
G
Guy Schalnat 已提交
1167

A
Andreas Dilger 已提交
1168
   if (end_info_ptr != NULL)
A
Andreas Dilger 已提交
1169
      png_info_destroy(png_ptr, end_info_ptr);
G
Guy Schalnat 已提交
1170

A
Andreas Dilger 已提交
1171
   png_free(png_ptr, png_ptr->zbuf);
1172
   png_free(png_ptr, png_ptr->big_row_buf);
A
Andreas Dilger 已提交
1173
   png_free(png_ptr, png_ptr->prev_row);
1174
   png_free(png_ptr, png_ptr->chunkdata);
G
Guy Schalnat 已提交
1175
#if defined(PNG_READ_DITHER_SUPPORTED)
A
Andreas Dilger 已提交
1176 1177
   png_free(png_ptr, png_ptr->palette_lookup);
   png_free(png_ptr, png_ptr->dither_index);
G
Guy Schalnat 已提交
1178 1179
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
1180
   png_free(png_ptr, png_ptr->gamma_table);
G
Guy Schalnat 已提交
1181 1182
#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
A
Andreas Dilger 已提交
1183 1184
   png_free(png_ptr, png_ptr->gamma_from_1);
   png_free(png_ptr, png_ptr->gamma_to_1);
G
Guy Schalnat 已提交
1185
#endif
1186
#ifdef PNG_FREE_ME_SUPPORTED
1187
   if (png_ptr->free_me & PNG_FREE_PLTE)
1188
      png_zfree(png_ptr, png_ptr->palette);
1189
   png_ptr->free_me &= ~PNG_FREE_PLTE;
1190 1191 1192 1193 1194
#else
   if (png_ptr->flags & PNG_FLAG_FREE_PLTE)
      png_zfree(png_ptr, png_ptr->palette);
   png_ptr->flags &= ~PNG_FLAG_FREE_PLTE;
#endif
1195
#if defined(PNG_tRNS_SUPPORTED) || \
1196
    defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
1197
#ifdef PNG_FREE_ME_SUPPORTED
1198
   if (png_ptr->free_me & PNG_FREE_TRNS)
A
Andreas Dilger 已提交
1199
      png_free(png_ptr, png_ptr->trans);
1200
   png_ptr->free_me &= ~PNG_FREE_TRNS;
1201 1202 1203 1204 1205
#else
   if (png_ptr->flags & PNG_FLAG_FREE_TRNS)
      png_free(png_ptr, png_ptr->trans);
   png_ptr->flags &= ~PNG_FLAG_FREE_TRNS;
#endif
1206
#endif
G
Guy Schalnat 已提交
1207
#if defined(PNG_READ_hIST_SUPPORTED)
1208
#ifdef PNG_FREE_ME_SUPPORTED
1209
   if (png_ptr->free_me & PNG_FREE_HIST)
A
Andreas Dilger 已提交
1210
      png_free(png_ptr, png_ptr->hist);
1211
   png_ptr->free_me &= ~PNG_FREE_HIST;
1212 1213 1214 1215 1216
#else
   if (png_ptr->flags & PNG_FLAG_FREE_HIST)
      png_free(png_ptr, png_ptr->hist);
   png_ptr->flags &= ~PNG_FLAG_FREE_HIST;
#endif
G
Guy Schalnat 已提交
1217 1218
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED)
A
Andreas Dilger 已提交
1219
   if (png_ptr->gamma_16_table != NULL)
G
Guy Schalnat 已提交
1220
   {
1221 1222
      int i;
      int istop = (1 << (8 - png_ptr->gamma_shift));
1223
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1224
      {
A
Andreas Dilger 已提交
1225
         png_free(png_ptr, png_ptr->gamma_16_table[i]);
G
Guy Schalnat 已提交
1226
      }
1227
   png_free(png_ptr, png_ptr->gamma_16_table);
G
Guy Schalnat 已提交
1228
   }
G
Guy Schalnat 已提交
1229
#if defined(PNG_READ_BACKGROUND_SUPPORTED)
A
Andreas Dilger 已提交
1230
   if (png_ptr->gamma_16_from_1 != NULL)
G
Guy Schalnat 已提交
1231
   {
1232 1233
      int i;
      int istop = (1 << (8 - png_ptr->gamma_shift));
1234
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1235
      {
A
Andreas Dilger 已提交
1236
         png_free(png_ptr, png_ptr->gamma_16_from_1[i]);
G
Guy Schalnat 已提交
1237
      }
A
Andreas Dilger 已提交
1238
   png_free(png_ptr, png_ptr->gamma_16_from_1);
1239
   }
A
Andreas Dilger 已提交
1240
   if (png_ptr->gamma_16_to_1 != NULL)
G
Guy Schalnat 已提交
1241
   {
1242 1243
      int i;
      int istop = (1 << (8 - png_ptr->gamma_shift));
1244
      for (i = 0; i < istop; i++)
G
Guy Schalnat 已提交
1245
      {
A
Andreas Dilger 已提交
1246
         png_free(png_ptr, png_ptr->gamma_16_to_1[i]);
G
Guy Schalnat 已提交
1247
      }
A
Andreas Dilger 已提交
1248
   png_free(png_ptr, png_ptr->gamma_16_to_1);
1249
   }
G
Guy Schalnat 已提交
1250
#endif
1251 1252 1253
#endif
#if defined(PNG_TIME_RFC1123_SUPPORTED)
   png_free(png_ptr, png_ptr->time_buffer);
1254
#endif
G
Guy Schalnat 已提交
1255

A
Andreas Dilger 已提交
1256
   inflateEnd(&png_ptr->zstream);
G
Guy Schalnat 已提交
1257
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
A
Andreas Dilger 已提交
1258
   png_free(png_ptr, png_ptr->save_buffer);
G
Guy Schalnat 已提交
1259
#endif
G
Guy Schalnat 已提交
1260

1261 1262 1263 1264 1265 1266
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
#ifdef PNG_TEXT_SUPPORTED
   png_free(png_ptr, png_ptr->current_text);
#endif /* PNG_TEXT_SUPPORTED */
#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */

G
Guy Schalnat 已提交
1267 1268 1269
   /* Save the important info out of the png_struct, in case it is
    * being used again.
    */
1270
#ifdef PNG_SETJMP_SUPPORTED
1271
   png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf));
1272
#endif
G
Guy Schalnat 已提交
1273 1274 1275 1276

   error_fn = png_ptr->error_fn;
   warning_fn = png_ptr->warning_fn;
   error_ptr = png_ptr->error_ptr;
1277 1278 1279
#ifdef PNG_USER_MEM_SUPPORTED
   free_fn = png_ptr->free_fn;
#endif
G
Guy Schalnat 已提交
1280

1281
   png_memset(png_ptr, 0, png_sizeof(png_struct));
G
Guy Schalnat 已提交
1282 1283 1284 1285

   png_ptr->error_fn = error_fn;
   png_ptr->warning_fn = warning_fn;
   png_ptr->error_ptr = error_ptr;
1286 1287 1288
#ifdef PNG_USER_MEM_SUPPORTED
   png_ptr->free_fn = free_fn;
#endif
G
Guy Schalnat 已提交
1289

1290
#ifdef PNG_SETJMP_SUPPORTED
1291
   png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf));
1292 1293
#endif

G
Guy Schalnat 已提交
1294
}
1295

1296
void PNGAPI
1297 1298
png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
{
1299
   if (png_ptr == NULL) return;
1300 1301
   png_ptr->read_row_fn = read_row_fn;
}
1302

1303 1304

#ifndef PNG_NO_SEQUENTIAL_READ_SUPPORTED
1305
#if defined(PNG_INFO_IMAGE_SUPPORTED)
1306 1307
void PNGAPI
png_read_png(png_structp png_ptr, png_infop info_ptr,
1308 1309 1310 1311 1312
                           int transforms,
                           voidp params)
{
   int row;

1313
   if (png_ptr == NULL) return;
1314
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED)
1315 1316
   /* invert the alpha channel from opacity to transparency
    */
1317 1318 1319 1320
   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
       png_set_invert_alpha(png_ptr);
#endif

1321
   /* png_read_info() gives us all of the information from the
1322 1323 1324
    * PNG file before the first IDAT (image data chunk).
    */
   png_read_info(png_ptr, info_ptr);
1325
   if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
1326
      png_error(png_ptr, "Image is too high to process with png_read_png()");
1327 1328 1329 1330

   /* -------------- image transformations start here ------------------- */

#if defined(PNG_READ_16_TO_8_SUPPORTED)
1331 1332
   /* tell libpng to strip 16 bit/color files down to 8 bits per color
    */
1333 1334 1335 1336 1337
   if (transforms & PNG_TRANSFORM_STRIP_16)
       png_set_strip_16(png_ptr);
#endif

#if defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
1338 1339
   /* Strip alpha bytes from the input data without combining with
    * the background (not recommended).
1340 1341 1342 1343 1344
    */
   if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
       png_set_strip_alpha(png_ptr);
#endif

1345
#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
1346
   /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single
1347 1348 1349 1350 1351 1352 1353 1354
    * byte into separate bytes (useful for paletted and grayscale images).
    */
   if (transforms & PNG_TRANSFORM_PACKING)
       png_set_packing(png_ptr);
#endif

#if defined(PNG_READ_PACKSWAP_SUPPORTED)
   /* Change the order of packed pixels to least significant bit first
1355 1356
    * (not useful if you are using png_set_packing).
    */
1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367
   if (transforms & PNG_TRANSFORM_PACKSWAP)
       png_set_packswap(png_ptr);
#endif

#if defined(PNG_READ_EXPAND_SUPPORTED)
   /* Expand paletted colors into true RGB triplets
    * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
    * Expand paletted or RGB images with transparency to full alpha
    * channels so the data will be available as RGBA quartets.
    */
   if (transforms & PNG_TRANSFORM_EXPAND)
1368 1369 1370 1371
       if ((png_ptr->bit_depth < 8) ||
           (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
           (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
         png_set_expand(png_ptr);
1372 1373
#endif

1374 1375
   /* We don't handle background color or gamma transformation or dithering.
    */
1376 1377

#if defined(PNG_READ_INVERT_SUPPORTED)
1378 1379
   /* invert monochrome files to have 0 as white and 1 as black
    */
1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
   if (transforms & PNG_TRANSFORM_INVERT_MONO)
       png_set_invert_mono(png_ptr);
#endif

#if defined(PNG_READ_SHIFT_SUPPORTED)
   /* If you want to shift the pixel values from the range [0,255] or
    * [0,65535] to the original [0,7] or [0,31], or whatever range the
    * colors were originally in:
    */
   if ((transforms & PNG_TRANSFORM_SHIFT)
       && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
   {
      png_color_8p sig_bit;

      png_get_sBIT(png_ptr, info_ptr, &sig_bit);
      png_set_shift(png_ptr, sig_bit);
   }
#endif

#if defined(PNG_READ_BGR_SUPPORTED)
1400 1401
   /* flip the RGB pixels to BGR (or RGBA to BGRA)
    */
1402 1403 1404 1405 1406
   if (transforms & PNG_TRANSFORM_BGR)
       png_set_bgr(png_ptr);
#endif

#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED)
1407 1408
   /* swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR)
    */
1409 1410 1411 1412 1413
   if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
       png_set_swap_alpha(png_ptr);
#endif

#if defined(PNG_READ_SWAP_SUPPORTED)
1414 1415
   /* swap bytes of 16 bit files to least significant byte first
    */
1416 1417 1418 1419 1420 1421 1422 1423
   if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
       png_set_swap(png_ptr);
#endif

   /* We don't handle adding filler bytes */

   /* Optional call to gamma correct and add the background to the palette
    * and update info structure.  REQUIRED if you are expecting libpng to
1424
    * update the palette for you (i.e., you selected such a transform above).
1425 1426 1427 1428 1429
    */
   png_read_update_info(png_ptr, info_ptr);

   /* -------------- image transformations end here ------------------- */

1430
#ifdef PNG_FREE_ME_SUPPORTED
1431
   png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1432
#endif
1433
   if (info_ptr->row_pointers == NULL)
1434 1435
   {
      info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
1436
         info_ptr->height * png_sizeof(png_bytep));
1437
#ifdef PNG_FREE_ME_SUPPORTED
1438
      info_ptr->free_me |= PNG_FREE_ROWS;
1439 1440
#endif
      for (row = 0; row < (int)info_ptr->height; row++)
1441 1442
      {
         info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
1443
            png_get_rowbytes(png_ptr, info_ptr));
1444
      }
1445
   }
1446 1447 1448 1449 1450 1451

   png_read_image(png_ptr, info_ptr->row_pointers);
   info_ptr->valid |= PNG_INFO_IDAT;

   /* read rest of file, and get additional chunks in info_ptr - REQUIRED */
   png_read_end(png_ptr, info_ptr);
1452

1453 1454
   transforms = transforms; /* quiet compiler warnings */
   params = params;
1455

1456
}
1457
#endif /* PNG_INFO_IMAGE_SUPPORTED */
1458
#endif /* PNG_NO_SEQUENTIAL_READ_SUPPORTED */
1459
#endif /* PNG_READ_SUPPORTED */