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

A
Andreas Dilger 已提交
2
/* pngread.c - read a PNG file
3
 *
4
 * Last changed in libpng 1.5.7 [(PENDING RELEASE)]
5
 * Copyright (c) 1998-2011 Glenn Randers-Pehrson
6 7
 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
 * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
8
 *
9
 * This code is released under the libpng license.
10
 * For conditions of distribution and use, see the disclaimer
11
 * and license in png.h
12
 *
13 14 15
 * This file contains routines that an application calls directly to
 * read a PNG file or stream.
 */
G
Guy Schalnat 已提交
16

17
#include "pngpriv.h"
18 19 20
#if defined PNG_SIMPLIFIED_READ_SUPPORTED && defined PNG_STDIO_SUPPORTED
#  include <errno.h>
#endif
21

22
#ifdef PNG_READ_SUPPORTED
23

A
Andreas Dilger 已提交
24
/* Create a PNG structure for reading, and allocate any memory needed. */
25 26 27
PNG_FUNCTION(png_structp,PNGAPI
png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
    png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
G
Guy Schalnat 已提交
28
{
29 30 31

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

35 36 37
/* Alternate create PNG structure for reading, and allocate any memory
 * needed.
 */
38 39
PNG_FUNCTION(png_structp,PNGAPI
png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
40
    png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
41
    png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
42 43 44
{
#endif /* PNG_USER_MEM_SUPPORTED */

45 46 47 48
#ifdef PNG_SETJMP_SUPPORTED
   volatile
#endif
   png_structp png_ptr;
49
   volatile int png_cleanup_needed = 0;
50

51
   png_debug(1, "in png_create_read_struct");
52

53
#ifdef PNG_USER_MEM_SUPPORTED
54
   png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
55
       malloc_fn, mem_ptr);
56
#else
57
   png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
58
#endif
59
   if (png_ptr == NULL)
60
      return (NULL);
61

62
   /* Added at libpng-1.2.6 */
63
#ifdef PNG_USER_LIMITS_SUPPORTED
64 65
   png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
   png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
66

67 68
#  ifdef PNG_USER_CHUNK_CACHE_MAX
   /* Added at libpng-1.2.43 and 1.4.0 */
69
   png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
70
#  endif
71

72 73 74 75
#  ifdef PNG_SET_USER_CHUNK_MALLOC_MAX
   /* Added at libpng-1.2.43 and 1.4.1 */
   png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
#  endif
76 77
#endif

78 79
#ifdef PNG_SETJMP_SUPPORTED
/* Applications that neglect to set up their own setjmp() and then
80 81 82
 * encounter a png_error() will longjmp here.  Since the jmpbuf is
 * then meaningless we abort instead of returning.
 */
83
   if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */
84
      PNG_ABORT();
85
#endif /* PNG_SETJMP_SUPPORTED */
86

87 88
#ifdef PNG_USER_MEM_SUPPORTED
   png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
89
#endif
90

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

93 94 95
   /* Call the general version checker (shared with read and write code): */
   if (!png_user_version_check(png_ptr, user_png_ver))
      png_cleanup_needed = 1;
96

97 98
   if (!png_cleanup_needed)
   {
99
   /* Initialize zbuf - compression buffer */
G
Guy Schalnat 已提交
100
   png_ptr->zbuf_size = PNG_ZBUF_SIZE;
101 102
   png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size);

103
   if (png_ptr->zbuf == NULL)
104
      png_cleanup_needed = 1;
105
   }
106

A
Andreas Dilger 已提交
107 108 109
   png_ptr->zstream.zalloc = png_zalloc;
   png_ptr->zstream.zfree = png_zfree;
   png_ptr->zstream.opaque = (voidpf)png_ptr;
G
Guy Schalnat 已提交
110

111 112
   if (!png_cleanup_needed)
   {
113 114
      switch (inflateInit(&png_ptr->zstream))
      {
115 116 117
         case Z_OK:
            break; /* Do nothing */

118
         case Z_MEM_ERROR:
119 120 121 122 123 124 125 126 127 128 129 130 131 132
            png_warning(png_ptr, "zlib memory error");
            png_cleanup_needed = 1;
            break;

         case Z_STREAM_ERROR:
            png_warning(png_ptr, "zlib stream error");
            png_cleanup_needed = 1;
            break;

         case Z_VERSION_ERROR:
            png_warning(png_ptr, "zlib version error");
            png_cleanup_needed = 1;
            break;

133 134 135
         default: png_warning(png_ptr, "Unknown zlib error");
            png_cleanup_needed = 1;
      }
136 137 138 139
   }

   if (png_cleanup_needed)
   {
140 141 142
      /* Clean up PNG structure and deallocate any memory. */
      png_free(png_ptr, png_ptr->zbuf);
      png_ptr->zbuf = NULL;
143
#ifdef PNG_USER_MEM_SUPPORTED
144
      png_destroy_struct_2((png_voidp)png_ptr,
145
          (png_free_ptr)free_fn, (png_voidp)mem_ptr);
146
#else
147
      png_destroy_struct((png_voidp)png_ptr);
148
#endif
149
      return (NULL);
G
Guy Schalnat 已提交
150 151
   }

A
Andreas Dilger 已提交
152 153
   png_ptr->zstream.next_out = png_ptr->zbuf;
   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
G
Guy Schalnat 已提交
154

155
   png_set_read_fn(png_ptr, NULL, NULL);
G
Guy Schalnat 已提交
156

157

G
Guy Schalnat 已提交
158 159 160
   return (png_ptr);
}

161

162
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
A
Andreas Dilger 已提交
163
/* Read the information before the actual image data.  This has been
164
 * changed in v0.90 to allow reading a file that already has the magic
A
Andreas Dilger 已提交
165
 * bytes read from the stream.  You can tell libpng how many bytes have
166
 * been read from the beginning of the stream (up to the maximum of 8)
A
Andreas Dilger 已提交
167 168 169 170
 * 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.
 */
171
void PNGAPI
A
Andreas Dilger 已提交
172
png_read_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
173
{
174
   png_debug(1, "in png_read_info");
175

176 177
   if (png_ptr == NULL || info_ptr == NULL)
      return;
178

179 180
   /* Read and check the PNG file signature. */
   png_read_sig(png_ptr, info_ptr);
G
Guy Schalnat 已提交
181

182
   for (;;)
G
Guy Schalnat 已提交
183
   {
184
      png_uint_32 length = png_read_chunk_header(png_ptr);
185
      png_uint_32 chunk_name = png_ptr->chunk_name;
A
Andreas Dilger 已提交
186 187 188 189

      /* This should be a binary subdivision search or a hash for
       * matching the chunk name rather than a linear search.
       */
190
      if (chunk_name == png_IDAT)
191 192
         if (png_ptr->mode & PNG_AFTER_IDAT)
            png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
193

194
      if (chunk_name == png_IHDR)
A
Andreas Dilger 已提交
195
         png_handle_IHDR(png_ptr, info_ptr, length);
196

197
      else if (chunk_name == png_IEND)
A
Andreas Dilger 已提交
198
         png_handle_IEND(png_ptr, info_ptr, length);
199

200
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
201 202
      else if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
         PNG_HANDLE_CHUNK_AS_DEFAULT)
203
      {
204
         if (chunk_name == png_IDAT)
205
            png_ptr->mode |= PNG_HAVE_IDAT;
206

207
         png_handle_unknown(png_ptr, info_ptr, length);
208

209
         if (chunk_name == png_PLTE)
210
            png_ptr->mode |= PNG_HAVE_PLTE;
211

212
         else if (chunk_name == png_IDAT)
213 214 215
         {
            if (!(png_ptr->mode & PNG_HAVE_IHDR))
               png_error(png_ptr, "Missing IHDR before IDAT");
216

217
            else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
218
                !(png_ptr->mode & PNG_HAVE_PLTE))
219
               png_error(png_ptr, "Missing PLTE before IDAT");
220

221 222 223 224
            break;
         }
      }
#endif
225
      else if (chunk_name == png_PLTE)
226
         png_handle_PLTE(png_ptr, info_ptr, length);
227

228
      else if (chunk_name == png_IDAT)
A
Andreas Dilger 已提交
229 230 231
      {
         if (!(png_ptr->mode & PNG_HAVE_IHDR))
            png_error(png_ptr, "Missing IHDR before IDAT");
232

A
Andreas Dilger 已提交
233
         else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
234
             !(png_ptr->mode & PNG_HAVE_PLTE))
A
Andreas Dilger 已提交
235 236 237 238 239 240
            png_error(png_ptr, "Missing PLTE before IDAT");

         png_ptr->idat_size = length;
         png_ptr->mode |= PNG_HAVE_IDAT;
         break;
      }
241

242
#ifdef PNG_READ_bKGD_SUPPORTED
243
      else if (chunk_name == png_bKGD)
