1 2 /* pngread.c - read a PNG file 3 * 4 * Last changed in libpng 1.2.44 [June 26, 2010] 5 * Copyright (c) 1998-2010 Glenn Randers-Pehrson 6 * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 7 * (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 * This file contains routines that an application calls directly to 14 * read a PNG file or stream. 15 */ 16 17 #define PNG_INTERNAL 18 #define PNG_NO_PEDANTIC_WARNINGS 19 #include "png.h" 20 #ifdef PNG_READ_SUPPORTED 21 22 23 /* Create a PNG structure for reading, and allocate any memory needed. */ 24 png_structp PNGAPI 25 png_create_read_struct(png_const_charp user_png_ver, png_voidp error_ptr, 26 png_error_ptr error_fn, png_error_ptr warn_fn) 27 { 28 29 #ifdef PNG_USER_MEM_SUPPORTED 30 return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn, 31 warn_fn, png_voidp_NULL, png_malloc_ptr_NULL, png_free_ptr_NULL)); 32 } 33 34 /* Alternate create PNG structure for reading, and allocate any memory 35 * needed. 36 */ 37 png_structp PNGAPI 38 png_create_read_struct_2(png_const_charp user_png_ver, png_voidp error_ptr, 39 png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, 40 png_malloc_ptr malloc_fn, png_free_ptr free_fn) 41 { 42 #endif /* PNG_USER_MEM_SUPPORTED */ 43 44 #ifdef PNG_SETJMP_SUPPORTED 45 volatile 46 #endif 47 png_structp png_ptr; 48 49 #ifdef PNG_SETJMP_SUPPORTED 50 #ifdef USE_FAR_KEYWORD 51 jmp_buf jmpbuf; 52 #endif 53 #endif 54 55 int i; 56 57 png_debug(1, "in png_create_read_struct"); 58 59 #ifdef PNG_USER_MEM_SUPPORTED 60 png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG, 61 (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr); 62 #else 63 png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); 64 #endif 65 if (png_ptr == NULL) 66 return (NULL); 67 68 /* Added at libpng-1.2.6 */ 69 #ifdef PNG_USER_LIMITS_SUPPORTED 70 png_ptr->user_width_max = PNG_USER_WIDTH_MAX; 71 png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; 72 # ifdef PNG_USER_CHUNK_CACHE_MAX 73 /* Added at libpng-1.2.43 and 1.4.0 */ 74 png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; 75 # endif 76 # ifdef PNG_SET_USER_CHUNK_MALLOC_MAX 77 /* Added at libpng-1.2.43 and 1.4.1 */ 78 png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; 79 # endif 80 #endif 81 82 #ifdef PNG_SETJMP_SUPPORTED 83 #ifdef USE_FAR_KEYWORD 84 if (setjmp(jmpbuf)) 85 #else 86 if (setjmp(png_ptr->jmpbuf)) 87 #endif 88 { 89 png_free(png_ptr, png_ptr->zbuf); 90 png_ptr->zbuf = NULL; 91 #ifdef PNG_USER_MEM_SUPPORTED 92 png_destroy_struct_2((png_voidp)png_ptr, 93 (png_free_ptr)free_fn, (png_voidp)mem_ptr); 94 #else 95 png_destroy_struct((png_voidp)png_ptr); 96 #endif 97 return (NULL); 98 } 99 #ifdef USE_FAR_KEYWORD 100 png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); 101 #endif 102 #endif /* PNG_SETJMP_SUPPORTED */ 103 104 #ifdef PNG_USER_MEM_SUPPORTED 105 png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn); 106 #endif 107 108 png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn); 109 110 if (user_png_ver) 111 { 112 i = 0; 113 do 114 { 115 if (user_png_ver[i] != png_libpng_ver[i]) 116 png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; 117 } while (png_libpng_ver[i++]); 118 } 119 else 120 png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; 121 122 123 if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) 124 { 125 /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so 126 * we must recompile any applications that use any older library version. 127 * For versions after libpng 1.0, we will be compatible, so we need 128 * only check the first digit. 129 */ 130 if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] || 131 (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) || 132 (user_png_ver[0] == '0' && user_png_ver[2] < '9')) 133 { 134 #if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) 135 char msg[80]; 136 if (user_png_ver) 137 { 138 png_snprintf(msg, 80, 139 "Application was compiled with png.h from libpng-%.20s", 140 user_png_ver); 141 png_warning(png_ptr, msg); 142 } 143 png_snprintf(msg, 80, 144 "Application is running with png.c from libpng-%.20s", 145 png_libpng_ver); 146 png_warning(png_ptr, msg); 147 #endif 148 #ifdef PNG_ERROR_NUMBERS_SUPPORTED 149 png_ptr->flags = 0; 150 #endif 151 png_error(png_ptr, 152 "Incompatible libpng version in application and library"); 153 } 154 } 155 156 /* Initialize zbuf - compression buffer */ 157 png_ptr->zbuf_size = PNG_ZBUF_SIZE; 158 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, 159 (png_uint_32)png_ptr->zbuf_size); 160 png_ptr->zstream.zalloc = png_zalloc; 161 png_ptr->zstream.zfree = png_zfree; 162 png_ptr->zstream.opaque = (voidpf)png_ptr; 163 164 switch (inflateInit(&png_ptr->zstream)) 165 { 166 case Z_OK: /* Do nothing */ break; 167 case Z_MEM_ERROR: 168 case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); 169 break; 170 case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); 171 break; 172 default: png_error(png_ptr, "Unknown zlib error"); 173 } 174 175 176 png_ptr->zstream.next_out = png_ptr->zbuf; 177 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 178 179 png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); 180 181 #ifdef PNG_SETJMP_SUPPORTED 182 /* Applications that neglect to set up their own setjmp() and then 183 encounter a png_error() will longjmp here. Since the jmpbuf is 184 then meaningless we abort instead of returning. */ 185 #ifdef USE_FAR_KEYWORD 186 if (setjmp(jmpbuf)) 187 PNG_ABORT(); 188 png_memcpy(png_ptr->jmpbuf, jmpbuf, png_sizeof(jmp_buf)); 189 #else 190 if (setjmp(png_ptr->jmpbuf)) 191 PNG_ABORT(); 192 #endif 193 #endif /* PNG_SETJMP_SUPPORTED */ 194 195 #ifdef PNG_INDEX_SUPPORTED 196 png_ptr->index = NULL; 197 #endif 198 199 return (png_ptr); 200 } 201 202 #if defined(PNG_1_0_X) || defined(PNG_1_2_X) 203 /* Initialize PNG structure for reading, and allocate any memory needed. 204 * This interface is deprecated in favour of the png_create_read_struct(), 205 * and it will disappear as of libpng-1.3.0. 206 */ 207 #undef png_read_init 208 void PNGAPI 209 png_read_init(png_structp png_ptr) 210 { 211 /* We only come here via pre-1.0.7-compiled applications */ 212 png_read_init_2(png_ptr, "1.0.6 or earlier", 0, 0); 213 } 214 215 void PNGAPI 216 png_read_init_2(png_structp png_ptr, png_const_charp user_png_ver, 217 png_size_t png_struct_size, png_size_t png_info_size) 218 { 219 /* We only come here via pre-1.0.12-compiled applications */ 220 if (png_ptr == NULL) 221 return; 222 #if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) 223 if (png_sizeof(png_struct) > png_struct_size || 224 png_sizeof(png_info) > png_info_size) 225 { 226 char msg[80]; 227 png_ptr->warning_fn = NULL; 228 if (user_png_ver) 229 { 230 png_snprintf(msg, 80, 231 "Application was compiled with png.h from libpng-%.20s", 232 user_png_ver); 233 png_warning(png_ptr, msg); 234 } 235 png_snprintf(msg, 80, 236 "Application is running with png.c from libpng-%.20s", 237 png_libpng_ver); 238 png_warning(png_ptr, msg); 239 } 240 #endif 241 if (png_sizeof(png_struct) > png_struct_size) 242 { 243 png_ptr->error_fn = NULL; 244 #ifdef PNG_ERROR_NUMBERS_SUPPORTED 245 png_ptr->flags = 0; 246 #endif 247 png_error(png_ptr, 248 "The png struct allocated by the application for reading is" 249 " too small."); 250 } 251 if (png_sizeof(png_info) > png_info_size) 252 { 253 png_ptr->error_fn = NULL; 254 #ifdef PNG_ERROR_NUMBERS_SUPPORTED 255 png_ptr->flags = 0; 256 #endif 257 png_error(png_ptr, 258 "The info struct allocated by application for reading is" 259 " too small."); 260 } 261 png_read_init_3(&png_ptr, user_png_ver, png_struct_size); 262 } 263 #endif /* PNG_1_0_X || PNG_1_2_X */ 264 265 void PNGAPI 266 png_read_init_3(png_structpp ptr_ptr, png_const_charp user_png_ver, 267 png_size_t png_struct_size) 268 { 269 #ifdef PNG_SETJMP_SUPPORTED 270 jmp_buf tmp_jmp; /* to save current jump buffer */ 271 #endif 272 273 int i = 0; 274 275 png_structp png_ptr=*ptr_ptr; 276 277 if (png_ptr == NULL) 278 return; 279 280 do 281 { 282 if (user_png_ver[i] != png_libpng_ver[i]) 283 { 284 #ifdef PNG_LEGACY_SUPPORTED 285 png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; 286 #else 287 png_ptr->warning_fn = NULL; 288 png_warning(png_ptr, 289 "Application uses deprecated png_read_init() and should be" 290 " recompiled."); 291 break; 292 #endif 293 } 294 } while (png_libpng_ver[i++]); 295 296 png_debug(1, "in png_read_init_3"); 297 298 #ifdef PNG_SETJMP_SUPPORTED 299 /* Save jump buffer and error functions */ 300 png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); 301 #endif 302 303 if (png_sizeof(png_struct) > png_struct_size) 304 { 305 png_destroy_struct(png_ptr); 306 *ptr_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG); 307 png_ptr = *ptr_ptr; 308 } 309 310 /* Reset all variables to 0 */ 311 png_memset(png_ptr, 0, png_sizeof(png_struct)); 312 313 #ifdef PNG_SETJMP_SUPPORTED 314 /* Restore jump buffer */ 315 png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); 316 #endif 317 318 /* Added at libpng-1.2.6 */ 319 #ifdef PNG_SET_USER_LIMITS_SUPPORTED 320 png_ptr->user_width_max = PNG_USER_WIDTH_MAX; 321 png_ptr->user_height_max = PNG_USER_HEIGHT_MAX; 322 #endif 323 324 /* Initialize zbuf - compression buffer */ 325 png_ptr->zbuf_size = PNG_ZBUF_SIZE; 326 png_ptr->zstream.zalloc = png_zalloc; 327 png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, 328 (png_uint_32)png_ptr->zbuf_size); 329 png_ptr->zstream.zalloc = png_zalloc; 330 png_ptr->zstream.zfree = png_zfree; 331 png_ptr->zstream.opaque = (voidpf)png_ptr; 332 333 switch (inflateInit(&png_ptr->zstream)) 334 { 335 case Z_OK: /* Do nothing */ break; 336 case Z_STREAM_ERROR: png_error(png_ptr, "zlib memory error"); break; 337 case Z_VERSION_ERROR: png_error(png_ptr, "zlib version error"); 338 break; 339 default: png_error(png_ptr, "Unknown zlib error"); 340 } 341 342 png_ptr->zstream.next_out = png_ptr->zbuf; 343 png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 344 345 png_set_read_fn(png_ptr, png_voidp_NULL, png_rw_ptr_NULL); 346 } 347 348 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 349 /* Read the information before the actual image data. This has been 350 * changed in v0.90 to allow reading a file that already has the magic 351 * bytes read from the stream. You can tell libpng how many bytes have 352 * been read from the beginning of the stream (up to the maximum of 8) 353 * via png_set_sig_bytes(), and we will only check the remaining bytes 354 * here. The application can then have access to the signature bytes we 355 * read if it is determined that this isn't a valid PNG file. 356 */ 357 void PNGAPI 358 png_read_info(png_structp png_ptr, png_infop info_ptr) 359 { 360 png_debug(1, "in png_read_info"); 361 362 if (png_ptr == NULL || info_ptr == NULL) 363 return; 364 365 /* If we haven't checked all of the PNG signature bytes, do so now. */ 366 if (png_ptr->sig_bytes < 8) 367 { 368 png_size_t num_checked = png_ptr->sig_bytes, 369 num_to_check = 8 - num_checked; 370 371 png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check); 372 png_ptr->sig_bytes = 8; 373 374 if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check)) 375 { 376 if (num_checked < 4 && 377 png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4)) 378 png_error(png_ptr, "Not a PNG file"); 379 else 380 png_error(png_ptr, "PNG file corrupted by ASCII conversion"); 381 } 382 if (num_checked < 3) 383 png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; 384 } 385 386 for (;;) 387 { 388 #ifdef PNG_USE_LOCAL_ARRAYS 389 PNG_CONST PNG_IHDR; 390 PNG_CONST PNG_IDAT; 391 PNG_CONST PNG_IEND; 392 PNG_CONST PNG_PLTE; 393 #ifdef PNG_READ_bKGD_SUPPORTED 394 PNG_CONST PNG_bKGD; 395 #endif 396 #ifdef PNG_READ_cHRM_SUPPORTED 397 PNG_CONST PNG_cHRM; 398 #endif 399 #ifdef PNG_READ_gAMA_SUPPORTED 400 PNG_CONST PNG_gAMA; 401 #endif 402 #ifdef PNG_READ_hIST_SUPPORTED 403 PNG_CONST PNG_hIST; 404 #endif 405 #ifdef PNG_READ_iCCP_SUPPORTED 406 PNG_CONST PNG_iCCP; 407 #endif 408 #ifdef PNG_READ_iTXt_SUPPORTED 409 PNG_CONST PNG_iTXt; 410 #endif 411 #ifdef PNG_READ_oFFs_SUPPORTED 412 PNG_CONST PNG_oFFs; 413 #endif 414 #ifdef PNG_READ_pCAL_SUPPORTED 415 PNG_CONST PNG_pCAL; 416 #endif 417 #ifdef PNG_READ_pHYs_SUPPORTED 418 PNG_CONST PNG_pHYs; 419 #endif 420 #ifdef PNG_READ_sBIT_SUPPORTED 421 PNG_CONST PNG_sBIT; 422 #endif 423 #ifdef PNG_READ_sCAL_SUPPORTED 424 PNG_CONST PNG_sCAL; 425 #endif 426 #ifdef PNG_READ_sPLT_SUPPORTED 427 PNG_CONST PNG_sPLT; 428 #endif 429 #ifdef PNG_READ_sRGB_SUPPORTED 430 PNG_CONST PNG_sRGB; 431 #endif 432 #ifdef PNG_READ_tEXt_SUPPORTED 433 PNG_CONST PNG_tEXt; 434 #endif 435 #ifdef PNG_READ_tIME_SUPPORTED 436 PNG_CONST PNG_tIME; 437 #endif 438 #ifdef PNG_READ_tRNS_SUPPORTED 439 PNG_CONST PNG_tRNS; 440 #endif 441 #ifdef PNG_READ_zTXt_SUPPORTED 442 PNG_CONST PNG_zTXt; 443 #endif 444 #endif /* PNG_USE_LOCAL_ARRAYS */ 445 png_uint_32 length = png_read_chunk_header(png_ptr); 446 PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; 447 448 /* This should be a binary subdivision search or a hash for 449 * matching the chunk name rather than a linear search. 450 */ 451 if (!png_memcmp(chunk_name, png_IDAT, 4)) 452 if (png_ptr->mode & PNG_AFTER_IDAT) 453 png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT; 454 455 if (!png_memcmp(chunk_name, png_IHDR, 4)) 456 png_handle_IHDR(png_ptr, info_ptr, length); 457 else if (!png_memcmp(chunk_name, png_IEND, 4)) 458 png_handle_IEND(png_ptr, info_ptr, length); 459 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 460 else if (png_handle_as_unknown(png_ptr, chunk_name)) 461 { 462 if (!png_memcmp(chunk_name, png_IDAT, 4)) 463 png_ptr->mode |= PNG_HAVE_IDAT; 464 png_handle_unknown(png_ptr, info_ptr, length); 465 if (!png_memcmp(chunk_name, png_PLTE, 4)) 466 png_ptr->mode |= PNG_HAVE_PLTE; 467 else if (!png_memcmp(chunk_name, png_IDAT, 4)) 468 { 469 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 470 png_error(png_ptr, "Missing IHDR before IDAT"); 471 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && 472 !(png_ptr->mode & PNG_HAVE_PLTE)) 473 png_error(png_ptr, "Missing PLTE before IDAT"); 474 break; 475 } 476 } 477 #endif 478 else if (!png_memcmp(chunk_name, png_PLTE, 4)) 479 png_handle_PLTE(png_ptr, info_ptr, length); 480 else if (!png_memcmp(chunk_name, png_IDAT, 4)) 481 { 482 if (!(png_ptr->mode & PNG_HAVE_IHDR)) 483 png_error(png_ptr, "Missing IHDR before IDAT"); 484 else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && 485 !(png_ptr->mode & PNG_HAVE_PLTE)) 486 png_error(png_ptr, "Missing PLTE before IDAT"); 487 488 png_ptr->idat_size = length; 489 png_ptr->mode |= PNG_HAVE_IDAT; 490 break; 491 } 492 #ifdef PNG_READ_bKGD_SUPPORTED 493 else if (!png_memcmp(chunk_name, png_bKGD, 4)) 494 png_handle_bKGD(png_ptr, info_ptr, length); 495 #endif 496 #ifdef PNG_READ_cHRM_SUPPORTED 497 else if (!png_memcmp(chunk_name, png_cHRM, 4)) 498 png_handle_cHRM(png_ptr, info_ptr, length); 499 #endif 500 #ifdef PNG_READ_gAMA_SUPPORTED 501 else if (!png_memcmp(chunk_name, png_gAMA, 4)) 502 png_handle_gAMA(png_ptr, info_ptr, length); 503 #endif 504 #ifdef PNG_READ_hIST_SUPPORTED 505 else if (!png_memcmp(chunk_name, png_hIST, 4)) 506 png_handle_hIST(png_ptr, info_ptr, length); 507 #endif 508 #ifdef PNG_READ_oFFs_SUPPORTED 509 else if (!png_memcmp(chunk_name, png_oFFs, 4)) 510 png_handle_oFFs(png_ptr, info_ptr, length); 511 #endif 512 #ifdef PNG_READ_pCAL_SUPPORTED 513 else if (!png_memcmp(chunk_name, png_pCAL, 4)) 514 png_handle_pCAL(png_ptr, info_ptr, length); 515 #endif 516 #ifdef PNG_READ_sCAL_SUPPORTED 517 else if (!png_memcmp(chunk_name, png_sCAL, 4)) 518 png_handle_sCAL(png_ptr, info_ptr, length); 519 #endif 520 #ifdef PNG_READ_pHYs_SUPPORTED 521 else if (!png_memcmp(chunk_name, png_pHYs, 4)) 522 png_handle_pHYs(png_ptr, info_ptr, length); 523 #endif 524 #ifdef PNG_READ_sBIT_SUPPORTED 525 else if (!png_memcmp(chunk_name, png_sBIT, 4)) 526 png_handle_sBIT(png_ptr, info_ptr, length); 527 #endif 528 #ifdef PNG_READ_sRGB_SUPPORTED 529 else if (!png_memcmp(chunk_name, png_sRGB, 4)) 530 png_handle_sRGB(png_ptr, info_ptr, length); 531 #endif 532 #ifdef PNG_READ_iCCP_SUPPORTED 533 else if (!png_memcmp(chunk_name, png_iCCP, 4)) 534 png_handle_iCCP(png_ptr, info_ptr, length); 535 #endif 536 #ifdef PNG_READ_sPLT_SUPPORTED 537 else if (!png_memcmp(chunk_name, png_sPLT, 4)) 538 png_handle_sPLT(png_ptr, info_ptr, length); 539 #endif 540 #ifdef PNG_READ_tEXt_SUPPORTED 541 else if (!png_memcmp(chunk_name, png_tEXt, 4)) 542 png_handle_tEXt(png_ptr, info_ptr, length); 543 #endif 544 #ifdef PNG_READ_tIME_SUPPORTED 545 else if (!png_memcmp(chunk_name, png_tIME, 4)) 546 png_handle_tIME(png_ptr, info_ptr, length); 547 #endif 548 #ifdef PNG_READ_tRNS_SUPPORTED 549 else if (!png_memcmp(chunk_name, png_tRNS, 4)) 550 png_handle_tRNS(png_ptr, info_ptr, length); 551 #endif 552 #ifdef PNG_READ_zTXt_SUPPORTED 553 else if (!png_memcmp(chunk_name, png_zTXt, 4)) 554 png_handle_zTXt(png_ptr, info_ptr, length); 555 #endif 556 #ifdef PNG_READ_iTXt_SUPPORTED 557 else if (!png_memcmp(chunk_name, png_iTXt, 4)) 558 png_handle_iTXt(png_ptr, info_ptr, length); 559 #endif 560 else 561 png_handle_unknown(png_ptr, info_ptr, length); 562 } 563 } 564 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 565 566 /* Optional call to update the users info_ptr structure */ 567 void PNGAPI 568 png_read_update_info(png_structp png_ptr, png_infop info_ptr) 569 { 570 png_debug(1, "in png_read_update_info"); 571 572 if (png_ptr == NULL) 573 return; 574 #ifdef PNG_INDEX_SUPPORTED 575 if (png_ptr->index) { 576 png_read_start_row(png_ptr); 577 } 578 #endif 579 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) 580 png_read_start_row(png_ptr); 581 else 582 png_warning(png_ptr, 583 "Ignoring extra png_read_update_info() call; row buffer not reallocated"); 584 585 png_read_transform_info(png_ptr, info_ptr); 586 } 587 588 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 589 /* Initialize palette, background, etc, after transformations 590 * are set, but before any reading takes place. This allows 591 * the user to obtain a gamma-corrected palette, for example. 592 * If the user doesn't call this, we will do it ourselves. 593 */ 594 void PNGAPI 595 png_start_read_image(png_structp png_ptr) 596 { 597 png_debug(1, "in png_start_read_image"); 598 599 if (png_ptr == NULL) 600 return; 601 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) 602 png_read_start_row(png_ptr); 603 } 604 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 605 606 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 607 void PNGAPI 608 png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row) 609 { 610 PNG_CONST PNG_IDAT; 611 PNG_CONST int png_pass_dsp_mask[7] = {0xff, 0x0f, 0xff, 0x33, 0xff, 0x55, 612 0xff}; 613 PNG_CONST int png_pass_mask[7] = {0x80, 0x08, 0x88, 0x22, 0xaa, 0x55, 0xff}; 614 int ret; 615 616 if (png_ptr == NULL) 617 return; 618 619 png_debug2(1, "in png_read_row (row %lu, pass %d)", 620 png_ptr->row_number, png_ptr->pass); 621 622 if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) 623 png_read_start_row(png_ptr); 624 if (png_ptr->row_number == 0 && png_ptr->pass == 0) 625 { 626 /* Check for transforms that have been set but were defined out */ 627 #if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) 628 if (png_ptr->transformations & PNG_INVERT_MONO) 629 png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined."); 630 #endif 631 #if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) 632 if (png_ptr->transformations & PNG_FILLER) 633 png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined."); 634 #endif 635 #if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ 636 !defined(PNG_READ_PACKSWAP_SUPPORTED) 637 if (png_ptr->transformations & PNG_PACKSWAP) 638 png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined."); 639 #endif 640 #if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) 641 if (png_ptr->transformations & PNG_PACK) 642 png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined."); 643 #endif 644 #if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) 645 if (png_ptr->transformations & PNG_SHIFT) 646 png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined."); 647 #endif 648 #if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) 649 if (png_ptr->transformations & PNG_BGR) 650 png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined."); 651 #endif 652 #if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) 653 if (png_ptr->transformations & PNG_SWAP_BYTES) 654 png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined."); 655 #endif 656 } 657 658 #ifdef PNG_READ_INTERLACING_SUPPORTED 659 /* If interlaced and we do not need a new row, combine row and return */ 660 if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) 661 { 662 switch (png_ptr->pass) 663 { 664 case 0: 665 if (png_ptr->row_number & 0x07) 666 { 667 if (dsp_row != NULL) 668 png_combine_row(png_ptr, dsp_row, 669 png_pass_dsp_mask[png_ptr->pass]); 670 png_read_finish_row(png_ptr); 671 return; 672 } 673 break; 674 case 1: 675 if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) 676 { 677 if (dsp_row != NULL) 678 png_combine_row(png_ptr, dsp_row, 679 png_pass_dsp_mask[png_ptr->pass]); 680 png_read_finish_row(png_ptr); 681 return; 682 } 683 break; 684 case 2: 685 if ((png_ptr->row_number & 0x07) != 4) 686 { 687 if (dsp_row != NULL && (png_ptr->row_number & 4)) 688 png_combine_row(png_ptr, dsp_row, 689 png_pass_dsp_mask[png_ptr->pass]); 690 png_read_finish_row(png_ptr); 691 return; 692 } 693 break; 694 case 3: 695 if ((png_ptr->row_number & 3) || png_ptr->width < 3) 696 { 697 if (dsp_row != NULL) 698 png_combine_row(png_ptr, dsp_row, 699 png_pass_dsp_mask[png_ptr->pass]); 700 png_read_finish_row(png_ptr); 701 return; 702 } 703 break; 704 case 4: 705 if ((png_ptr->row_number & 3) != 2) 706 { 707 if (dsp_row != NULL && (png_ptr->row_number & 2)) 708 png_combine_row(png_ptr, dsp_row, 709 png_pass_dsp_mask[png_ptr->pass]); 710 png_read_finish_row(png_ptr); 711 return; 712 } 713 break; 714 case 5: 715 if ((png_ptr->row_number & 1) || png_ptr->width < 2) 716 { 717 if (dsp_row != NULL) 718 png_combine_row(png_ptr, dsp_row, 719 png_pass_dsp_mask[png_ptr->pass]); 720 png_read_finish_row(png_ptr); 721 return; 722 } 723 break; 724 case 6: 725 if (!(png_ptr->row_number & 1)) 726 { 727 png_read_finish_row(png_ptr); 728 return; 729 } 730 break; 731 } 732 } 733 #endif 734 735 if (!(png_ptr->mode & PNG_HAVE_IDAT)) 736 png_error(png_ptr, "Invalid attempt to read row data"); 737 738 png_ptr->zstream.next_out = png_ptr->row_buf; 739 png_ptr->zstream.avail_out = 740 (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth, 741 png_ptr->iwidth) + 1); 742 do 743 { 744 if (!(png_ptr->zstream.avail_in)) 745 { 746 while (!png_ptr->idat_size) 747 { 748 #ifdef PNG_INDEX_SUPPORTED 749 if (png_ptr->index) { 750 png_opt_crc_finish(png_ptr, 0, 0); 751 png_ptr->index->stream_idat_position = png_ptr->total_data_read; 752 } else 753 #endif 754 png_crc_finish(png_ptr, 0); 755 756 757 png_ptr->idat_size = png_read_chunk_header(png_ptr); 758 if (png_memcmp(png_ptr->chunk_name, png_IDAT, 4)) 759 png_error(png_ptr, "Not enough image data"); 760 } 761 png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size; 762 png_ptr->zstream.next_in = png_ptr->zbuf; 763 if (png_ptr->zbuf_size > png_ptr->idat_size) 764 png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size; 765 png_crc_read(png_ptr, png_ptr->zbuf, 766 (png_size_t)png_ptr->zstream.avail_in); 767 png_ptr->idat_size -= png_ptr->zstream.avail_in; 768 } 769 ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH); 770 if (ret == Z_STREAM_END) 771 { 772 if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in || 773 png_ptr->idat_size) 774 png_error(png_ptr, "Extra compressed data"); 775 png_ptr->mode |= PNG_AFTER_IDAT; 776 png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED; 777 break; 778 } 779 if (ret != Z_OK) 780 #ifdef PNG_INDEX_SUPPORTED 781 if (png_ptr->index && png_ptr->row_number != png_ptr->height - 1) 782 #endif 783 png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg : 784 "Decompression error"); 785 786 } while (png_ptr->zstream.avail_out); 787 788 png_ptr->row_info.color_type = png_ptr->color_type; 789 png_ptr->row_info.width = png_ptr->iwidth; 790 png_ptr->row_info.channels = png_ptr->channels; 791 png_ptr->row_info.bit_depth = png_ptr->bit_depth; 792 png_ptr->row_info.pixel_depth = png_ptr->pixel_depth; 793 png_ptr->row_info.rowbytes = PNG_ROWBYTES(png_ptr->row_info.pixel_depth, 794 png_ptr->row_info.width); 795 796 if (png_ptr->row_buf[0]) 797 png_read_filter_row(png_ptr, &(png_ptr->row_info), 798 png_ptr->row_buf + 1, png_ptr->prev_row + 1, 799 (int)(png_ptr->row_buf[0])); 800 801 png_memcpy_check(png_ptr, png_ptr->prev_row, png_ptr->row_buf, 802 png_ptr->rowbytes + 1); 803 804 #ifdef PNG_MNG_FEATURES_SUPPORTED 805 if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && 806 (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) 807 { 808 /* Intrapixel differencing */ 809 png_do_read_intrapixel(&(png_ptr->row_info), png_ptr->row_buf + 1); 810 } 811 #endif 812 813 814 if (png_ptr->transformations || (png_ptr->flags&PNG_FLAG_STRIP_ALPHA)) 815 png_do_read_transformations(png_ptr); 816 817 #ifdef PNG_READ_INTERLACING_SUPPORTED 818 /* Blow up interlaced rows to full size */ 819 if (png_ptr->interlaced && 820 (png_ptr->transformations & PNG_INTERLACE)) 821 { 822 if (png_ptr->pass < 6) 823 /* Old interface (pre-1.0.9): 824 * png_do_read_interlace(&(png_ptr->row_info), 825 * png_ptr->row_buf + 1, png_ptr->pass, png_ptr->transformations); 826 */ 827 png_do_read_interlace(png_ptr); 828 829 if (dsp_row != NULL) 830 png_combine_row(png_ptr, dsp_row, 831 png_pass_dsp_mask[png_ptr->pass]); 832 if (row != NULL) 833 png_combine_row(png_ptr, row, 834 png_pass_mask[png_ptr->pass]); 835 } 836 else 837 #endif 838 { 839 if (row != NULL) 840 png_combine_row(png_ptr, row, 0xff); 841 if (dsp_row != NULL) 842 png_combine_row(png_ptr, dsp_row, 0xff); 843 } 844 png_read_finish_row(png_ptr); 845 846 if (png_ptr->read_row_fn != NULL) 847 (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); 848 } 849 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 850 851 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 852 /* Read one or more rows of image data. If the image is interlaced, 853 * and png_set_interlace_handling() has been called, the rows need to 854 * contain the contents of the rows from the previous pass. If the 855 * image has alpha or transparency, and png_handle_alpha()[*] has been 856 * called, the rows contents must be initialized to the contents of the 857 * screen. 858 * 859 * "row" holds the actual image, and pixels are placed in it 860 * as they arrive. If the image is displayed after each pass, it will 861 * appear to "sparkle" in. "display_row" can be used to display a 862 * "chunky" progressive image, with finer detail added as it becomes 863 * available. If you do not want this "chunky" display, you may pass 864 * NULL for display_row. If you do not want the sparkle display, and 865 * you have not called png_handle_alpha(), you may pass NULL for rows. 866 * If you have called png_handle_alpha(), and the image has either an 867 * alpha channel or a transparency chunk, you must provide a buffer for 868 * rows. In this case, you do not have to provide a display_row buffer 869 * also, but you may. If the image is not interlaced, or if you have 870 * not called png_set_interlace_handling(), the display_row buffer will 871 * be ignored, so pass NULL to it. 872 * 873 * [*] png_handle_alpha() does not exist yet, as of this version of libpng 874 */ 875 876 void PNGAPI 877 png_read_rows(png_structp png_ptr, png_bytepp row, 878 png_bytepp display_row, png_uint_32 num_rows) 879 { 880 png_uint_32 i; 881 png_bytepp rp; 882 png_bytepp dp; 883 884 png_debug(1, "in png_read_rows"); 885 886 if (png_ptr == NULL) 887 return; 888 rp = row; 889 dp = display_row; 890 if (rp != NULL && dp != NULL) 891 for (i = 0; i < num_rows; i++) 892 { 893 png_bytep rptr = *rp++; 894 png_bytep dptr = *dp++; 895 896 png_read_row(png_ptr, rptr, dptr); 897 } 898 else if (rp != NULL) 899 for (i = 0; i < num_rows; i++) 900 { 901 png_bytep rptr = *rp; 902 png_read_row(png_ptr, rptr, png_bytep_NULL); 903 rp++; 904 } 905 else if (dp != NULL) 906 for (i = 0; i < num_rows; i++) 907 { 908 png_bytep dptr = *dp; 909 png_read_row(png_ptr, png_bytep_NULL, dptr); 910 dp++; 911 } 912 } 913 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 914 915 #ifdef PNG_INDEX_SUPPORTED 916 #define IDAT_HEADER_SIZE 8 917 918 /* Set the png read position to a new position based on idat_position and 919 * offset. 920 */ 921 void 922 png_set_read_offset(png_structp png_ptr, 923 png_uint_32 idat_position, png_uint_32 bytes_left) 924 { 925 png_seek_data(png_ptr, idat_position); 926 png_ptr->idat_size = png_read_chunk_header(png_ptr); 927 928 // We need to add back IDAT_HEADER_SIZE because in zlib's perspective, 929 // IDAT_HEADER in PNG is already stripped out. 930 png_seek_data(png_ptr, idat_position + IDAT_HEADER_SIZE + png_ptr->idat_size - bytes_left); 931 png_ptr->idat_size = bytes_left; 932 } 933 934 /* Configure png decoder to decode the pass starting from *row. 935 * The requested row may be adjusted to align with an indexing row. 936 * The actual row for the decoder to start its decoding will be returned in 937 * *row. 938 */ 939 void PNGAPI 940 png_configure_decoder(png_structp png_ptr, int *row, int pass) 941 { 942 png_indexp index = png_ptr->index; 943 int n = *row / index->step[pass]; 944 png_line_indexp line_index = index->pass_line_index[pass][n]; 945 946 // Adjust row to an indexing row. 947 *row = n * index->step[pass]; 948 png_ptr->row_number = *row; 949 950 #ifdef PNG_READ_INTERLACING_SUPPORTED 951 if (png_ptr->interlaced) 952 png_set_interlaced_pass(png_ptr, pass); 953 #endif 954 955 long row_byte_length = 956 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1; 957 958 inflateEnd(&png_ptr->zstream); 959 inflateCopy(&png_ptr->zstream, line_index->z_state); 960 961 // Set the png read position to line_index. 962 png_set_read_offset(png_ptr, line_index->stream_idat_position, 963 line_index->bytes_left_in_idat); 964 png_memcpy_check(png_ptr, 965 png_ptr->prev_row, line_index->prev_row, row_byte_length); 966 png_ptr->zstream.avail_in = 0; 967 } 968 969 /* Build the line index and store the index in png_ptr->index. 970 */ 971 void PNGAPI 972 png_build_index(png_structp png_ptr) 973 { 974 // number of rows in a 8x8 block for each interlaced pass. 975 int number_rows_in_pass[7] = {1, 1, 1, 2, 2, 4, 4}; 976 977 int ret; 978 png_uint_32 i, j; 979 png_bytep rp; 980 int p, pass_number = 1; 981 982 #ifdef PNG_READ_INTERLACING_SUPPORTED 983 pass_number = png_set_interlace_handling(png_ptr); 984 #endif 985 986 if (png_ptr == NULL) 987 return; 988 989 png_read_start_row(png_ptr); 990 991 #ifdef PNG_READ_INTERLACING_SUPPORTED 992 if (!png_ptr->interlaced) 993 #endif 994 { 995 number_rows_in_pass[0] = 8; 996 } 997 998 rp = png_malloc(png_ptr, png_ptr->rowbytes); 999 1000 png_indexp index = png_malloc(png_ptr, sizeof(png_index)); 1001 png_ptr->index = index; 1002 1003 index->stream_idat_position = png_ptr->total_data_read - IDAT_HEADER_SIZE; 1004 1005 // Set the default size of index in each pass to 0, 1006 // so that we can free index correctly in png_destroy_read_struct. 1007 for (p = 0; p < 7; p++) 1008 index->size[p] = 0; 1009 1010 for (p = 0; p < pass_number; p++) 1011 { 1012 // We adjust the index step in each pass to make sure each pass 1013 // has roughly the same size of index. 1014 // This way, we won't consume to much memory in recording index. 1015 index->step[p] = INDEX_SAMPLE_SIZE * (8 / number_rows_in_pass[p]); 1016 index->size[p] = 1017 (png_ptr->height + index->step[p] - 1) / index->step[p]; 1018 index->pass_line_index[p] = 1019 png_malloc(png_ptr, index->size[p] * sizeof(png_line_indexp)); 1020 1021 // Get the row_byte_length seen by the filter. This value may be 1022 // different from the row_byte_length of a bitmap in the case of 1023 // color palette mode. 1024 int row_byte_length = 1025 PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1; 1026 1027 // Now, we record index for each indexing row. 1028 for (i = 0; i < index->size[p]; i++) 1029 { 1030 png_line_indexp line_index = png_malloc(png_ptr, sizeof(png_line_index)); 1031 index->pass_line_index[p][i] = line_index; 1032 1033 line_index->z_state = png_malloc(png_ptr, sizeof(z_stream)); 1034 inflateCopy(line_index->z_state, &png_ptr->zstream); 1035 line_index->prev_row = png_malloc(png_ptr, row_byte_length); 1036 png_memcpy_check(png_ptr, 1037 line_index->prev_row, png_ptr->prev_row, row_byte_length); 1038 line_index->stream_idat_position = index->stream_idat_position; 1039 line_index->bytes_left_in_idat = png_ptr->idat_size + png_ptr->zstream.avail_in; 1040 1041 // Skip the "step" number of rows to the next indexing row. 1042 for (j = 0; j < index->step[p] && 1043 i * index->step[p] + j < png_ptr->height; j++) 1044 { 1045 png_read_row(png_ptr, rp, png_bytep_NULL); 1046 } 1047 } 1048 } 1049 png_free(png_ptr, rp); 1050 } 1051 #endif 1052 1053 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 1054 /* Read the entire image. If the image has an alpha channel or a tRNS 1055 * chunk, and you have called png_handle_alpha()[*], you will need to 1056 * initialize the image to the current image that PNG will be overlaying. 1057 * We set the num_rows again here, in case it was incorrectly set in 1058 * png_read_start_row() by a call to png_read_update_info() or 1059 * png_start_read_image() if png_set_interlace_handling() wasn't called 1060 * prior to either of these functions like it should have been. You can 1061 * only call this function once. If you desire to have an image for 1062 * each pass of a interlaced image, use png_read_rows() instead. 1063 * 1064 * [*] png_handle_alpha() does not exist yet, as of this version of libpng 1065 */ 1066 void PNGAPI 1067 png_read_image(png_structp png_ptr, png_bytepp image) 1068 { 1069 png_uint_32 i, image_height; 1070 int pass, j; 1071 png_bytepp rp; 1072 1073 png_debug(1, "in png_read_image"); 1074 1075 if (png_ptr == NULL) 1076 return; 1077 1078 #ifdef PNG_READ_INTERLACING_SUPPORTED 1079 pass = png_set_interlace_handling(png_ptr); 1080 #else 1081 if (png_ptr->interlaced) 1082 png_error(png_ptr, 1083 "Cannot read interlaced image -- interlace handler disabled."); 1084 pass = 1; 1085 #endif 1086 1087 1088 image_height=png_ptr->height; 1089 png_ptr->num_rows = image_height; /* Make sure this is set correctly */ 1090 1091 for (j = 0; j < pass; j++) 1092 { 1093 rp = image; 1094 for (i = 0; i < image_height; i++) 1095 { 1096 png_read_row(png_ptr, *rp, png_bytep_NULL); 1097 rp++; 1098 } 1099 } 1100 } 1101 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 1102 1103 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 1104 /* Read the end of the PNG file. Will not read past the end of the 1105 * file, will verify the end is accurate, and will read any comments 1106 * or time information at the end of the file, if info is not NULL. 1107 */ 1108 void PNGAPI 1109 png_read_end(png_structp png_ptr, png_infop info_ptr) 1110 { 1111 png_debug(1, "in png_read_end"); 1112 1113 if (png_ptr == NULL) 1114 return; 1115 png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */ 1116 1117 do 1118 { 1119 #ifdef PNG_USE_LOCAL_ARRAYS 1120 PNG_CONST PNG_IHDR; 1121 PNG_CONST PNG_IDAT; 1122 PNG_CONST PNG_IEND; 1123 PNG_CONST PNG_PLTE; 1124 #ifdef PNG_READ_bKGD_SUPPORTED 1125 PNG_CONST PNG_bKGD; 1126 #endif 1127 #ifdef PNG_READ_cHRM_SUPPORTED 1128 PNG_CONST PNG_cHRM; 1129 #endif 1130 #ifdef PNG_READ_gAMA_SUPPORTED 1131 PNG_CONST PNG_gAMA; 1132 #endif 1133 #ifdef PNG_READ_hIST_SUPPORTED 1134 PNG_CONST PNG_hIST; 1135 #endif 1136 #ifdef PNG_READ_iCCP_SUPPORTED 1137 PNG_CONST PNG_iCCP; 1138 #endif 1139 #ifdef PNG_READ_iTXt_SUPPORTED 1140 PNG_CONST PNG_iTXt; 1141 #endif 1142 #ifdef PNG_READ_oFFs_SUPPORTED 1143 PNG_CONST PNG_oFFs; 1144 #endif 1145 #ifdef PNG_READ_pCAL_SUPPORTED 1146 PNG_CONST PNG_pCAL; 1147 #endif 1148 #ifdef PNG_READ_pHYs_SUPPORTED 1149 PNG_CONST PNG_pHYs; 1150 #endif 1151 #ifdef PNG_READ_sBIT_SUPPORTED 1152 PNG_CONST PNG_sBIT; 1153 #endif 1154 #ifdef PNG_READ_sCAL_SUPPORTED 1155 PNG_CONST PNG_sCAL; 1156 #endif 1157 #ifdef PNG_READ_sPLT_SUPPORTED 1158 PNG_CONST PNG_sPLT; 1159 #endif 1160 #ifdef PNG_READ_sRGB_SUPPORTED 1161 PNG_CONST PNG_sRGB; 1162 #endif 1163 #ifdef PNG_READ_tEXt_SUPPORTED 1164 PNG_CONST PNG_tEXt; 1165 #endif 1166 #ifdef PNG_READ_tIME_SUPPORTED 1167 PNG_CONST PNG_tIME; 1168 #endif 1169 #ifdef PNG_READ_tRNS_SUPPORTED 1170 PNG_CONST PNG_tRNS; 1171 #endif 1172 #ifdef PNG_READ_zTXt_SUPPORTED 1173 PNG_CONST PNG_zTXt; 1174 #endif 1175 #endif /* PNG_USE_LOCAL_ARRAYS */ 1176 png_uint_32 length = png_read_chunk_header(png_ptr); 1177 PNG_CONST png_bytep chunk_name = png_ptr->chunk_name; 1178 1179 if (!png_memcmp(chunk_name, png_IHDR, 4)) 1180 png_handle_IHDR(png_ptr, info_ptr, length); 1181 else if (!png_memcmp(chunk_name, png_IEND, 4)) 1182 png_handle_IEND(png_ptr, info_ptr, length); 1183 #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 1184 else if (png_handle_as_unknown(png_ptr, chunk_name)) 1185 { 1186 if (!png_memcmp(chunk_name, png_IDAT, 4)) 1187 { 1188 if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) 1189 png_error(png_ptr, "Too many IDAT's found"); 1190 } 1191 png_handle_unknown(png_ptr, info_ptr, length); 1192 if (!png_memcmp(chunk_name, png_PLTE, 4)) 1193 png_ptr->mode |= PNG_HAVE_PLTE; 1194 } 1195 #endif 1196 else if (!png_memcmp(chunk_name, png_IDAT, 4)) 1197 { 1198 /* Zero length IDATs are legal after the last IDAT has been 1199 * read, but not after other chunks have been read. 1200 */ 1201 if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) 1202 png_error(png_ptr, "Too many IDAT's found"); 1203 png_crc_finish(png_ptr, length); 1204 } 1205 else if (!png_memcmp(chunk_name, png_PLTE, 4)) 1206 png_handle_PLTE(png_ptr, info_ptr, length); 1207 #ifdef PNG_READ_bKGD_SUPPORTED 1208 else if (!png_memcmp(chunk_name, png_bKGD, 4)) 1209 png_handle_bKGD(png_ptr, info_ptr, length); 1210 #endif 1211 #ifdef PNG_READ_cHRM_SUPPORTED 1212 else if (!png_memcmp(chunk_name, png_cHRM, 4)) 1213 png_handle_cHRM(png_ptr, info_ptr, length); 1214 #endif 1215 #ifdef PNG_READ_gAMA_SUPPORTED 1216 else if (!png_memcmp(chunk_name, png_gAMA, 4)) 1217 png_handle_gAMA(png_ptr, info_ptr, length); 1218 #endif 1219 #ifdef PNG_READ_hIST_SUPPORTED 1220 else if (!png_memcmp(chunk_name, png_hIST, 4)) 1221 png_handle_hIST(png_ptr, info_ptr, length); 1222 #endif 1223 #ifdef PNG_READ_oFFs_SUPPORTED 1224 else if (!png_memcmp(chunk_name, png_oFFs, 4)) 1225 png_handle_oFFs(png_ptr, info_ptr, length); 1226 #endif 1227 #ifdef PNG_READ_pCAL_SUPPORTED 1228 else if (!png_memcmp(chunk_name, png_pCAL, 4)) 1229 png_handle_pCAL(png_ptr, info_ptr, length); 1230 #endif 1231 #ifdef PNG_READ_sCAL_SUPPORTED 1232 else if (!png_memcmp(chunk_name, png_sCAL, 4)) 1233 png_handle_sCAL(png_ptr, info_ptr, length); 1234 #endif 1235 #ifdef PNG_READ_pHYs_SUPPORTED 1236 else if (!png_memcmp(chunk_name, png_pHYs, 4)) 1237 png_handle_pHYs(png_ptr, info_ptr, length); 1238 #endif 1239 #ifdef PNG_READ_sBIT_SUPPORTED 1240 else if (!png_memcmp(chunk_name, png_sBIT, 4)) 1241 png_handle_sBIT(png_ptr, info_ptr, length); 1242 #endif 1243 #ifdef PNG_READ_sRGB_SUPPORTED 1244 else if (!png_memcmp(chunk_name, png_sRGB, 4)) 1245 png_handle_sRGB(png_ptr, info_ptr, length); 1246 #endif 1247 #ifdef PNG_READ_iCCP_SUPPORTED 1248 else if (!png_memcmp(chunk_name, png_iCCP, 4)) 1249 png_handle_iCCP(png_ptr, info_ptr, length); 1250 #endif 1251 #ifdef PNG_READ_sPLT_SUPPORTED 1252 else if (!png_memcmp(chunk_name, png_sPLT, 4)) 1253 png_handle_sPLT(png_ptr, info_ptr, length); 1254 #endif 1255 #ifdef PNG_READ_tEXt_SUPPORTED 1256 else if (!png_memcmp(chunk_name, png_tEXt, 4)) 1257 png_handle_tEXt(png_ptr, info_ptr, length); 1258 #endif 1259 #ifdef PNG_READ_tIME_SUPPORTED 1260 else if (!png_memcmp(chunk_name, png_tIME, 4)) 1261 png_handle_tIME(png_ptr, info_ptr, length); 1262 #endif 1263 #ifdef PNG_READ_tRNS_SUPPORTED 1264 else if (!png_memcmp(chunk_name, png_tRNS, 4)) 1265 png_handle_tRNS(png_ptr, info_ptr, length); 1266 #endif 1267 #ifdef PNG_READ_zTXt_SUPPORTED 1268 else if (!png_memcmp(chunk_name, png_zTXt, 4)) 1269 png_handle_zTXt(png_ptr, info_ptr, length); 1270 #endif 1271 #ifdef PNG_READ_iTXt_SUPPORTED 1272 else if (!png_memcmp(chunk_name, png_iTXt, 4)) 1273 png_handle_iTXt(png_ptr, info_ptr, length); 1274 #endif 1275 else 1276 png_handle_unknown(png_ptr, info_ptr, length); 1277 } while (!(png_ptr->mode & PNG_HAVE_IEND)); 1278 } 1279 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 1280 1281 /* Free all memory used by the read */ 1282 void PNGAPI 1283 png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, 1284 png_infopp end_info_ptr_ptr) 1285 { 1286 png_structp png_ptr = NULL; 1287 png_infop info_ptr = NULL, end_info_ptr = NULL; 1288 #ifdef PNG_USER_MEM_SUPPORTED 1289 png_free_ptr free_fn = NULL; 1290 png_voidp mem_ptr = NULL; 1291 #endif 1292 1293 png_debug(1, "in png_destroy_read_struct"); 1294 1295 if (png_ptr_ptr != NULL) 1296 png_ptr = *png_ptr_ptr; 1297 if (png_ptr == NULL) 1298 return; 1299 1300 #ifdef PNG_USER_MEM_SUPPORTED 1301 free_fn = png_ptr->free_fn; 1302 mem_ptr = png_ptr->mem_ptr; 1303 #endif 1304 1305 if (info_ptr_ptr != NULL) 1306 info_ptr = *info_ptr_ptr; 1307 1308 if (end_info_ptr_ptr != NULL) 1309 end_info_ptr = *end_info_ptr_ptr; 1310 1311 png_read_destroy(png_ptr, info_ptr, end_info_ptr); 1312 1313 if (info_ptr != NULL) 1314 { 1315 #ifdef PNG_TEXT_SUPPORTED 1316 png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1); 1317 #endif 1318 1319 #ifdef PNG_USER_MEM_SUPPORTED 1320 png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn, 1321 (png_voidp)mem_ptr); 1322 #else 1323 png_destroy_struct((png_voidp)info_ptr); 1324 #endif 1325 *info_ptr_ptr = NULL; 1326 } 1327 1328 if (end_info_ptr != NULL) 1329 { 1330 #ifdef PNG_READ_TEXT_SUPPORTED 1331 png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1); 1332 #endif 1333 #ifdef PNG_USER_MEM_SUPPORTED 1334 png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn, 1335 (png_voidp)mem_ptr); 1336 #else 1337 png_destroy_struct((png_voidp)end_info_ptr); 1338 #endif 1339 *end_info_ptr_ptr = NULL; 1340 } 1341 1342 if (png_ptr != NULL) 1343 { 1344 #ifdef PNG_INDEX_SUPPORTED 1345 if (png_ptr->index) { 1346 unsigned int i, p; 1347 png_indexp index = png_ptr->index; 1348 for (p = 0; p < 7; p++) { 1349 for (i = 0; i < index->size[p]; i++) { 1350 inflateEnd(index->pass_line_index[p][i]->z_state); 1351 png_free(png_ptr, index->pass_line_index[p][i]->z_state); 1352 png_free(png_ptr, index->pass_line_index[p][i]->prev_row); 1353 png_free(png_ptr, index->pass_line_index[p][i]); 1354 } 1355 if (index->size[p] != 0) { 1356 png_free(png_ptr, index->pass_line_index[p]); 1357 } 1358 } 1359 png_free(png_ptr, index); 1360 } 1361 #endif 1362 #ifdef PNG_USER_MEM_SUPPORTED 1363 png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn, 1364 (png_voidp)mem_ptr); 1365 #else 1366 png_destroy_struct((png_voidp)png_ptr); 1367 #endif 1368 *png_ptr_ptr = NULL; 1369 } 1370 } 1371 1372 /* Free all memory used by the read (old method) */ 1373 void /* PRIVATE */ 1374 png_read_destroy(png_structp png_ptr, png_infop info_ptr, 1375 png_infop end_info_ptr) 1376 { 1377 #ifdef PNG_SETJMP_SUPPORTED 1378 jmp_buf tmp_jmp; 1379 #endif 1380 png_error_ptr error_fn; 1381 png_error_ptr warning_fn; 1382 png_voidp error_ptr; 1383 #ifdef PNG_USER_MEM_SUPPORTED 1384 png_free_ptr free_fn; 1385 #endif 1386 1387 png_debug(1, "in png_read_destroy"); 1388 1389 if (info_ptr != NULL) 1390 png_info_destroy(png_ptr, info_ptr); 1391 1392 if (end_info_ptr != NULL) 1393 png_info_destroy(png_ptr, end_info_ptr); 1394 1395 png_free(png_ptr, png_ptr->zbuf); 1396 png_free(png_ptr, png_ptr->big_row_buf); 1397 png_free(png_ptr, png_ptr->prev_row); 1398 png_free(png_ptr, png_ptr->chunkdata); 1399 #ifdef PNG_READ_DITHER_SUPPORTED 1400 png_free(png_ptr, png_ptr->palette_lookup); 1401 png_free(png_ptr, png_ptr->dither_index); 1402 #endif 1403 #ifdef PNG_READ_GAMMA_SUPPORTED 1404 png_free(png_ptr, png_ptr->gamma_table); 1405 #endif 1406 #ifdef PNG_READ_BACKGROUND_SUPPORTED 1407 png_free(png_ptr, png_ptr->gamma_from_1); 1408 png_free(png_ptr, png_ptr->gamma_to_1); 1409 #endif 1410 #ifdef PNG_FREE_ME_SUPPORTED 1411 if (png_ptr->free_me & PNG_FREE_PLTE) 1412 png_zfree(png_ptr, png_ptr->palette); 1413 png_ptr->free_me &= ~PNG_FREE_PLTE; 1414 #else 1415 if (png_ptr->flags & PNG_FLAG_FREE_PLTE) 1416 png_zfree(png_ptr, png_ptr->palette); 1417 png_ptr->flags &= ~PNG_FLAG_FREE_PLTE; 1418 #endif 1419 #if defined(PNG_tRNS_SUPPORTED) || \ 1420 defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 1421 #ifdef PNG_FREE_ME_SUPPORTED 1422 if (png_ptr->free_me & PNG_FREE_TRNS) 1423 png_free(png_ptr, png_ptr->trans); 1424 png_ptr->free_me &= ~PNG_FREE_TRNS; 1425 #else 1426 if (png_ptr->flags & PNG_FLAG_FREE_TRNS) 1427 png_free(png_ptr, png_ptr->trans); 1428 png_ptr->flags &= ~PNG_FLAG_FREE_TRNS; 1429 #endif 1430 #endif 1431 #ifdef PNG_READ_hIST_SUPPORTED 1432 #ifdef PNG_FREE_ME_SUPPORTED 1433 if (png_ptr->free_me & PNG_FREE_HIST) 1434 png_free(png_ptr, png_ptr->hist); 1435 png_ptr->free_me &= ~PNG_FREE_HIST; 1436 #else 1437 if (png_ptr->flags & PNG_FLAG_FREE_HIST) 1438 png_free(png_ptr, png_ptr->hist); 1439 png_ptr->flags &= ~PNG_FLAG_FREE_HIST; 1440 #endif 1441 #endif 1442 #ifdef PNG_READ_GAMMA_SUPPORTED 1443 if (png_ptr->gamma_16_table != NULL) 1444 { 1445 int i; 1446 int istop = (1 << (8 - png_ptr->gamma_shift)); 1447 for (i = 0; i < istop; i++) 1448 { 1449 png_free(png_ptr, png_ptr->gamma_16_table[i]); 1450 } 1451 png_free(png_ptr, png_ptr->gamma_16_table); 1452 } 1453 #ifdef PNG_READ_BACKGROUND_SUPPORTED 1454 if (png_ptr->gamma_16_from_1 != NULL) 1455 { 1456 int i; 1457 int istop = (1 << (8 - png_ptr->gamma_shift)); 1458 for (i = 0; i < istop; i++) 1459 { 1460 png_free(png_ptr, png_ptr->gamma_16_from_1[i]); 1461 } 1462 png_free(png_ptr, png_ptr->gamma_16_from_1); 1463 } 1464 if (png_ptr->gamma_16_to_1 != NULL) 1465 { 1466 int i; 1467 int istop = (1 << (8 - png_ptr->gamma_shift)); 1468 for (i = 0; i < istop; i++) 1469 { 1470 png_free(png_ptr, png_ptr->gamma_16_to_1[i]); 1471 } 1472 png_free(png_ptr, png_ptr->gamma_16_to_1); 1473 } 1474 #endif 1475 #endif 1476 #ifdef PNG_TIME_RFC1123_SUPPORTED 1477 png_free(png_ptr, png_ptr->time_buffer); 1478 #endif 1479 1480 inflateEnd(&png_ptr->zstream); 1481 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED 1482 png_free(png_ptr, png_ptr->save_buffer); 1483 #endif 1484 1485 #ifdef PNG_PROGRESSIVE_READ_SUPPORTED 1486 #ifdef PNG_TEXT_SUPPORTED 1487 png_free(png_ptr, png_ptr->current_text); 1488 #endif /* PNG_TEXT_SUPPORTED */ 1489 #endif /* PNG_PROGRESSIVE_READ_SUPPORTED */ 1490 1491 /* Save the important info out of the png_struct, in case it is 1492 * being used again. 1493 */ 1494 #ifdef PNG_SETJMP_SUPPORTED 1495 png_memcpy(tmp_jmp, png_ptr->jmpbuf, png_sizeof(jmp_buf)); 1496 #endif 1497 1498 error_fn = png_ptr->error_fn; 1499 warning_fn = png_ptr->warning_fn; 1500 error_ptr = png_ptr->error_ptr; 1501 #ifdef PNG_USER_MEM_SUPPORTED 1502 free_fn = png_ptr->free_fn; 1503 #endif 1504 1505 png_memset(png_ptr, 0, png_sizeof(png_struct)); 1506 1507 png_ptr->error_fn = error_fn; 1508 png_ptr->warning_fn = warning_fn; 1509 png_ptr->error_ptr = error_ptr; 1510 #ifdef PNG_USER_MEM_SUPPORTED 1511 png_ptr->free_fn = free_fn; 1512 #endif 1513 1514 #ifdef PNG_SETJMP_SUPPORTED 1515 png_memcpy(png_ptr->jmpbuf, tmp_jmp, png_sizeof(jmp_buf)); 1516 #endif 1517 1518 } 1519 1520 void PNGAPI 1521 png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn) 1522 { 1523 if (png_ptr == NULL) 1524 return; 1525 png_ptr->read_row_fn = read_row_fn; 1526 } 1527 1528 1529 #ifdef PNG_SEQUENTIAL_READ_SUPPORTED 1530 #ifdef PNG_INFO_IMAGE_SUPPORTED 1531 void PNGAPI 1532 png_read_png(png_structp png_ptr, png_infop info_ptr, 1533 int transforms, 1534 voidp params) 1535 { 1536 int row; 1537 1538 if (png_ptr == NULL) 1539 return; 1540 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 1541 /* Invert the alpha channel from opacity to transparency 1542 */ 1543 if (transforms & PNG_TRANSFORM_INVERT_ALPHA) 1544 png_set_invert_alpha(png_ptr); 1545 #endif 1546 1547 /* png_read_info() gives us all of the information from the 1548 * PNG file before the first IDAT (image data chunk). 1549 */ 1550 png_read_info(png_ptr, info_ptr); 1551 if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep)) 1552 png_error(png_ptr, "Image is too high to process with png_read_png()"); 1553 1554 /* -------------- image transformations start here ------------------- */ 1555 1556 #ifdef PNG_READ_16_TO_8_SUPPORTED 1557 /* Tell libpng to strip 16 bit/color files down to 8 bits per color. 1558 */ 1559 if (transforms & PNG_TRANSFORM_STRIP_16) 1560 png_set_strip_16(png_ptr); 1561 #endif 1562 1563 #ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 1564 /* Strip alpha bytes from the input data without combining with 1565 * the background (not recommended). 1566 */ 1567 if (transforms & PNG_TRANSFORM_STRIP_ALPHA) 1568 png_set_strip_alpha(png_ptr); 1569 #endif 1570 1571 #if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED) 1572 /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single 1573 * byte into separate bytes (useful for paletted and grayscale images). 1574 */ 1575 if (transforms & PNG_TRANSFORM_PACKING) 1576 png_set_packing(png_ptr); 1577 #endif 1578 1579 #ifdef PNG_READ_PACKSWAP_SUPPORTED 1580 /* Change the order of packed pixels to least significant bit first 1581 * (not useful if you are using png_set_packing). 1582 */ 1583 if (transforms & PNG_TRANSFORM_PACKSWAP) 1584 png_set_packswap(png_ptr); 1585 #endif 1586 1587 #ifdef PNG_READ_EXPAND_SUPPORTED 1588 /* Expand paletted colors into true RGB triplets 1589 * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel 1590 * Expand paletted or RGB images with transparency to full alpha 1591 * channels so the data will be available as RGBA quartets. 1592 */ 1593 if (transforms & PNG_TRANSFORM_EXPAND) 1594 if ((png_ptr->bit_depth < 8) || 1595 (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) || 1596 (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))) 1597 png_set_expand(png_ptr); 1598 #endif 1599 1600 /* We don't handle background color or gamma transformation or dithering. 1601 */ 1602 1603 #ifdef PNG_READ_INVERT_SUPPORTED 1604 /* Invert monochrome files to have 0 as white and 1 as black 1605 */ 1606 if (transforms & PNG_TRANSFORM_INVERT_MONO) 1607 png_set_invert_mono(png_ptr); 1608 #endif 1609 1610 #ifdef PNG_READ_SHIFT_SUPPORTED 1611 /* If you want to shift the pixel values from the range [0,255] or 1612 * [0,65535] to the original [0,7] or [0,31], or whatever range the 1613 * colors were originally in: 1614 */ 1615 if ((transforms & PNG_TRANSFORM_SHIFT) 1616 && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT)) 1617 { 1618 png_color_8p sig_bit; 1619 1620 png_get_sBIT(png_ptr, info_ptr, &sig_bit); 1621 png_set_shift(png_ptr, sig_bit); 1622 } 1623 #endif 1624 1625 #ifdef PNG_READ_BGR_SUPPORTED 1626 /* Flip the RGB pixels to BGR (or RGBA to BGRA) 1627 */ 1628 if (transforms & PNG_TRANSFORM_BGR) 1629 png_set_bgr(png_ptr); 1630 #endif 1631 1632 #ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 1633 /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) 1634 */ 1635 if (transforms & PNG_TRANSFORM_SWAP_ALPHA) 1636 png_set_swap_alpha(png_ptr); 1637 #endif 1638 1639 #ifdef PNG_READ_SWAP_SUPPORTED 1640 /* Swap bytes of 16 bit files to least significant byte first 1641 */ 1642 if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) 1643 png_set_swap(png_ptr); 1644 #endif 1645 1646 /* Added at libpng-1.2.41 */ 1647 #ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 1648 /* Invert the alpha channel from opacity to transparency 1649 */ 1650 if (transforms & PNG_TRANSFORM_INVERT_ALPHA) 1651 png_set_invert_alpha(png_ptr); 1652 #endif 1653 1654 /* Added at libpng-1.2.41 */ 1655 #ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1656 /* Expand grayscale image to RGB 1657 */ 1658 if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) 1659 png_set_gray_to_rgb(png_ptr); 1660 #endif 1661 1662 /* We don't handle adding filler bytes */ 1663 1664 /* Optional call to gamma correct and add the background to the palette 1665 * and update info structure. REQUIRED if you are expecting libpng to 1666 * update the palette for you (i.e., you selected such a transform above). 1667 */ 1668 png_read_update_info(png_ptr, info_ptr); 1669 1670 /* -------------- image transformations end here ------------------- */ 1671 1672 #ifdef PNG_FREE_ME_SUPPORTED 1673 png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); 1674 #endif 1675 if (info_ptr->row_pointers == NULL) 1676 { 1677 info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr, 1678 info_ptr->height * png_sizeof(png_bytep)); 1679 png_memset(info_ptr->row_pointers, 0, info_ptr->height 1680 * png_sizeof(png_bytep)); 1681 1682 #ifdef PNG_FREE_ME_SUPPORTED 1683 info_ptr->free_me |= PNG_FREE_ROWS; 1684 #endif 1685 1686 for (row = 0; row < (int)info_ptr->height; row++) 1687 info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr, 1688 png_get_rowbytes(png_ptr, info_ptr)); 1689 } 1690 1691 png_read_image(png_ptr, info_ptr->row_pointers); 1692 info_ptr->valid |= PNG_INFO_IDAT; 1693 1694 /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ 1695 png_read_end(png_ptr, info_ptr); 1696 1697 transforms = transforms; /* Quiet compiler warnings */ 1698 params = params; 1699 1700 } 1701 #endif /* PNG_INFO_IMAGE_SUPPORTED */ 1702 #endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 1703 #endif /* PNG_READ_SUPPORTED */ 1704