A
Andreas Dilger 已提交
244
         png_handle_bKGD(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
245
#endif
246

247
#ifdef PNG_READ_cHRM_SUPPORTED
248
      else if (chunk_name == png_cHRM)
A
Andreas Dilger 已提交
249
         png_handle_cHRM(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
250
#endif
251

252
#ifdef PNG_READ_gAMA_SUPPORTED
253
      else if (chunk_name == png_gAMA)
A
Andreas Dilger 已提交
254
         png_handle_gAMA(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
255
#endif
256

257
#ifdef PNG_READ_hIST_SUPPORTED
258
      else if (chunk_name == png_hIST)
A
Andreas Dilger 已提交
259
         png_handle_hIST(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
260
#endif
261

262
#ifdef PNG_READ_oFFs_SUPPORTED
263
      else if (chunk_name == png_oFFs)
A
Andreas Dilger 已提交
264 265
         png_handle_oFFs(png_ptr, info_ptr, length);
#endif
266

267
#ifdef PNG_READ_pCAL_SUPPORTED
268
      else if (chunk_name == png_pCAL)
A
Andreas Dilger 已提交
269 270
         png_handle_pCAL(png_ptr, info_ptr, length);
#endif
271

272
#ifdef PNG_READ_sCAL_SUPPORTED
273
      else if (chunk_name == png_sCAL)
274 275
         png_handle_sCAL(png_ptr, info_ptr, length);
#endif
276

277
#ifdef PNG_READ_pHYs_SUPPORTED
278
      else if (chunk_name == png_pHYs)
A
Andreas Dilger 已提交
279
         png_handle_pHYs(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
280
#endif
281

282
#ifdef PNG_READ_sBIT_SUPPORTED
283
      else if (chunk_name == png_sBIT)
A
Andreas Dilger 已提交
284 285
         png_handle_sBIT(png_ptr, info_ptr, length);
#endif
286

287
#ifdef PNG_READ_sRGB_SUPPORTED
288
      else if (chunk_name == png_sRGB)
289 290
         png_handle_sRGB(png_ptr, info_ptr, length);
#endif
291

292
#ifdef PNG_READ_iCCP_SUPPORTED
293
      else if (chunk_name == png_iCCP)
294 295
         png_handle_iCCP(png_ptr, info_ptr, length);
#endif
296

297
#ifdef PNG_READ_sPLT_SUPPORTED
298
      else if (chunk_name == png_sPLT)
299 300
         png_handle_sPLT(png_ptr, info_ptr, length);
#endif
301

302
#ifdef PNG_READ_tEXt_SUPPORTED
303
      else if (chunk_name == png_tEXt)
A
Andreas Dilger 已提交
304
         png_handle_tEXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
305
#endif
306

307
#ifdef PNG_READ_tIME_SUPPORTED
308
      else if (chunk_name == png_tIME)
A
Andreas Dilger 已提交
309
         png_handle_tIME(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
310
#endif
311

312
#ifdef PNG_READ_tRNS_SUPPORTED
313
      else if (chunk_name == png_tRNS)
A
Andreas Dilger 已提交
314
         png_handle_tRNS(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
315
#endif
316

317
#ifdef PNG_READ_zTXt_SUPPORTED
318
      else if (chunk_name == png_zTXt)
A
Andreas Dilger 已提交
319
         png_handle_zTXt(png_ptr, info_ptr, length);
320
#endif
321

322
#ifdef PNG_READ_iTXt_SUPPORTED
323
      else if (chunk_name == png_iTXt)
324
         png_handle_iTXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
325
#endif
326

A
Andreas Dilger 已提交
327 328
      else
         png_handle_unknown(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
329 330
   }
}
331
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
332

333
/* Optional call to update the users info_ptr structure */
334
void PNGAPI
A
Andreas Dilger 已提交
335
png_read_update_info(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
336
{
337
   png_debug(1, "in png_read_update_info");
338

339 340
   if (png_ptr == NULL)
      return;
341

342
   png_read_start_row(png_ptr);
343

344
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
A
Andreas Dilger 已提交
345
   png_read_transform_info(png_ptr, info_ptr);
346 347 348
#else
   PNG_UNUSED(info_ptr)
#endif
G
Guy Schalnat 已提交
349 350
}

351
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
352 353
/* Initialize palette, background, etc, after transformations
 * are set, but before any reading takes place.  This allows
354
 * the user to obtain a gamma-corrected palette, for example.
355 356
 * If the user doesn't call this, we will do it ourselves.
 */
357
void PNGAPI
G
Guy Schalnat 已提交
358
png_start_read_image(png_structp png_ptr)
G
Guy Schalnat 已提交
359
{
360
   png_debug(1, "in png_start_read_image");
361

362 363
   if (png_ptr != NULL)
     png_read_start_row(png_ptr);
G
Guy Schalnat 已提交
364
}
365
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
366

367
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
368
void PNGAPI
G
Guy Schalnat 已提交
369
png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
G
Guy Schalnat 已提交
370 371
{
   int ret;
372

373 374
   png_row_info row_info;

375 376
   if (png_ptr == NULL)
      return;
377

378
   png_debug2(1, "in png_read_row (row %lu, pass %d)",
379
       (unsigned long)png_ptr->row_number, png_ptr->pass);
380

381 382 383
   /* png_read_start_row sets the information (in particular iwidth) for this
    * interlace pass.
    */
G
Guy Schalnat 已提交
384
   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
G
Guy Schalnat 已提交
385
      png_read_start_row(png_ptr);
386

387 388 389 390 391 392 393 394
   /* 1.5.6: row_info moved out of png_struct to a local here. */
   row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */
   row_info.color_type = png_ptr->color_type;
   row_info.bit_depth = png_ptr->bit_depth;
   row_info.channels = png_ptr->channels;
   row_info.pixel_depth = png_ptr->pixel_depth;
   row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);

395 396
   if (png_ptr->row_number == 0 && png_ptr->pass == 0)
   {
397
   /* Check for transforms that have been set but were defined out */
398 399
#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
   if (png_ptr->transformations & PNG_INVERT_MONO)
400
      png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined");
401
#endif
402

403 404
#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
   if (png_ptr->transformations & PNG_FILLER)
405
      png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined");
406
#endif
407

408 409
#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
    !defined(PNG_READ_PACKSWAP_SUPPORTED)
410
   if (png_ptr->transformations & PNG_PACKSWAP)
411
      png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined");
412
#endif
413

414 415
#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
   if (png_ptr->transformations & PNG_PACK)
416
      png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined");
417
#endif
418

419 420
#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
   if (png_ptr->transformations & PNG_SHIFT)
421
      png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined");
422
#endif
423

424 425
#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
   if (png_ptr->transformations & PNG_BGR)
426
      png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined");
427
#endif
428

429 430
#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
   if (png_ptr->transformations & PNG_SWAP_BYTES)
431
      png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined");
432 433
#endif
   }
G
Guy Schalnat 已提交
434

435
#ifdef PNG_READ_INTERLACING_SUPPORTED
436 437 438 439 440 441
   /* If interlaced and we do not need a new row, combine row and return.
    * Notice that the pixels we have from previous rows have been transformed
    * already; we can only combine like with like (transformed or
    * untransformed) and, because of the libpng API for interlaced images, this
    * means we must transform before de-interlacing.
    */
G
Guy Schalnat 已提交
442 443 444 445 446
   if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
   {
      switch (png_ptr->pass)
      {
         case 0:
447
            if (png_ptr->row_number & 0x07)
G
Guy Schalnat 已提交
448
            {
A
Andreas Dilger 已提交
449
               if (dsp_row != NULL)
450
                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
G
Guy Schalnat 已提交
451
               png_read_finish_row(png_ptr);
G
Guy Schalnat 已提交
452 453 454
               return;
            }
            break;
455

G
Guy Schalnat 已提交
456
         case 1:
457
            if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
G
Guy Schalnat 已提交
458
            {
A
Andreas Dilger 已提交
459
               if (dsp_row != NULL)
460
                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
461

G
Guy Schalnat 已提交
462 463 464 465
               png_read_finish_row(png_ptr);
               return;
            }
            break;
466

G
Guy Schalnat 已提交
467
         case 2:
468
            if ((png_ptr->row_number & 0x07) != 4)
G
Guy Schalnat 已提交
469
            {
A
Andreas Dilger 已提交
470
               if (dsp_row != NULL && (png_ptr->row_number & 4))
471
                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
472

G
Guy Schalnat 已提交
473 474 475 476
               png_read_finish_row(png_ptr);
               return;
            }
            break;
477

G
Guy Schalnat 已提交
478 479 480
         case 3:
            if ((png_ptr->row_number & 3) || png_ptr->width < 3)
            {
A
Andreas Dilger 已提交
481
               if (dsp_row != NULL)
482
                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
483

G
Guy Schalnat 已提交
484 485 486 487
               png_read_finish_row(png_ptr);
               return;
            }
            break;
488

G
Guy Schalnat 已提交
489 490
         case 4:
            if ((png_ptr->row_number & 3) != 2)
G
Guy Schalnat 已提交
491
            {
A
Andreas Dilger 已提交
492
               if (dsp_row != NULL && (png_ptr->row_number & 2))
493
                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
494

G
Guy Schalnat 已提交
495 496 497 498 499 500 501
               png_read_finish_row(png_ptr);
               return;
            }
            break;
         case 5:
            if ((png_ptr->row_number & 1) || png_ptr->width < 2)
            {
A
Andreas Dilger 已提交
502
               if (dsp_row != NULL)
503
                  png_combine_row(png_ptr, dsp_row, 1/*display*/);
504

G
Guy Schalnat 已提交
505 506 507 508
               png_read_finish_row(png_ptr);
               return;
            }
            break;
509

510
         default:
G
Guy Schalnat 已提交
511
         case 6:
G
Guy Schalnat 已提交
512 513 514 515 516 517 518 519
            if (!(png_ptr->row_number & 1))
            {
               png_read_finish_row(png_ptr);
               return;
            }
            break;
      }
   }
G
Guy Schalnat 已提交
520
#endif
G
Guy Schalnat 已提交
521

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

A
Andreas Dilger 已提交
525
   png_ptr->zstream.next_out = png_ptr->row_buf;
526 527 528
   png_ptr->zstream.avail_out =
       (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
       png_ptr->iwidth) + 1);
529

G
Guy Schalnat 已提交
530 531
   do
   {
A
Andreas Dilger 已提交
532
      if (!(png_ptr->zstream.avail_in))
G
Guy Schalnat 已提交
533 534 535
      {
         while (!png_ptr->idat_size)
         {
A
Andreas Dilger 已提交
536
            png_crc_finish(png_ptr, 0);
G
Guy Schalnat 已提交
537

538
            png_ptr->idat_size = png_read_chunk_header(png_ptr);
539
            if (png_ptr->chunk_name != png_IDAT)
A
Andreas Dilger 已提交
540
               png_error(png_ptr, "Not enough image data");
G
Guy Schalnat 已提交
541
         }
A
Andreas Dilger 已提交
542 543
         png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
         png_ptr->zstream.next_in = png_ptr->zbuf;
G
Guy Schalnat 已提交
544
         if (png_ptr->zbuf_size > png_ptr->idat_size)
A
Andreas Dilger 已提交
545
            png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
A
Andreas Dilger 已提交
546
         png_crc_read(png_ptr, png_ptr->zbuf,
547
             (png_size_t)png_ptr->zstream.avail_in);
A
Andreas Dilger 已提交
548
         png_ptr->idat_size -= png_ptr->zstream.avail_in;
G
Guy Schalnat 已提交
549
      }
550

A
Andreas Dilger 已提交
551
      ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
552

G
Guy Schalnat 已提交
553 554
      if (ret == Z_STREAM_END)
      {
A
Andreas Dilger 已提交
555
         if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
G
Guy Schalnat 已提交
556
            png_ptr->idat_size)
557
            png_benign_error(png_ptr, "Extra compressed data");
A
Andreas Dilger 已提交
558
         png_ptr->mode |= PNG_AFTER_IDAT;
G
Guy Schalnat 已提交
559
         png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
G
Guy Schalnat 已提交
560
         break;
G
Guy Schalnat 已提交
561
      }
562

G
Guy Schalnat 已提交
563
      if (ret != Z_OK)
A
Andreas Dilger 已提交
564
         png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
565
             "Decompression error");
A
Andreas Dilger 已提交
566 567

   } while (png_ptr->zstream.avail_out);
G
Guy Schalnat 已提交
568

569 570 571
   if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
   {
      if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST)
572
         png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1,
573 574 575 576
            png_ptr->prev_row + 1, png_ptr->row_buf[0]);
      else
         png_error(png_ptr, "bad adaptive filter value");
   }
G
Guy Schalnat 已提交
577

578 579 580 581 582 583
   /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before
    * 1.5.6, while the buffer really is this big in current versions of libpng
    * it may not be in the future, so this was changed just to copy the
    * interlaced count:
    */
   png_memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
584

585
#ifdef PNG_MNG_FEATURES_SUPPORTED
586
   if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
587
       (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
588 589
   {
      /* Intrapixel differencing */
590
      png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1);
591 592
   }
#endif
G
Guy Schalnat 已提交
593

594

595
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
596
   if (png_ptr->transformations)
597
      png_do_read_transformations(png_ptr, &row_info);
598
#endif
G
Guy Schalnat 已提交
599

600 601 602 603 604 605 606 607 608 609 610
   /* The transformed pixel depth should match the depth now in row_info. */
   if (png_ptr->transformed_pixel_depth == 0)
   {
      png_ptr->transformed_pixel_depth = row_info.pixel_depth;
      if (row_info.pixel_depth > png_ptr->maximum_pixel_depth)
         png_error(png_ptr, "sequential row overflow");
   }

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

611
#ifdef PNG_READ_INTERLACING_SUPPORTED
612
   /* Blow up interlaced rows to full size */
G
Guy Schalnat 已提交
613 614 615 616
   if (png_ptr->interlaced &&
      (png_ptr->transformations & PNG_INTERLACE))
   {
      if (png_ptr->pass < 6)
617 618
         png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
            png_ptr->transformations);
G
Guy Schalnat 已提交
619

A
Andreas Dilger 已提交
620
      if (dsp_row != NULL)
621
         png_combine_row(png_ptr, dsp_row, 1/*display*/);
622

A
Andreas Dilger 已提交
623
      if (row != NULL)
624
         png_combine_row(png_ptr, row, 0/*row*/);
G
Guy Schalnat 已提交
625
   }
626

G
Guy Schalnat 已提交
627
   else
G
Guy Schalnat 已提交
628
#endif
G
Guy Schalnat 已提交
629
   {
A
Andreas Dilger 已提交
630
      if (row != NULL)
631
         png_combine_row(png_ptr, row, -1/*ignored*/);
632

A
Andreas Dilger 已提交
633
      if (dsp_row != NULL)
634
         png_combine_row(png_ptr, dsp_row, -1/*ignored*/);
G
Guy Schalnat 已提交
635 636
   }
   png_read_finish_row(png_ptr);
637 638 639

   if (png_ptr->read_row_fn != NULL)
      (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
G
Guy Schalnat 已提交
640
}
641
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
642

643
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
A
Andreas Dilger 已提交
644
/* Read one or more rows of image data.  If the image is interlaced,
645 646
 * and png_set_interlace_handling() has been called, the rows need to
 * contain the contents of the rows from the previous pass.  If the
647
 * image has alpha or transparency, and png_handle_alpha()[*] has been
648 649
 * called, the rows contents must be initialized to the contents of the
 * screen.
650
 *
651 652 653 654 655 656 657 658 659 660 661 662 663
 * "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.
664
 *
665
 * [*] png_handle_alpha() does not exist yet, as of this version of libpng
666
 */
G
Guy Schalnat 已提交
667

668
void PNGAPI
G
Guy Schalnat 已提交
669
png_read_rows(png_structp png_ptr, png_bytepp row,
670
    png_bytepp display_row, png_uint_32 num_rows)
G
Guy Schalnat 已提交
671
{
G
Guy Schalnat 已提交
672 673 674
   png_uint_32 i;
   png_bytepp rp;
   png_bytepp dp;
G
Guy Schalnat 已提交
675

676
   png_debug(1, "in png_read_rows");
677

678 679
   if (png_ptr == NULL)
      return;
680

G
Guy Schalnat 已提交
681 682
   rp = row;
   dp = display_row;
683
   if (rp != NULL && dp != NULL)
684 685 686 687
      for (i = 0; i < num_rows; i++)
      {
         png_bytep rptr = *rp++;
         png_bytep dptr = *dp++;
688

689 690
         png_read_row(png_ptr, rptr, dptr);
      }
691

692
   else if (rp != NULL)
693 694
      for (i = 0; i < num_rows; i++)
      {
695
         png_bytep rptr = *rp;
696
         png_read_row(png_ptr, rptr, NULL);
697 698
         rp++;
      }
699

700
   else if (dp != NULL)
701 702 703
      for (i = 0; i < num_rows; i++)
      {
         png_bytep dptr = *dp;
704
         png_read_row(png_ptr, NULL, dptr);
705
         dp++;
706
      }
G
Guy Schalnat 已提交
707
}
708
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
709

710
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
A
Andreas Dilger 已提交
711
/* Read the entire image.  If the image has an alpha channel or a tRNS
712
 * chunk, and you have called png_handle_alpha()[*], you will need to
713 714 715 716 717 718 719
 * 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.
720
 *
721
 * [*] png_handle_alpha() does not exist yet, as of this version of libpng
722
 */
723
void PNGAPI
G
Guy Schalnat 已提交
724
png_read_image(png_structp png_ptr, png_bytepp image)
G
Guy Schalnat 已提交
725
{
726
   png_uint_32 i, image_height;
G
Guy Schalnat 已提交
727
   int pass, j;
G
Guy Schalnat 已提交
728
   png_bytepp rp;
G
Guy Schalnat 已提交
729

730
   png_debug(1, "in png_read_image");
731

732 733
   if (png_ptr == NULL)
      return;
734 735

#ifdef PNG_READ_INTERLACING_SUPPORTED
G
[devel]  
Glenn Randers-Pehrson 已提交
736 737 738 739 740 741 742 743
   if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
   {
      pass = png_set_interlace_handling(png_ptr);
      /* And make sure transforms are initialized. */
      png_start_read_image(png_ptr);
   }
   else
   {
744
      if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE))
G
[devel]  
Glenn Randers-Pehrson 已提交
745
      {
746 747 748 749 750 751 752 753
         /* Caller called png_start_read_image or png_read_update_info without
          * first turning on the PNG_INTERLACE transform.  We can fix this here,
          * but the caller should do it!
          */
         png_warning(png_ptr, "Interlace handling should be turned on when "
            "using png_read_image");
         /* Make sure this is set correctly */
         png_ptr->num_rows = png_ptr->height;
G
[devel]  
Glenn Randers-Pehrson 已提交
754 755 756 757 758 759 760
      }

      /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in
       * the above error case.
       */
      pass = png_set_interlace_handling(png_ptr);
   }
761 762 763
#else
   if (png_ptr->interlaced)
      png_error(png_ptr,
764
          "Cannot read interlaced image -- interlace handler disabled");
765

766 767 768
   pass = 1;
#endif

769
   image_height=png_ptr->height;
G
Guy Schalnat 已提交
770

G
Guy Schalnat 已提交
771 772 773
   for (j = 0; j < pass; j++)
   {
      rp = image;
774
      for (i = 0; i < image_height; i++)
G
Guy Schalnat 已提交
775
      {
776
         png_read_row(png_ptr, *rp, NULL);
G
Guy Schalnat 已提交
777 778 779 780
         rp++;
      }
   }
}
781
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
782

783
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
A
Andreas Dilger 已提交
784
/* Read the end of the PNG file.  Will not read past the end of the
785 786 787
 * 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.
 */
788
void PNGAPI
A
Andreas Dilger 已提交
789
png_read_end(png_structp png_ptr, png_infop info_ptr)
G
Guy Schalnat 已提交
790
{
791
   png_debug(1, "in png_read_end");
792

793 794
   if (png_ptr == NULL)
      return;
795

A
Andreas Dilger 已提交
796
   png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
G
Guy Schalnat 已提交
797 798 799

   do
   {
800
      png_uint_32 length = png_read_chunk_header(png_ptr);
801
      png_uint_32 chunk_name = png_ptr->chunk_name;
A
Andreas Dilger 已提交
802

803
      if (chunk_name == png_IHDR)
A
Andreas Dilger 已提交
804
         png_handle_IHDR(png_ptr, info_ptr, length);
805

806
      else if (chunk_name == png_IEND)
807
         png_handle_IEND(png_ptr, info_ptr, length);
808

809
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
810 811
      else if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
         PNG_HANDLE_CHUNK_AS_DEFAULT)
812
      {
813
         if (chunk_name == png_IDAT)
814
         {
815
            if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
816
               png_benign_error(png_ptr, "Too many IDATs found");
817 818
         }
         png_handle_unknown(png_ptr, info_ptr, length);
819
         if (chunk_name == png_PLTE)
820 821 822
            png_ptr->mode |= PNG_HAVE_PLTE;
      }
#endif
823

824
      else if (chunk_name == png_IDAT)
A
Andreas Dilger 已提交
825 826 827 828
      {
         /* Zero length IDATs are legal after the last IDAT has been
          * read, but not after other chunks have been read.
          */
829
         if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
830
            png_benign_error(png_ptr, "Too many IDATs found");
831

832
         png_crc_finish(png_ptr, length);
A
Andreas Dilger 已提交
833
      }
834
      else if (chunk_name == png_PLTE)
A
Andreas Dilger 已提交
835
         png_handle_PLTE(png_ptr, info_ptr, length);
836

837
#ifdef PNG_READ_bKGD_SUPPORTED
838
      else if (chunk_name == png_bKGD)
A
Andreas Dilger 已提交
839
         png_handle_bKGD(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
840
#endif
841

842
#ifdef PNG_READ_cHRM_SUPPORTED
843
      else if (chunk_name == png_cHRM)
A
Andreas Dilger 已提交
844 845
         png_handle_cHRM(png_ptr, info_ptr, length);
#endif
846

847
#ifdef PNG_READ_gAMA_SUPPORTED
848
      else if (chunk_name == png_gAMA)
A
Andreas Dilger 已提交
849 850
         png_handle_gAMA(png_ptr, info_ptr, length);
#endif
851

852
#ifdef PNG_READ_hIST_SUPPORTED
853
      else if (chunk_name == png_hIST)
A
Andreas Dilger 已提交
854
         png_handle_hIST(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
855
#endif
856

857
#ifdef PNG_READ_oFFs_SUPPORTED
858
      else if (chunk_name == png_oFFs)
A
Andreas Dilger 已提交
859
         png_handle_oFFs(png_ptr, info_ptr, length);
A
Andreas Dilger 已提交
860
#endif
861

862
#ifdef PNG_READ_pCAL_SUPPORTED
863
      else if (chunk_name == png_pCAL)
A
Andreas Dilger 已提交
864 865
         png_handle_pCAL(png_ptr, info_ptr, length);
#endif
866

867
#ifdef PNG_READ_sCAL_SUPPORTED
868
      else if (chunk_name == png_sCAL)
869 870
         png_handle_sCAL(png_ptr, info_ptr, length);
#endif
871

872
#ifdef PNG_READ_pHYs_SUPPORTED
873
      else if (chunk_name == png_pHYs)
A
Andreas Dilger 已提交
874 875
         png_handle_pHYs(png_ptr, info_ptr, length);
#endif
876

877
#ifdef PNG_READ_sBIT_SUPPORTED
878
      else if (chunk_name == png_sBIT)
A
Andreas Dilger 已提交
879
         png_handle_sBIT(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
880
#endif
881

882
#ifdef PNG_READ_sRGB_SUPPORTED
883
      else if (chunk_name == png_sRGB)
884 885
         png_handle_sRGB(png_ptr, info_ptr, length);
#endif
886

887
#ifdef PNG_READ_iCCP_SUPPORTED
888
      else if (chunk_name == png_iCCP)
889 890
         png_handle_iCCP(png_ptr, info_ptr, length);
#endif
891

892
#ifdef PNG_READ_sPLT_SUPPORTED
893
      else if (chunk_name == png_sPLT)
894 895
         png_handle_sPLT(png_ptr, info_ptr, length);
#endif
896

897
#ifdef PNG_READ_tEXt_SUPPORTED
898
      else if (chunk_name == png_tEXt)
A
Andreas Dilger 已提交
899
         png_handle_tEXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
900
#endif
901

902
#ifdef PNG_READ_tIME_SUPPORTED
903
      else if (chunk_name == png_tIME)
A
Andreas Dilger 已提交
904 905
         png_handle_tIME(png_ptr, info_ptr, length);
#endif
906

907
#ifdef PNG_READ_tRNS_SUPPORTED
908
      else if (chunk_name == png_tRNS)
A
Andreas Dilger 已提交
909 910
         png_handle_tRNS(png_ptr, info_ptr, length);
#endif
911

912
#ifdef PNG_READ_zTXt_SUPPORTED
913
      else if (chunk_name == png_zTXt)
A
Andreas Dilger 已提交
914
         png_handle_zTXt(png_ptr, info_ptr, length);
915
#endif
916

917
#ifdef PNG_READ_iTXt_SUPPORTED
918
      else if (chunk_name == png_iTXt)
919
         png_handle_iTXt(png_ptr, info_ptr, length);
G
Guy Schalnat 已提交
920
#endif
921

G
Guy Schalnat 已提交
922
      else
A
Andreas Dilger 已提交
923 924
         png_handle_unknown(png_ptr, info_ptr, length);
   } while (!(png_ptr->mode & PNG_HAVE_IEND));
G
Guy Schalnat 已提交
925
}
926
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
G
Guy Schalnat 已提交
927

928
/* Free all memory used by the read */
929
void PNGAPI
G
Guy Schalnat 已提交
930
png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
931
    png_infopp end_info_ptr_ptr)
G
Guy Schalnat 已提交
932 933
{
   png_structp png_ptr = NULL;
A
Andreas Dilger 已提交
934
   png_infop info_ptr = NULL, end_info_ptr = NULL;
935
#ifdef PNG_USER_MEM_SUPPORTED
936 937
   png_free_ptr free_fn = NULL;
   png_voidp mem_ptr = NULL;
938
#endif
G
Guy Schalnat 已提交
939

940
   png_debug(1, "in png_destroy_read_struct");
941

A
Andreas Dilger 已提交
942
   if (png_ptr_ptr != NULL)
G
Guy Schalnat 已提交
943
      png_ptr = *png_ptr_ptr;
944 945 946 947 948 949 950
   if (png_ptr == NULL)
      return;

#ifdef PNG_USER_MEM_SUPPORTED
   free_fn = png_ptr->free_fn;
   mem_ptr = png_ptr->mem_ptr;
#endif
G
Guy Schalnat 已提交
951

A
Andreas Dilger 已提交
952
   if (info_ptr_ptr != NULL)
G
Guy Schalnat 已提交
953 954
      info_ptr = *info_ptr_ptr;

A
Andreas Dilger 已提交
955
   if (end_info_ptr_ptr != NULL)
A
Andreas Dilger 已提交
956
      end_info_ptr = *end_info_ptr_ptr;
G
Guy Schalnat 已提交
957

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

A
Andreas Dilger 已提交
960
   if (info_ptr != NULL)
G
Guy Schalnat 已提交
961
   {
962
#ifdef PNG_TEXT_SUPPORTED
963
      png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);
964
#endif
965 966

#ifdef PNG_USER_MEM_SUPPORTED
967 968
      png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
          (png_voidp)mem_ptr);
969
#else
A
Andreas Dilger 已提交
970
      png_destroy_struct((png_voidp)info_ptr);
971
#endif
972
      *info_ptr_ptr = NULL;
G
Guy Schalnat 已提交
973 974
   }

A
Andreas Dilger 已提交
975
   if (end_info_ptr != NULL)
G
Guy Schalnat 已提交
976
   {
977
#ifdef PNG_READ_TEXT_SUPPORTED
978
      png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);
979
#endif
980
#ifdef PNG_USER_MEM_SUPPORTED
981
      png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn,
982
          (png_voidp)mem_ptr);
983
#else
A
Andreas Dilger 已提交
984
      png_destroy_struct((png_voidp)end_info_ptr);
985
#endif
986
      *end_info_ptr_ptr = NULL;
G
Guy Schalnat 已提交
987 988
   }

A
Andreas Dilger 已提交
989
   if (png_ptr != NULL)
G
Guy Schalnat 已提交
990
   {
991
#ifdef PNG_USER_MEM_SUPPORTED
992 993
      png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
          (png_voidp)mem_ptr);
994
#else
A
Andreas Dilger 已提交
995
      png_destroy_struct((png_voidp)png_ptr);
996
#endif
997
      *png_ptr_ptr = NULL;
G
Guy Schalnat 已提交
998 999 1000
   }
}

1001
/* Free all memory used by the read (old method) */
1002
void /* PRIVATE */
1003 1004
png_read_destroy(png_structp png_ptr, png_infop info_ptr,
    png_infop end_info_ptr)
G
Guy Schalnat 已提交
1005
{
1006
#ifdef PNG_SETJMP_SUPPORTED
G
Guy Schalnat 已提交
1007
   jmp_buf tmp_jmp;
1008
#endif
G
Guy Schalnat 已提交
1009
   png_error_ptr error_fn;
1010
#ifdef PNG_WARNINGS_SUPPORTED
G
Guy Schalnat 已提交
1011
   png_error_ptr warning_fn;
1012
#endif
G
Guy Schalnat 已提交
1013
   png_voidp error_ptr;
1014 1015 1016
#ifdef PNG_USER_MEM_SUPPORTED
   png_free_ptr free_fn;
#endif
G
Guy Schalnat 已提交
1017

1018
   png_debug(1, "in png_read_destroy");
1019

A
Andreas Dilger 已提交
1020
   if (info_ptr != NULL)
A
Andreas Dilger 已提交
1021
      png_info_destroy(png_ptr, info_ptr);
G
Guy Schalnat 已提交
1022

A
Andreas Dilger 已提交
1023
   if (end_info_ptr != NULL)
A
Andreas Dilger 已提交
1024
      png_info_destroy(png_ptr, end_info_ptr);
G
Guy Schalnat 已提交
1025

1026 1027 1028 1029
#ifdef PNG_READ_GAMMA_SUPPORTED
   png_destroy_gamma_table(png_ptr);
#endif

A
Andreas Dilger 已提交
1030
   png_free(png_ptr, png_ptr->zbuf);
1031
   png_free(png_ptr, png_ptr->big_row_buf);
1032
   png_free(png_ptr, png_ptr->big_prev_row);
1033
   png_free(png_ptr, png_ptr->chunkdata);
1034

1035
#ifdef PNG_READ_QUANTIZE_SUPPORTED
A
Andreas Dilger 已提交
1036
   png_free(png_ptr, png_ptr->palette_lookup);
1037
   png_free(png_ptr, png_ptr->quantize_index);
G
Guy Schalnat 已提交
1038
#endif
1039

1040
   if (png_ptr->free_me & PNG_FREE_PLTE)
1041
      png_zfree(png_ptr, png_ptr->palette);
1042
   png_ptr->free_me &= ~PNG_FREE_PLTE;
1043

1044
#if defined(PNG_tRNS_SUPPORTED) || \
1045
    defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
1046
   if (png_ptr->free_me & PNG_FREE_TRNS)
1047
      png_free(png_ptr, png_ptr->trans_alpha);
1048
   png_ptr->free_me &= ~PNG_FREE_TRNS;
1049
#endif
1050

1051
#ifdef PNG_READ_hIST_SUPPORTED
1052
   if (png_ptr->free_me & PNG_FREE_HIST)
A
Andreas Dilger 已提交
1053
      png_free(png_ptr, png_ptr->hist);
1054
   png_ptr->free_me &= ~PNG_FREE_HIST;
G
Guy Schalnat 已提交
1055
#endif
1056

A
Andreas Dilger 已提交
1057
   inflateEnd(&png_ptr->zstream);
1058

G
Guy Schalnat 已提交
1059
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
A
Andreas Dilger 已提交
1060
   png_free(png_ptr, png_ptr->save_buffer);
G
Guy Schalnat 已提交
1061
#endif
G
Guy Schalnat 已提交
1062

1063 1064 1065 1066 1067 1068
#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 已提交
1069 1070 1071
   /* Save the important info out of the png_struct, in case it is
    * being used again.
    */
1072
#ifdef PNG_SETJMP_SUPPORTED
1073
   png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
1074
#endif
G
Guy Schalnat 已提交
1075 1076

   error_fn = png_ptr->error_fn;
1077
#ifdef PNG_WARNINGS_SUPPORTED
G
Guy Schalnat 已提交
1078
   warning_fn = png_ptr->warning_fn;
1079
#endif
G
Guy Schalnat 已提交
1080
   error_ptr = png_ptr->error_ptr;
1081 1082 1083
#ifdef PNG_USER_MEM_SUPPORTED
   free_fn = png_ptr->free_fn;
#endif
G
Guy Schalnat 已提交
1084

1085
   png_memset(png_ptr, 0, png_sizeof(png_struct));
G
Guy Schalnat 已提交
1086 1087

   png_ptr->error_fn = error_fn;
1088
#ifdef PNG_WARNINGS_SUPPORTED
G
Guy Schalnat 已提交
1089
   png_ptr->warning_fn = warning_fn;
1090
#endif
G
Guy Schalnat 已提交
1091
   png_ptr->error_ptr = error_ptr;
1092 1093 1094
#ifdef PNG_USER_MEM_SUPPORTED
   png_ptr->free_fn = free_fn;
#endif
G
Guy Schalnat 已提交
1095

1096
#ifdef PNG_SETJMP_SUPPORTED
1097
   png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf));
1098 1099
#endif

G
Guy Schalnat 已提交
1100
}
1101

1102
void PNGAPI
1103 1104
png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
{
1105 1106
   if (png_ptr == NULL)
      return;
1107

1108 1109
   png_ptr->read_row_fn = read_row_fn;
}
1110

1111

1112
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
1113
#ifdef PNG_INFO_IMAGE_SUPPORTED
1114 1115
void PNGAPI
png_read_png(png_structp png_ptr, png_infop info_ptr,
1116 1117 1118 1119 1120
                           int transforms,
                           voidp params)
{
   int row;

1121
   if (png_ptr == NULL || info_ptr == NULL)
1122
      return;
1123

1124
   /* png_read_info() gives us all of the information from the
1125 1126 1127
    * PNG file before the first IDAT (image data chunk).
    */
   png_read_info(png_ptr, info_ptr);
1128 1129
   if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
      png_error(png_ptr, "Image is too high to process with png_read_png()");
1130 1131 1132

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

1133
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
1134
   /* Tell libpng to strip 16-bit/color files down to 8 bits per color.
1135
    */
1136
   if (transforms & PNG_TRANSFORM_SCALE_16)
1137
   {
1138 1139 1140
     /* Added at libpng-1.5.4. "strip_16" produces the same result that it
      * did in earlier versions, while "scale_16" is now more accurate.
      */
1141 1142 1143 1144 1145
      png_set_scale_16(png_ptr);
   }
#endif

#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
1146 1147 1148 1149 1150 1151
   /* If both SCALE and STRIP are required pngrtran will effectively cancel the
    * latter by doing SCALE first.  This is ok and allows apps not to check for
    * which is supported to get the right answer.
    */
   if (transforms & PNG_TRANSFORM_STRIP_16)
      png_set_strip_16(png_ptr);
1152 1153
#endif

1154
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
1155 1156
   /* Strip alpha bytes from the input data without combining with
    * the background (not recommended).
1157 1158
    */
   if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
1159
      png_set_strip_alpha(png_ptr);
1160 1161
#endif

1162
#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
1163
   /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single
1164 1165 1166
    * byte into separate bytes (useful for paletted and grayscale images).
    */
   if (transforms & PNG_TRANSFORM_PACKING)
1167
      png_set_packing(png_ptr);
1168 1169
#endif

1170
#ifdef PNG_READ_PACKSWAP_SUPPORTED
1171
   /* Change the order of packed pixels to least significant bit first
1172 1173
    * (not useful if you are using png_set_packing).
    */
1174
   if (transforms & PNG_TRANSFORM_PACKSWAP)
1175
      png_set_packswap(png_ptr);
1176 1177
#endif

1178
#ifdef PNG_READ_EXPAND_SUPPORTED
1179 1180 1181 1182 1183 1184
   /* 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)
1185 1186 1187
      if ((png_ptr->bit_depth < 8) ||
          (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
          (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
1188
         png_set_expand(png_ptr);
1189 1190
#endif

1191
   /* We don't handle background color or gamma transformation or quantizing.
1192
    */
1193

1194
#ifdef PNG_READ_INVERT_SUPPORTED
1195
   /* Invert monochrome files to have 0 as white and 1 as black
1196
    */
1197
   if (transforms & PNG_TRANSFORM_INVERT_MONO)
1198
      png_set_invert_mono(png_ptr);
1199 1200
#endif

1201
#ifdef PNG_READ_SHIFT_SUPPORTED
1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215
   /* 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

1216
#ifdef PNG_READ_BGR_SUPPORTED
1217
   /* Flip the RGB pixels to BGR (or RGBA to BGRA) */
1218
   if (transforms & PNG_TRANSFORM_BGR)
1219
      png_set_bgr(png_ptr);
1220 1221
#endif

1222
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
1223
   /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
1224
   if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
1225
      png_set_swap_alpha(png_ptr);
1226 1227
#endif

1228
#ifdef PNG_READ_SWAP_SUPPORTED
1229
   /* Swap bytes of 16-bit files to least significant byte first */
1230
   if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
1231
      png_set_swap(png_ptr);
1232 1233
#endif

1234
/* Added at libpng-1.2.41 */
1235
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
1236
   /* Invert the alpha channel from opacity to transparency */
1237
   if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
1238
      png_set_invert_alpha(png_ptr);
1239 1240
#endif

1241
/* Added at libpng-1.2.41 */
1242
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
1243
   /* Expand grayscale image to RGB */
1244
   if (transforms & PNG_TRANSFORM_GRAY_TO_RGB)
1245
      png_set_gray_to_rgb(png_ptr);
1246 1247
#endif

1248
/* Added at libpng-1.5.4 */
1249 1250 1251 1252 1253
#ifdef PNG_READ_EXPAND_16_SUPPORTED
   if (transforms & PNG_TRANSFORM_EXPAND_16)
      png_set_expand_16(png_ptr);
#endif

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

1256 1257 1258 1259 1260
   /* We use png_read_image and rely on that for interlace handling, but we also
    * call png_read_update_info therefore must turn on interlace handling now:
    */
   (void)png_set_interlace_handling(png_ptr);

1261 1262
   /* Optional call to gamma correct and add the background to the palette
    * and update info structure.  REQUIRED if you are expecting libpng to
1263
    * update the palette for you (i.e., you selected such a transform above).
1264 1265 1266 1267 1268
    */
   png_read_update_info(png_ptr, info_ptr);

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

1269
   png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
1270
   if (info_ptr->row_pointers == NULL)
1271
   {
1272
      png_uint_32 iptr;
1273

1274
      info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
1275
          info_ptr->height * png_sizeof(png_bytep));
1276 1277 1278
      for (iptr=0; iptr<info_ptr->height; iptr++)
         info_ptr->row_pointers[iptr] = NULL;

1279
      info_ptr->free_me |= PNG_FREE_ROWS;
1280

1281
      for (row = 0; row < (int)info_ptr->height; row++)
1282
         info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
1283
            png_get_rowbytes(png_ptr, info_ptr));
1284
   }
1285 1286 1287 1288

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

1289
   /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
1290
   png_read_end(png_ptr, info_ptr);
1291

1292 1293
   PNG_UNUSED(transforms)   /* Quiet compiler warnings */
   PNG_UNUSED(params)
1294

1295
}
1296
#endif /* PNG_INFO_IMAGE_SUPPORTED */
1297
#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
1298 1299 1300 1301 1302 1303 1304 1305

#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
/* SIMPLIFIED READ
 *
 * This code currently relies on the sequential reader, though it could easily
 * be made to work with the progressive one.
 */
/* Do all the *safe* initialization - 'safe' means that png_error won't be
1306 1307 1308
 * called, so setting up the jmp_buf is not required.  This means that anything
 * called from here must *not* call png_malloc - it has to call png_malloc_warn
 * instead so that control is returned safely back to this routine.
1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321
 */
static int
png_image_read_init(png_imagep image)
{
   png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image,
          png_safe_error, png_safe_warning);

   if (png_ptr != NULL)
   {
      png_infop info_ptr = png_create_info_struct(png_ptr);

      if (info_ptr != NULL)
      {
1322 1323
         png_controlp control = png_voidcast(png_controlp,
            png_malloc_warn(png_ptr, sizeof *control));
1324 1325 1326

         if (control != NULL)
         {
1327
            png_memset(control, 0, sizeof *control);
1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374

            control->png_ptr = png_ptr;
            control->info_ptr = info_ptr;
            control->for_write = 0;

            image->opaque = control;
            return 1;
         }

         /* Error clean up */
         png_destroy_info_struct(png_ptr, &info_ptr);
      }

      png_destroy_read_struct(&png_ptr, NULL, NULL);
   }

   return png_image_error(image, "png_image_read: out of memory");
}

/* Utility to find the base format of a PNG file from a png_struct. */
static png_uint_32
png_image_format(png_structp png_ptr, png_infop info_ptr)
{
   png_uint_32 format = 0;

   if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
      format |= PNG_FORMAT_FLAG_COLOR;

   if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      format |= PNG_FORMAT_FLAG_ALPHA;

   else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
      format |= PNG_FORMAT_FLAG_ALPHA;

   if (png_ptr->bit_depth == 16)
      format |= PNG_FORMAT_FLAG_LINEAR;

   return format;
}

/* Do the main body of a 'png_image_begin_read' function; read the PNG file
 * header and fill in all the information.  This is executed in a safe context,
 * unlike the init routine above.
 */
static int
png_image_read_header(png_voidp argument)
{
1375
   png_imagep image = png_voidcast(png_imagep, argument);
1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396
   png_structp png_ptr = image->opaque->png_ptr;
   png_infop info_ptr = image->opaque->info_ptr;

   png_read_info(png_ptr, info_ptr);

   /* Do this the fast way; just read directly out of png_struct. */
   image->width = png_ptr->width;
   image->height = png_ptr->height;

   {
      png_uint_32 format = png_image_format(png_ptr, info_ptr);

      image->format = format;
      image->flags = 0;

      /* Now try to work out whether the color data does not match sRGB. */
      if ((format & PNG_FORMAT_FLAG_COLOR) != 0 &&
         (info_ptr->valid & PNG_INFO_sRGB) == 0)
      {
         /* gamma is irrelevant because libpng does gamma correction, what
          * matters is if the cHRM chunk doesn't match or, in the absence of
1397
          * cRHM, if the iCCP profile appears to have different end points.
1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417
          */
         if (info_ptr->valid & PNG_INFO_cHRM)
         {
            /* TODO: this is a copy'n'paste from pngrutil.c, make a common
             * checking function.  This checks for a 1% error.
             */
            /* The cHRM chunk is used in preference to iCCP */
            if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270,  1000) ||
                PNG_OUT_OF_RANGE(info_ptr->y_white, 32900,  1000) ||
                PNG_OUT_OF_RANGE(info_ptr->x_red,   64000,  1000) ||
                PNG_OUT_OF_RANGE(info_ptr->y_red,   33000,  1000) ||
                PNG_OUT_OF_RANGE(info_ptr->x_green, 30000,  1000) ||
                PNG_OUT_OF_RANGE(info_ptr->y_green, 60000,  1000) ||
                PNG_OUT_OF_RANGE(info_ptr->x_blue,  15000,  1000) ||
                PNG_OUT_OF_RANGE(info_ptr->y_blue,   6000,  1000))
               image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
         }

         else if (info_ptr->valid & PNG_INFO_iCCP)
         {
1418 1419 1420
#        if 0
            /* TODO: IMPLEMENT THIS! Remember to remove iCCP from
                 the chunks_to_ignore list */
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498
            /* Here if we just have an iCCP chunk. */
            if (!png_iCCP_is_sRGB(png_ptr, info_ptr))
#        endif
               image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
         }
      }
   }

   return 1;
}

#ifdef PNG_STDIO_SUPPORTED
int PNGAPI
png_image_begin_read_from_stdio(png_imagep image, FILE* file)
{
   if (image != NULL)
   {
      if (file != NULL)
      {
         if (png_image_read_init(image))
         {
            /* This is slightly evil, but png_init_io doesn't do anything other
             * than this and we haven't changed the standard IO functions so
             * this saves a 'safe' function.
             */
            image->opaque->png_ptr->io_ptr = file;
            return png_safe_execute(image, png_image_read_header, image);
         }
      }

      else
         return png_image_error(image,
            "png_image_begin_read_from_stdio: invalid argument");
   }

   return 0;
}

int PNGAPI
png_image_begin_read_from_file(png_imagep image, const char *file_name)
{
   if (image != NULL)
   {
      if (file_name != NULL)
      {
         FILE *fp = fopen(file_name, "rb");

         if (fp != NULL)
         {
            if (png_image_read_init(image))
            {
               image->opaque->png_ptr->io_ptr = fp;
               image->opaque->owned_file = 1;
               return png_safe_execute(image, png_image_read_header, image);
            }

            /* Clean up: just the opened file. */
            (void)fclose(fp);
         }

         else
            return png_image_error(image, strerror(errno));
      }

      else
         return png_image_error(image,
            "png_image_begin_read_from_file: invalid argument");
   }

   return 0;
}
#endif /* PNG_STDIO_SUPPORTED */

static void PNGCBAPI
png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need)
{
   if (png_ptr != NULL)
   {
1499
      png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr);
1500 1501 1502 1503 1504 1505 1506 1507 1508 1509
      if (image != NULL)
      {
         png_controlp cp = image->opaque;
         if (cp != NULL)
         {
            png_const_bytep memory = cp->memory;
            png_size_t size = cp->size;

            if (memory != NULL && size >= need)
            {
1510
               png_memcpy(out, memory, need);
1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536
               cp->memory = memory + need;
               cp->size = size - need;
               return;
            }

            png_error(png_ptr, "read beyond end of data");
         }
      }

      png_error(png_ptr, "invalid memory read");
   }
}

int PNGAPI png_image_begin_read_from_memory(png_imagep image,
   png_const_voidp memory, png_size_t size)
{
   if (image != NULL)
   {
      if (memory != NULL && size > 0)
      {
         if (png_image_read_init(image))
         {
            /* Now set the IO functions to read from the memory buffer and
             * store it into io_ptr.  Again do this in-place to avoid calling a
             * libpng function that requires error handling.
             */
1537
            image->opaque->memory = png_voidcast(png_const_bytep, memory);
1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571
            image->opaque->size = size;
            image->opaque->png_ptr->io_ptr = image;
            image->opaque->png_ptr->read_data_fn = png_image_memory_read;

            return png_safe_execute(image, png_image_read_header, image);
         }
      }

      else
         return png_image_error(image,
            "png_image_begin_read_from_memory: invalid argument");
   }

   return 0;
}

/* Arguments to png_image_finish_read: */
typedef struct
{
   /* Arguments: */
   png_imagep image;
   png_voidp  buffer;
   png_int_32 row_stride;
   png_colorp background;
   /* Local variables: */
   png_bytep  local_row;
   png_bytep  first_row;
   ptrdiff_t  row_bytes; /* unsigned arithmetic step between rows */
} png_image_read_control;

/* Just the row reading part of png_image_read. */
static int
png_image_read_composite(png_voidp argument)
{
1572 1573
   png_image_read_control *display = png_voidcast(png_image_read_control*,
      argument);
1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613
   png_imagep image = display->image;
   png_structp png_ptr = image->opaque->png_ptr;
   png_byte interlace_type = png_ptr->interlaced;
   int passes;

   switch (interlace_type)
   {
      case PNG_INTERLACE_NONE:
         passes = 1;
         break;

      case PNG_INTERLACE_ADAM7:
         passes = PNG_INTERLACE_ADAM7_PASSES;
         break;

      default:
         png_error(png_ptr, "unknown interlace type");
   }

   {
      png_uint_32 height = image->height;
      png_uint_32 width = image->width;
      unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1;
      int pass;

      for (pass = 0; pass < passes; ++pass)
      {
         png_bytep        row = display->first_row;
         unsigned int     startx, stepx, stepy;
         png_uint_32      y;

         if (interlace_type == PNG_INTERLACE_ADAM7)
         {
            /* The row may be empty for a short image: */
            if (PNG_PASS_COLS(width, pass) == 0)
               continue;

            startx = PNG_PASS_START_COL(pass);
            stepx = PNG_PASS_COL_OFFSET(pass);
            y = PNG_PASS_START_ROW(pass);
1614
            stepy = PNG_PASS_ROW_OFFSET(pass);
1615 1616 1617 1618 1619 1620 1621 1622
         }

         else
         {
            y = 0;
            startx = 0;
            stepx = stepy = 1;
         }
1623 1624 1625 1626

         /* The following are invariants across all the rows: */
         startx *= channels;
         stepx *= channels;
1627 1628 1629 1630
         
         for (; y<height; y += stepy)
            {
               png_bytep inrow = display->local_row;
1631 1632
               png_bytep outrow = row + startx;
               png_const_bytep end_row = row + width * channels;
1633 1634 1635 1636 1637

               /* Read the row, which is packed: */
               png_read_row(png_ptr, inrow, NULL);

               /* Now do the composition on each pixel in this row. */
1638
               for (; outrow < end_row; outrow += stepx)
1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661
               {
                  png_byte alpha = inrow[channels];

                  if (alpha > 0) /* else no change to the output */
                  {
                     unsigned int c;

                     for (c=0; c<channels; ++c)
                     {
                        png_uint_32 component = inrow[c];

                        if (alpha < 255) /* else just use component */
                        {
                           /* This is PNG_OPTIMIZED_ALPHA, the component value
                            * is a linear 8-bit value.  Combine this with the
                            * current outrow[c] value which is sRGB encoded.
                            * Arithmetic here is 16-bits to preserve the output
                            * values correctly.
                            */
                           component *= 257*255; /* =65535 */
                           component += (255-alpha)*png_sRGB_table[outrow[c]];

                           /* So 'component' is scaled by 255*65535 and is
1662
                            * therefore appropriate for the sRGB to linear
1663
                            * conversion table.
1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682
                            */
                           component = PNG_sRGB_FROM_LINEAR(component);
                        }

                        outrow[c] = (png_byte)component;
                     }
                  }

                  inrow += channels+1; /* components and alpha channel */
               }

               row += display->row_bytes;
            }
      }
   }

   return 1;
}

1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698
/* The do_local_background case; called when all the following transforms are to
 * be done:
 *
 * PNG_RGB_TO_GRAY
 * PNG_COMPOSITE
 * PNG_GAMMA
 *
 * This is a work-round for the fact that both the PNG_RGB_TO_GRAY and
 * PNG_COMPOSITE code performs gamma correction, so we get double gamma
 * correction.  The fix-up is to prevent the PNG_COMPOSITE operation happening
 * inside libpng, so this routine sees an 8 or 16-bit gray+alpha row and handles
 * the removal or pre-multiplication of the alpha channel.
 */
static int
png_image_read_background(png_voidp argument)
{
1699 1700
   png_image_read_control *display = png_voidcast(png_image_read_control*,
      argument);
1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832 1833 1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845 1846 1847 1848 1849 1850 1851 1852 1853 1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953
   png_imagep image = display->image;
   png_structp png_ptr = image->opaque->png_ptr;
   png_infop info_ptr = image->opaque->info_ptr;
   png_byte interlace_type = png_ptr->interlaced;
   png_uint_32 height = image->height;
   png_uint_32 width = image->width;
   int pass, passes;

   /* Double check the convoluted logic below.  We expect to get here with
    * libpng doing rgb to gray and gamma correction but background processing
    * left to the png_image_read_background function.  The rows libpng produce
    * might be 8 or 16-bit but should always have two channels; gray plus alpha.
    */
   if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
      png_error(png_ptr, "lost rgb to gray");

   if ((png_ptr->transformations & PNG_COMPOSE) != 0)
      png_error(png_ptr, "unexpected compose");

   /* The palette code zaps PNG_GAMMA in place... */
   if ((png_ptr->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
      (png_ptr->transformations & PNG_GAMMA) == 0)
      png_error(png_ptr, "lost gamma correction");

   if (png_get_channels(png_ptr, info_ptr) != 2)
      png_error(png_ptr, "lost/gained channels");

   switch (interlace_type)
   {
      case PNG_INTERLACE_NONE:
         passes = 1;
         break;

      case PNG_INTERLACE_ADAM7:
         passes = PNG_INTERLACE_ADAM7_PASSES;
         break;

      default:
         png_error(png_ptr, "unknown interlace type");
   }

   switch (png_get_bit_depth(png_ptr, info_ptr))
   {
      default:
         png_error(png_ptr, "unexpected bit depth");
         break;

      case 8:
         /* 8-bit sRGB gray values with an alpha channel; the alpha channel is
          * to be removed by composing on a backgroundi: either the row if
          * display->background is NULL or display->background.green if not.
          * Unlike the code above ALPHA_OPTIMIZED has *not* been done.
          */
         for (pass = 0; pass < passes; ++pass)
         {
            png_bytep        row = display->first_row;
            unsigned int     startx, stepx, stepy;
            png_uint_32      y;

            if (interlace_type == PNG_INTERLACE_ADAM7)
            {
               /* The row may be empty for a short image: */
               if (PNG_PASS_COLS(width, pass) == 0)
                  continue;

               startx = PNG_PASS_START_COL(pass);
               stepx = PNG_PASS_COL_OFFSET(pass);
               y = PNG_PASS_START_ROW(pass);
               stepy = PNG_PASS_ROW_OFFSET(pass);
            }

            else
            {
               y = 0;
               startx = 0;
               stepx = stepy = 1;
            }
            
            if (display->background == NULL)
            {
               for (; y<height; y += stepy)
                  {
                     png_bytep inrow = display->local_row;
                     png_bytep outrow = row + startx;
                     png_const_bytep end_row = row + width;

                     /* Read the row, which is packed: */
                     png_read_row(png_ptr, inrow, NULL);

                     /* Now do the composition on each pixel in this row. */
                     for (; outrow < end_row; outrow += stepx)
                     {
                        png_byte alpha = inrow[1];

                        if (alpha > 0) /* else no change to the output */
                        {
                           png_uint_32 component = inrow[0];

                           if (alpha < 255) /* else just use component */
                           {
                              /* Since PNG_OPTIMIZED_ALPHA was not set it is
                               * necessary to invert the sRGB transfer
                               * function and multiply the alpha out.
                               */
                              component = png_sRGB_table[component] * alpha;
                              component += png_sRGB_table[outrow[0]] *
                                 (255-alpha);
                              component = PNG_sRGB_FROM_LINEAR(component);
                           }

                           outrow[0] = (png_byte)component;
                        }

                        inrow += 2; /* gray and alpha channel */
                     }

                     row += display->row_bytes;
                  }
            }

            else /* constant background value */
            {
               png_byte background8 = display->background->green;
               png_uint_16 background = png_sRGB_table[background8];

               for (; y<height; y += stepy)
                  {
                     png_bytep inrow = display->local_row;
                     png_bytep outrow = row + startx;
                     png_const_bytep end_row = row + width;

                     /* Read the row, which is packed: */
                     png_read_row(png_ptr, inrow, NULL);

                     /* Now do the composition on each pixel in this row. */
                     for (; outrow < end_row; outrow += stepx)
                     {
                        png_byte alpha = inrow[1];

                        if (alpha > 0) /* else use background */
                        {
                           png_uint_32 component = inrow[0];

                           if (alpha < 255) /* else just use component */
                           {
                              component = png_sRGB_table[component] * alpha;
                              component += background * (255-alpha);
                              component = PNG_sRGB_FROM_LINEAR(component);
                           }

                           outrow[0] = (png_byte)component;
                        }

                        else
                           outrow[0] = background8;

                        inrow += 2; /* gray and alpha channel */
                     }

                     row += display->row_bytes;
                  }
            }
         }
         break;

      case 16:
         /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must
          * still be done and, maybe, the alpha channel removed.  This code also
          * handles the alpha-first option.
          */
         {
            unsigned int outchannels = png_get_channels(png_ptr, info_ptr);
            int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
            int swap_alpha = 0;

            if (preserve_alpha && (image->format & PNG_FORMAT_FLAG_AFIRST))
               swap_alpha = 1;

            for (pass = 0; pass < passes; ++pass)
            {
               png_uint_16p     row = (png_uint_16p)display->first_row;
               unsigned int     startx, stepx, stepy; /* all in pixels */
               png_uint_32      y;

               if (interlace_type == PNG_INTERLACE_ADAM7)
               {
                  /* The row may be empty for a short image: */
                  if (PNG_PASS_COLS(width, pass) == 0)
                     continue;

                  startx = PNG_PASS_START_COL(pass);
                  stepx = PNG_PASS_COL_OFFSET(pass);
                  y = PNG_PASS_START_ROW(pass);
                  stepy = PNG_PASS_ROW_OFFSET(pass);
               }

               else
               {
                  y = 0;
                  startx = 0;
                  stepx = stepy = 1;
               }

               startx *= outchannels;
               stepx *= outchannels;
               
               for (; y<height; y += stepy)
                  {
                     png_uint_16p inrow;
                     png_uint_16p outrow = row + startx;
                     png_uint_16p end_row = row + width * outchannels;

                     /* Read the row, which is packed: */
                     png_read_row(png_ptr, display->local_row, NULL);
                     inrow = (png_uint_16p)display->local_row;

                     /* Now do the pre-multiplication on each pixel in this row.
                      */
                     for (; outrow < end_row; outrow += stepx)
                     {
                        png_uint_32 component = inrow[0];
                        png_uint_16 alpha = inrow[1];

                        if (alpha > 0) /* else 0 */
                        {
                           if (alpha < 65535) /* else just use component */
                           {
                              component *= alpha;
                              component += 32767;
                              component /= 65535;
                           }
                        }

                        else
                           component = 0;

                        outrow[swap_alpha] = (png_uint_16)component;
                        if (outchannels > 1)
                           outrow[1 ^ swap_alpha] = alpha;

                        inrow += 2; /* components and alpha channel */
                     }

                     row += display->row_bytes;
                  }
            }
         }
         break;
   }

   return 1;
}

1954 1955 1956 1957
/* The guts of png_image_finish_read as a png_safe_execute callback. */
static int
png_image_read_end(png_voidp argument)
{
1958 1959
   png_image_read_control *display = png_voidcast(png_image_read_control*,
      argument);
1960 1961 1962 1963 1964 1965 1966
   png_imagep image = display->image;
   png_structp png_ptr = image->opaque->png_ptr;
   png_infop info_ptr = image->opaque->info_ptr;

   png_uint_32 format = image->format;
   int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
   int do_local_compose = 0;
1967
   int do_local_background = 0; /* to avoid double gamma correction bug */
1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979
   int passes = 0;

   /* Add transforms to ensure the correct output format is produced then check
    * that the required implementation support is there.  Always expand; always
    * need 8 bits minimum, no palette and expanded tRNS.
    */
   png_set_expand(png_ptr);
   
   /* Now check the format to see if it was modified. */
   {
      png_uint_32 base_format = png_image_format(png_ptr, info_ptr);
      png_uint_32 change = format ^ base_format;
1980 1981
      png_fixed_point output_gamma;
      int mode; /* alpha mode */
1982

1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
      /* Do this first so that we have a record if rgb to gray is happening. */
      if (change & PNG_FORMAT_FLAG_COLOR)
      {
         /* gray<->color transformation required. */
         if (format & PNG_FORMAT_FLAG_COLOR)
            png_set_gray_to_rgb(png_ptr);

         else
         {
            /* libpng can't do both rgb to gray and
             * background/pre-multiplication if there is also significant gamma
             * correction, because both operations require linear colors and
             * the code only supports one transform doing the gamma correction.
             * Handle this by doing the pre-multiplication or background
             * operation in this code, if necessary.
             *
             * TODO: fix this by rewriting pngrtran.c (!)
             *
             * For the moment (given that fixing this in pngrtran.c is an
             * enormous change) 'do_local_background' is used to indicate that
             * the problem exists.
             */
            if (base_format & PNG_FORMAT_FLAG_ALPHA)
               do_local_background = 1/*maybe*/;

            png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,
               PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
         }

         change &= ~PNG_FORMAT_FLAG_COLOR;
      }

2015 2016 2017
      /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.
       */
      {
2018
         png_fixed_point input_gamma_default;
2019 2020 2021 2022 2023 2024

         if (base_format & PNG_FORMAT_FLAG_LINEAR)
            input_gamma_default = PNG_GAMMA_LINEAR;
         else
            input_gamma_default = PNG_DEFAULT_sRGB;

2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036
         /* Call png_set_alpha_mode to set the default for the input gamma; the
          * output gamma is set by a second call below.
          */
         png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default);
      }

      if (linear)
      {
         /* If there *is* an alpha channel in the input it must be multiplied
          * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG.
          */
         if (base_format & PNG_FORMAT_FLAG_ALPHA)
2037
            mode = PNG_ALPHA_STANDARD; /* associated alpha */
2038 2039 2040 2041

         else
            mode = PNG_ALPHA_PNG;

2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064
         output_gamma = PNG_GAMMA_LINEAR;
      }

      else
      {
         mode = PNG_ALPHA_PNG;
         output_gamma = PNG_DEFAULT_sRGB;
      }

      /* If 'do_local_background' is set check for the presence of gamma
       * correction; this is part of the work-round for the libpng bug
       * described above.
       *
       * TODO: fix libpng and remove this.
       */
      if (do_local_background)
      {
         png_fixed_point gtest;

         /* This is 'png_gamma_threshold' from pngrtran.c; the test used for
          * gamma correction, the screen gamma hasn't been set on png_struct
          * yet; it's set below.  png_struct::gamma, however, is set to the
          * final value.
2065
          */
2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076
         if (png_muldiv(&gtest, output_gamma, png_ptr->gamma, PNG_FP_1) &&
            !png_gamma_significant(gtest))
            do_local_background = 0;

         else if (mode == PNG_ALPHA_STANDARD)
         {
            do_local_background = 2/*required*/;
            mode = PNG_ALPHA_PNG; /* prevent libpng doing it */
         }

         /* else leave as 1 for the checks below */
2077
      }
2078

2079 2080 2081 2082 2083
      /* If the bit-depth changes then handle that here. */
      if (change & PNG_FORMAT_FLAG_LINEAR)
      {
         if (linear /*16-bit output*/)
            png_set_expand_16(png_ptr);
2084

2085 2086
         else /* 8-bit output */
            png_set_scale_16(png_ptr);
2087

2088
         change &= ~PNG_FORMAT_FLAG_LINEAR;
2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099
      }

      /* Now the background/alpha channel changes. */
      if (change & PNG_FORMAT_FLAG_ALPHA)
      {
         /* Removing an alpha channel requires composition for the 8-bit
          * formats; for the 16-bit it is already done, above, by the
          * pre-multiplication and the channel just needs to be stripped.
          */
         if (base_format & PNG_FORMAT_FLAG_ALPHA)
         {
2100 2101 2102 2103 2104 2105 2106 2107
            /* If RGB->gray is happening the alpha channel must be left and the
             * operation completed locally.
             *
             * TODO: fix libpng and remove this.
             */
            if (do_local_background)
               do_local_background = 2/*required*/;

2108
            /* 16-bit output: just remove the channel */
2109
            else if (linear) /* compose on black (well, pre-multiply) */
2110 2111
               png_set_strip_alpha(png_ptr);

2112
            /* 8-bit output: do an appropriate compose */
2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136
            else if (display->background != NULL)
            {
               png_color_16 c;

               c.index = 0; /*unused*/
               c.red = display->background->red;
               c.green = display->background->green;
               c.blue = display->background->blue;
               c.gray = display->background->green;

               /* This is always an 8-bit sRGB value, using the 'green' channel
                * for gray is much better than calculating the luminance here;
                * we can get off-by-one errors in that calculation relative to
                * the app expectations and that will show up in transparent
                * pixels.
                */
               png_set_background_fixed(png_ptr, &c,
                  PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
                  0/*gamma: not used*/);
            }

            else /* compose on row: implemented below. */
            {
               do_local_compose = 1;
2137
               /* This leaves the alpha channel in the output, so it has to be
2138 2139 2140 2141
                * removed by the code below.  Set the encoding to the 'OPTIMIZE'
                * one so the code only has to hack on the pixels that require
                * composition.
                */
2142
               mode = PNG_ALPHA_OPTIMIZED;
2143 2144 2145 2146 2147 2148
            }
         }

         else /* output needs an alpha channel */
         {
            /* This is tricky because it happens before the swap operation has
2149
             * been accomplished; however, the swap does *not* swap the added
2150 2151
             * alpha channel (weird API), so it must be added in the correct
             * place.
2152
             */
2153
            png_uint_32 filler; /* opaque filler */
2154
            int where;
2155 2156 2157 2158 2159 2160 2161

            if (linear)
               filler = 65535;

            else
               filler = 255;

2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173
#           ifdef PNG_FORMAT_AFIRST_SUPPORTED
               if (format & PNG_FORMAT_FLAG_AFIRST)
               {
                  where = PNG_FILLER_BEFORE;
                  change &= ~PNG_FORMAT_FLAG_AFIRST;
               }

               else
#           endif
               where = PNG_FILLER_AFTER;

            png_set_add_alpha(png_ptr, filler, where);
2174 2175
         }

2176
         /* This stops the (irrelevant) call to swap_alpha below. */
2177 2178 2179
         change &= ~PNG_FORMAT_FLAG_ALPHA;
      }

2180 2181 2182 2183 2184 2185
      /* Now set the alpha mode correctly; this is always done, even if there is
       * no alpha channel in either the input or the output because it correctly
       * sets the output gamma.
       */
      png_set_alpha_mode_fixed(png_ptr, mode, output_gamma);

2186
#     ifdef PNG_FORMAT_BGR_SUPPORTED
2187
         if (change & PNG_FORMAT_FLAG_BGR)
2188
         {
2189
            /* Check only the output format; PNG is never BGR; don't do this if
2190 2191 2192 2193 2194 2195 2196 2197 2198 2199 2200 2201 2202
             * the output is gray, but fix up the 'format' value in that case.
             */
            if (format & PNG_FORMAT_FLAG_COLOR)
               png_set_bgr(png_ptr);

            else
               format &= ~PNG_FORMAT_FLAG_BGR;

            change &= ~PNG_FORMAT_FLAG_BGR;
         }
#     endif

#     ifdef PNG_FORMAT_AFIRST_SUPPORTED
2203
         if (change & PNG_FORMAT_FLAG_AFIRST)
2204 2205 2206 2207 2208 2209 2210
         {
            /* Only relevant if there is an alpha channel - it's particularly
             * important to handle this correctly because do_local_compose may
             * be set above and then libpng will keep the alpha channel for this
             * code to remove.
             */
            if (format & PNG_FORMAT_FLAG_ALPHA)
2211 2212 2213 2214 2215 2216 2217
            {
               /* Disable this if doing a local background,
                * TODO: remove this when local background is no longer required.
                */
               if (do_local_background != 2)
                  png_set_swap_alpha(png_ptr);
            }
2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241

            else
               format &= ~PNG_FORMAT_FLAG_AFIRST;

            change &= ~PNG_FORMAT_FLAG_AFIRST;
         }
#     endif

      /* If the *output* is 16-bit then we need to check for a byte-swap on this
       * architecture.
       */
      if (linear)
      {
         PNG_CONST png_uint_16 le = 0x0001;

         if (*(png_const_bytep)&le)
            png_set_swap(png_ptr);
      }

      /* If change is not now 0 some transformation is missing - error out. */
      if (change)
         png_error(png_ptr, "png_read_image: unsupported transformation");
   }

2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282
#  ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
      /* Prepare the reader to ignore all recognized chunks whose data will not
       * be used, i.e., all chunks recognized by libpng except for those
       * involved in basic image reading:
       *
       *    IHDR, PLTE, IDAT, IEND
       *
       * Or image data handling:
       *
       *    tRNS, bKGD, gAMA, cHRM, sRGB, iCCP and sBIT.
       *
       * This provides a small performance improvement and eliminates any
       * potential vulnerability to security problems in the unused chunks.
       *
       * TODO: make it so that this is an explicit list to process, not a list
       * to ignore?
       */
      {
          static PNG_CONST png_byte chunks_to_ignore[] = {
              104,  73,  83,  84, '\0',  /* hIST */
              105,  84,  88, 116, '\0',  /* iTXt */
              111,  70,  70, 115, '\0',  /* oFFs */
              112,  67,  65,  76, '\0',  /* pCAL */
              112,  72,  89, 115, '\0',  /* pHYs */
              115,  67,  65,  76, '\0',  /* sCAL */
              115,  80,  76,  84, '\0',  /* sPLT */
              116,  69,  88, 116, '\0',  /* tEXt */
              116,  73,  77,  69, '\0',  /* tIME */
              122,  84,  88, 116, '\0'   /* zTXt */
          };

          /* Ignore unknown chunks */
          png_set_keep_unknown_chunks(png_ptr, 1 /* PNG_HANDLE_CHUNK_NEVER */,
            NULL, 0);

          /* Ignore known but unused chunks */
          png_set_keep_unknown_chunks(png_ptr, 1 /* PNG_HANDLE_CHUNK_NEVER */,
            chunks_to_ignore, (sizeof chunks_to_ignore)/5);
       }
#  endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */

2283
   /* Update the 'info' structure and make sure the result is as required; first
2284 2285
    * make sure to turn on the interlace handling if it will be required
    * (because it can't be turned on *after* the call to png_read_update_info!)
2286 2287
    *
    * TODO: remove the do_local_background fixup below.
2288
    */
2289
   if (!do_local_compose && do_local_background != 2)
2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301
      passes = png_set_interlace_handling(png_ptr);

   png_read_update_info(png_ptr, info_ptr);

   {
      png_uint_32 info_format = 0;

      if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
         info_format |= PNG_FORMAT_FLAG_COLOR;

      if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
      {
2302
         /* do_local_compose removes this channel below. */
2303
         if (!do_local_compose)
2304 2305 2306 2307 2308 2309
         {
            /* do_local_background does the same if required. */
            if (do_local_background != 2 ||
               (format & PNG_FORMAT_FLAG_ALPHA) != 0)
               info_format |= PNG_FORMAT_FLAG_ALPHA;
         }
2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323
      }

      else if (do_local_compose) /* internal error */
         png_error(png_ptr, "png_image_read: alpha channel lost");

      if (info_ptr->bit_depth == 16)
         info_format |= PNG_FORMAT_FLAG_LINEAR;

#     ifdef PNG_FORMAT_BGR_SUPPORTED
         if (png_ptr->transformations & PNG_BGR)
            info_format |= PNG_FORMAT_FLAG_BGR;
#     endif

#     ifdef PNG_FORMAT_AFIRST_SUPPORTED
2324 2325 2326
         if (png_ptr->transformations & PNG_SWAP_ALPHA ||
            ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&
            (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0))
2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340
            info_format |= PNG_FORMAT_FLAG_AFIRST;
#     endif

      /* This is actually an internal error. */
      if (info_format != format)
         png_error(png_ptr, "png_read_image: invalid transformations");
   }

   /* Now read the rows.  If do_local_compose is set then it is necessary to use
    * a local row buffer.  The output will be GA, RGBA or BGRA and must be
    * converted to G, RGB or BGR as appropriate.  The 'local_row' member of the
    * display acts as a flag.
    */
   {
2341
      png_bytep first_row = png_voidcast(png_bytep, display->buffer);
2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354 2355 2356 2357 2358 2359
      ptrdiff_t row_bytes = display->row_stride;

      if (linear)
         row_bytes *= sizeof (png_uint_16);

      /* The following expression is designed to work correctly whether it gives
       * a signed or an unsigned result.
       */
      if (row_bytes < 0)
         first_row += (image->height-1) * (-row_bytes);

      display->first_row = first_row;
      display->row_bytes = row_bytes;
   }

   if (do_local_compose)
   {
      int result;
2360 2361
      png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
         png_get_rowbytes(png_ptr, info_ptr)));
2362 2363 2364 2365 2366 2367 2368 2369 2370

      display->local_row = row;
      result = png_safe_execute(image, png_image_read_composite, display);
      display->local_row = NULL;
      png_free(png_ptr, row);

      return result;
   }

2371 2372 2373
   else if (do_local_background == 2)
   {
      int result;
2374 2375
      png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
         png_get_rowbytes(png_ptr, info_ptr)));
2376 2377 2378 2379 2380 2381 2382 2383 2384

      display->local_row = row;
      result = png_safe_execute(image, png_image_read_background, display);
      display->local_row = NULL;
      png_free(png_ptr, row);

      return result;
   }

2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412
   else
   {
      png_alloc_size_t row_bytes = display->row_bytes;

      while (--passes >= 0)
      {
         png_uint_32      y = image->height;
         png_bytep        row = display->first_row;
         
         while (y-- > 0)
         {
            png_read_row(png_ptr, row, NULL);
            row += row_bytes;
         }
      }

      return 1;
   }
}

int PNGAPI
png_image_finish_read(png_imagep image, png_colorp background, void *buffer,
   png_int_32 row_stride)
{
   if (image != NULL)
   {
      png_uint_32 check;

2413 2414 2415
      if (row_stride == 0)
         row_stride = PNG_IMAGE_ROW_STRIDE(*image);

2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426
      if (row_stride < 0)
         check = -row_stride;

      else
         check = row_stride;

      if (buffer != NULL && check >= PNG_IMAGE_ROW_STRIDE(*image))
      {
         int result;
         png_image_read_control display;

2427
         png_memset(&display, 0, sizeof display);
2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446
         display.image = image;
         display.buffer = buffer;
         display.row_stride = row_stride;
         display.background = background;
         display.local_row = NULL;
         result = png_safe_execute(image, png_image_read_end, &display);
         png_image_free(image);
         return result;
      }

      else
         return png_image_error(image,
            "png_image_finish_read: invalid argument");
   }

   return 0;
}

#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */
2447
#endif /* PNG_READ_SUPPORTED */