13965825b97a5809454f5810f7e603cbd02daa036scroggo 23965825b97a5809454f5810f7e603cbd02daa036scroggo/* pngread.c - read a PNG file 33965825b97a5809454f5810f7e603cbd02daa036scroggo * 43965825b97a5809454f5810f7e603cbd02daa036scroggo * Last changed in libpng 1.6.17 [March 26, 2015] 53965825b97a5809454f5810f7e603cbd02daa036scroggo * Copyright (c) 1998-2002,2004,2006-2015 Glenn Randers-Pehrson 63965825b97a5809454f5810f7e603cbd02daa036scroggo * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 73965825b97a5809454f5810f7e603cbd02daa036scroggo * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 83965825b97a5809454f5810f7e603cbd02daa036scroggo * 93965825b97a5809454f5810f7e603cbd02daa036scroggo * This code is released under the libpng license. 103965825b97a5809454f5810f7e603cbd02daa036scroggo * For conditions of distribution and use, see the disclaimer 113965825b97a5809454f5810f7e603cbd02daa036scroggo * and license in png.h 123965825b97a5809454f5810f7e603cbd02daa036scroggo * 133965825b97a5809454f5810f7e603cbd02daa036scroggo * This file contains routines that an application calls directly to 143965825b97a5809454f5810f7e603cbd02daa036scroggo * read a PNG file or stream. 153965825b97a5809454f5810f7e603cbd02daa036scroggo */ 163965825b97a5809454f5810f7e603cbd02daa036scroggo 173965825b97a5809454f5810f7e603cbd02daa036scroggo#include "pngpriv.h" 183965825b97a5809454f5810f7e603cbd02daa036scroggo#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) 193965825b97a5809454f5810f7e603cbd02daa036scroggo# include <errno.h> 203965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 213965825b97a5809454f5810f7e603cbd02daa036scroggo 223965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_SUPPORTED 233965825b97a5809454f5810f7e603cbd02daa036scroggo 243965825b97a5809454f5810f7e603cbd02daa036scroggo/* Create a PNG structure for reading, and allocate any memory needed. */ 253965825b97a5809454f5810f7e603cbd02daa036scroggoPNG_FUNCTION(png_structp,PNGAPI 263965825b97a5809454f5810f7e603cbd02daa036scroggopng_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, 273965825b97a5809454f5810f7e603cbd02daa036scroggo png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) 283965825b97a5809454f5810f7e603cbd02daa036scroggo{ 293965825b97a5809454f5810f7e603cbd02daa036scroggo#ifndef PNG_USER_MEM_SUPPORTED 303965825b97a5809454f5810f7e603cbd02daa036scroggo png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, 313965825b97a5809454f5810f7e603cbd02daa036scroggo error_fn, warn_fn, NULL, NULL, NULL); 323965825b97a5809454f5810f7e603cbd02daa036scroggo#else 333965825b97a5809454f5810f7e603cbd02daa036scroggo return png_create_read_struct_2(user_png_ver, error_ptr, error_fn, 343965825b97a5809454f5810f7e603cbd02daa036scroggo warn_fn, NULL, NULL, NULL); 353965825b97a5809454f5810f7e603cbd02daa036scroggo} 363965825b97a5809454f5810f7e603cbd02daa036scroggo 373965825b97a5809454f5810f7e603cbd02daa036scroggo/* Alternate create PNG structure for reading, and allocate any memory 383965825b97a5809454f5810f7e603cbd02daa036scroggo * needed. 393965825b97a5809454f5810f7e603cbd02daa036scroggo */ 403965825b97a5809454f5810f7e603cbd02daa036scroggoPNG_FUNCTION(png_structp,PNGAPI 413965825b97a5809454f5810f7e603cbd02daa036scroggopng_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, 423965825b97a5809454f5810f7e603cbd02daa036scroggo png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, 433965825b97a5809454f5810f7e603cbd02daa036scroggo png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) 443965825b97a5809454f5810f7e603cbd02daa036scroggo{ 453965825b97a5809454f5810f7e603cbd02daa036scroggo png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, 463965825b97a5809454f5810f7e603cbd02daa036scroggo error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); 473965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* USER_MEM */ 483965825b97a5809454f5810f7e603cbd02daa036scroggo 493965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr != NULL) 503965825b97a5809454f5810f7e603cbd02daa036scroggo { 513965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->mode = PNG_IS_READ_STRUCT; 523965825b97a5809454f5810f7e603cbd02daa036scroggo 533965825b97a5809454f5810f7e603cbd02daa036scroggo /* Added in libpng-1.6.0; this can be used to detect a read structure if 543965825b97a5809454f5810f7e603cbd02daa036scroggo * required (it will be zero in a write structure.) 553965825b97a5809454f5810f7e603cbd02daa036scroggo */ 563965825b97a5809454f5810f7e603cbd02daa036scroggo# ifdef PNG_SEQUENTIAL_READ_SUPPORTED 573965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE; 583965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 593965825b97a5809454f5810f7e603cbd02daa036scroggo 603965825b97a5809454f5810f7e603cbd02daa036scroggo# ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED 613965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; 623965825b97a5809454f5810f7e603cbd02daa036scroggo 633965825b97a5809454f5810f7e603cbd02daa036scroggo /* In stable builds only warn if an application error can be completely 643965825b97a5809454f5810f7e603cbd02daa036scroggo * handled. 653965825b97a5809454f5810f7e603cbd02daa036scroggo */ 663965825b97a5809454f5810f7e603cbd02daa036scroggo# if PNG_RELEASE_BUILD 673965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; 683965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 693965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 703965825b97a5809454f5810f7e603cbd02daa036scroggo 713965825b97a5809454f5810f7e603cbd02daa036scroggo /* TODO: delay this, it can be done in png_init_io (if the app doesn't 723965825b97a5809454f5810f7e603cbd02daa036scroggo * do it itself) avoiding setting the default function if it is not 733965825b97a5809454f5810f7e603cbd02daa036scroggo * required. 743965825b97a5809454f5810f7e603cbd02daa036scroggo */ 753965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_read_fn(png_ptr, NULL, NULL); 763965825b97a5809454f5810f7e603cbd02daa036scroggo } 773965825b97a5809454f5810f7e603cbd02daa036scroggo 783965825b97a5809454f5810f7e603cbd02daa036scroggo return png_ptr; 793965825b97a5809454f5810f7e603cbd02daa036scroggo} 803965825b97a5809454f5810f7e603cbd02daa036scroggo 813965825b97a5809454f5810f7e603cbd02daa036scroggo 823965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 833965825b97a5809454f5810f7e603cbd02daa036scroggo/* Read the information before the actual image data. This has been 843965825b97a5809454f5810f7e603cbd02daa036scroggo * changed in v0.90 to allow reading a file that already has the magic 853965825b97a5809454f5810f7e603cbd02daa036scroggo * bytes read from the stream. You can tell libpng how many bytes have 863965825b97a5809454f5810f7e603cbd02daa036scroggo * been read from the beginning of the stream (up to the maximum of 8) 873965825b97a5809454f5810f7e603cbd02daa036scroggo * via png_set_sig_bytes(), and we will only check the remaining bytes 883965825b97a5809454f5810f7e603cbd02daa036scroggo * here. The application can then have access to the signature bytes we 893965825b97a5809454f5810f7e603cbd02daa036scroggo * read if it is determined that this isn't a valid PNG file. 903965825b97a5809454f5810f7e603cbd02daa036scroggo */ 913965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI 923965825b97a5809454f5810f7e603cbd02daa036scroggopng_read_info(png_structrp png_ptr, png_inforp info_ptr) 933965825b97a5809454f5810f7e603cbd02daa036scroggo{ 943965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 953965825b97a5809454f5810f7e603cbd02daa036scroggo int keep; 963965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 973965825b97a5809454f5810f7e603cbd02daa036scroggo 983965825b97a5809454f5810f7e603cbd02daa036scroggo png_debug(1, "in png_read_info"); 993965825b97a5809454f5810f7e603cbd02daa036scroggo 1003965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr == NULL || info_ptr == NULL) 1013965825b97a5809454f5810f7e603cbd02daa036scroggo return; 1023965825b97a5809454f5810f7e603cbd02daa036scroggo 1033965825b97a5809454f5810f7e603cbd02daa036scroggo /* Read and check the PNG file signature. */ 1043965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_sig(png_ptr, info_ptr); 1053965825b97a5809454f5810f7e603cbd02daa036scroggo 1063965825b97a5809454f5810f7e603cbd02daa036scroggo for (;;) 1073965825b97a5809454f5810f7e603cbd02daa036scroggo { 1083965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 length = png_read_chunk_header(png_ptr); 1093965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 chunk_name = png_ptr->chunk_name; 1103965825b97a5809454f5810f7e603cbd02daa036scroggo 1113965825b97a5809454f5810f7e603cbd02daa036scroggo /* IDAT logic needs to happen here to simplify getting the two flags 1123965825b97a5809454f5810f7e603cbd02daa036scroggo * right. 1133965825b97a5809454f5810f7e603cbd02daa036scroggo */ 1143965825b97a5809454f5810f7e603cbd02daa036scroggo if (chunk_name == png_IDAT) 1153965825b97a5809454f5810f7e603cbd02daa036scroggo { 1163965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->mode & PNG_HAVE_IHDR) == 0) 1173965825b97a5809454f5810f7e603cbd02daa036scroggo png_chunk_error(png_ptr, "Missing IHDR before IDAT"); 1183965825b97a5809454f5810f7e603cbd02daa036scroggo 1193965825b97a5809454f5810f7e603cbd02daa036scroggo else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && 1203965825b97a5809454f5810f7e603cbd02daa036scroggo (png_ptr->mode & PNG_HAVE_PLTE) == 0) 1213965825b97a5809454f5810f7e603cbd02daa036scroggo png_chunk_error(png_ptr, "Missing PLTE before IDAT"); 1223965825b97a5809454f5810f7e603cbd02daa036scroggo 1233965825b97a5809454f5810f7e603cbd02daa036scroggo else if ((png_ptr->mode & PNG_AFTER_IDAT) != 0) 1243965825b97a5809454f5810f7e603cbd02daa036scroggo png_chunk_benign_error(png_ptr, "Too many IDATs found"); 1253965825b97a5809454f5810f7e603cbd02daa036scroggo 1263965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->mode |= PNG_HAVE_IDAT; 1273965825b97a5809454f5810f7e603cbd02daa036scroggo } 1283965825b97a5809454f5810f7e603cbd02daa036scroggo 1293965825b97a5809454f5810f7e603cbd02daa036scroggo else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0) 1303965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->mode |= PNG_AFTER_IDAT; 1313965825b97a5809454f5810f7e603cbd02daa036scroggo 1323965825b97a5809454f5810f7e603cbd02daa036scroggo /* This should be a binary subdivision search or a hash for 1333965825b97a5809454f5810f7e603cbd02daa036scroggo * matching the chunk name rather than a linear search. 1343965825b97a5809454f5810f7e603cbd02daa036scroggo */ 1353965825b97a5809454f5810f7e603cbd02daa036scroggo if (chunk_name == png_IHDR) 1363965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_IHDR(png_ptr, info_ptr, length); 1373965825b97a5809454f5810f7e603cbd02daa036scroggo 1383965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_IEND) 1393965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_IEND(png_ptr, info_ptr, length); 1403965825b97a5809454f5810f7e603cbd02daa036scroggo 1413965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 1423965825b97a5809454f5810f7e603cbd02daa036scroggo else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) 1433965825b97a5809454f5810f7e603cbd02daa036scroggo { 1443965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_unknown(png_ptr, info_ptr, length, keep); 1453965825b97a5809454f5810f7e603cbd02daa036scroggo 1463965825b97a5809454f5810f7e603cbd02daa036scroggo if (chunk_name == png_PLTE) 1473965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->mode |= PNG_HAVE_PLTE; 1483965825b97a5809454f5810f7e603cbd02daa036scroggo 1493965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_IDAT) 1503965825b97a5809454f5810f7e603cbd02daa036scroggo { 1513965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->idat_size = 0; /* It has been consumed */ 1523965825b97a5809454f5810f7e603cbd02daa036scroggo break; 1533965825b97a5809454f5810f7e603cbd02daa036scroggo } 1543965825b97a5809454f5810f7e603cbd02daa036scroggo } 1553965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 1563965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_PLTE) 1573965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_PLTE(png_ptr, info_ptr, length); 1583965825b97a5809454f5810f7e603cbd02daa036scroggo 1593965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_IDAT) 1603965825b97a5809454f5810f7e603cbd02daa036scroggo { 1613965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->idat_size = length; 1623965825b97a5809454f5810f7e603cbd02daa036scroggo break; 1633965825b97a5809454f5810f7e603cbd02daa036scroggo } 1643965825b97a5809454f5810f7e603cbd02daa036scroggo 1653965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_bKGD_SUPPORTED 1663965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_bKGD) 1673965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_bKGD(png_ptr, info_ptr, length); 1683965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 1693965825b97a5809454f5810f7e603cbd02daa036scroggo 1703965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_cHRM_SUPPORTED 1713965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_cHRM) 1723965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_cHRM(png_ptr, info_ptr, length); 1733965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 1743965825b97a5809454f5810f7e603cbd02daa036scroggo 1753965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_gAMA_SUPPORTED 1763965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_gAMA) 1773965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_gAMA(png_ptr, info_ptr, length); 1783965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 1793965825b97a5809454f5810f7e603cbd02daa036scroggo 1803965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_hIST_SUPPORTED 1813965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_hIST) 1823965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_hIST(png_ptr, info_ptr, length); 1833965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 1843965825b97a5809454f5810f7e603cbd02daa036scroggo 1853965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_oFFs_SUPPORTED 1863965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_oFFs) 1873965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_oFFs(png_ptr, info_ptr, length); 1883965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 1893965825b97a5809454f5810f7e603cbd02daa036scroggo 1903965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_pCAL_SUPPORTED 1913965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_pCAL) 1923965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_pCAL(png_ptr, info_ptr, length); 1933965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 1943965825b97a5809454f5810f7e603cbd02daa036scroggo 1953965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sCAL_SUPPORTED 1963965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_sCAL) 1973965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_sCAL(png_ptr, info_ptr, length); 1983965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 1993965825b97a5809454f5810f7e603cbd02daa036scroggo 2003965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_pHYs_SUPPORTED 2013965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_pHYs) 2023965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_pHYs(png_ptr, info_ptr, length); 2033965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 2043965825b97a5809454f5810f7e603cbd02daa036scroggo 2053965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sBIT_SUPPORTED 2063965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_sBIT) 2073965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_sBIT(png_ptr, info_ptr, length); 2083965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 2093965825b97a5809454f5810f7e603cbd02daa036scroggo 2103965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sRGB_SUPPORTED 2113965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_sRGB) 2123965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_sRGB(png_ptr, info_ptr, length); 2133965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 2143965825b97a5809454f5810f7e603cbd02daa036scroggo 2153965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_iCCP_SUPPORTED 2163965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_iCCP) 2173965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_iCCP(png_ptr, info_ptr, length); 2183965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 2193965825b97a5809454f5810f7e603cbd02daa036scroggo 2203965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sPLT_SUPPORTED 2213965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_sPLT) 2223965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_sPLT(png_ptr, info_ptr, length); 2233965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 2243965825b97a5809454f5810f7e603cbd02daa036scroggo 2253965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_tEXt_SUPPORTED 2263965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_tEXt) 2273965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_tEXt(png_ptr, info_ptr, length); 2283965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 2293965825b97a5809454f5810f7e603cbd02daa036scroggo 2303965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_tIME_SUPPORTED 2313965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_tIME) 2323965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_tIME(png_ptr, info_ptr, length); 2333965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 2343965825b97a5809454f5810f7e603cbd02daa036scroggo 2353965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_tRNS_SUPPORTED 2363965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_tRNS) 2373965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_tRNS(png_ptr, info_ptr, length); 2383965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 2393965825b97a5809454f5810f7e603cbd02daa036scroggo 2403965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_zTXt_SUPPORTED 2413965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_zTXt) 2423965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_zTXt(png_ptr, info_ptr, length); 2433965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 2443965825b97a5809454f5810f7e603cbd02daa036scroggo 2453965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_iTXt_SUPPORTED 2463965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_iTXt) 2473965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_iTXt(png_ptr, info_ptr, length); 2483965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 2493965825b97a5809454f5810f7e603cbd02daa036scroggo 2503965825b97a5809454f5810f7e603cbd02daa036scroggo else 2513965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_unknown(png_ptr, info_ptr, length, 2523965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_HANDLE_CHUNK_AS_DEFAULT); 2533965825b97a5809454f5810f7e603cbd02daa036scroggo } 2543965825b97a5809454f5810f7e603cbd02daa036scroggo} 2553965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* SEQUENTIAL_READ */ 2563965825b97a5809454f5810f7e603cbd02daa036scroggo 2573965825b97a5809454f5810f7e603cbd02daa036scroggo/* Optional call to update the users info_ptr structure */ 2583965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI 2593965825b97a5809454f5810f7e603cbd02daa036scroggopng_read_update_info(png_structrp png_ptr, png_inforp info_ptr) 2603965825b97a5809454f5810f7e603cbd02daa036scroggo{ 2613965825b97a5809454f5810f7e603cbd02daa036scroggo png_debug(1, "in png_read_update_info"); 2623965825b97a5809454f5810f7e603cbd02daa036scroggo 2633965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr != NULL) 2643965825b97a5809454f5810f7e603cbd02daa036scroggo { 2653965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) 2663965825b97a5809454f5810f7e603cbd02daa036scroggo { 2673965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_start_row(png_ptr); 2683965825b97a5809454f5810f7e603cbd02daa036scroggo 2693965825b97a5809454f5810f7e603cbd02daa036scroggo# ifdef PNG_READ_TRANSFORMS_SUPPORTED 2703965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_transform_info(png_ptr, info_ptr); 2713965825b97a5809454f5810f7e603cbd02daa036scroggo# else 2723965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_UNUSED(info_ptr) 2733965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 2743965825b97a5809454f5810f7e603cbd02daa036scroggo } 2753965825b97a5809454f5810f7e603cbd02daa036scroggo 2763965825b97a5809454f5810f7e603cbd02daa036scroggo /* New in 1.6.0 this avoids the bug of doing the initializations twice */ 2773965825b97a5809454f5810f7e603cbd02daa036scroggo else 2783965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, 2793965825b97a5809454f5810f7e603cbd02daa036scroggo "png_read_update_info/png_start_read_image: duplicate call"); 2803965825b97a5809454f5810f7e603cbd02daa036scroggo } 2813965825b97a5809454f5810f7e603cbd02daa036scroggo} 2823965825b97a5809454f5810f7e603cbd02daa036scroggo 2833965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 2843965825b97a5809454f5810f7e603cbd02daa036scroggo/* Initialize palette, background, etc, after transformations 2853965825b97a5809454f5810f7e603cbd02daa036scroggo * are set, but before any reading takes place. This allows 2863965825b97a5809454f5810f7e603cbd02daa036scroggo * the user to obtain a gamma-corrected palette, for example. 2873965825b97a5809454f5810f7e603cbd02daa036scroggo * If the user doesn't call this, we will do it ourselves. 2883965825b97a5809454f5810f7e603cbd02daa036scroggo */ 2893965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI 2903965825b97a5809454f5810f7e603cbd02daa036scroggopng_start_read_image(png_structrp png_ptr) 2913965825b97a5809454f5810f7e603cbd02daa036scroggo{ 2923965825b97a5809454f5810f7e603cbd02daa036scroggo png_debug(1, "in png_start_read_image"); 2933965825b97a5809454f5810f7e603cbd02daa036scroggo 2943965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr != NULL) 2953965825b97a5809454f5810f7e603cbd02daa036scroggo { 2963965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) 2973965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_start_row(png_ptr); 2983965825b97a5809454f5810f7e603cbd02daa036scroggo 2993965825b97a5809454f5810f7e603cbd02daa036scroggo /* New in 1.6.0 this avoids the bug of doing the initializations twice */ 3003965825b97a5809454f5810f7e603cbd02daa036scroggo else 3013965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, 3023965825b97a5809454f5810f7e603cbd02daa036scroggo "png_start_read_image/png_read_update_info: duplicate call"); 3033965825b97a5809454f5810f7e603cbd02daa036scroggo } 3043965825b97a5809454f5810f7e603cbd02daa036scroggo} 3053965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* SEQUENTIAL_READ */ 3063965825b97a5809454f5810f7e603cbd02daa036scroggo 3073965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 3083965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_MNG_FEATURES_SUPPORTED 3093965825b97a5809454f5810f7e603cbd02daa036scroggo/* Undoes intrapixel differencing, 3103965825b97a5809454f5810f7e603cbd02daa036scroggo * NOTE: this is apparently only supported in the 'sequential' reader. 3113965825b97a5809454f5810f7e603cbd02daa036scroggo */ 3123965825b97a5809454f5810f7e603cbd02daa036scroggostatic void 3133965825b97a5809454f5810f7e603cbd02daa036scroggopng_do_read_intrapixel(png_row_infop row_info, png_bytep row) 3143965825b97a5809454f5810f7e603cbd02daa036scroggo{ 3153965825b97a5809454f5810f7e603cbd02daa036scroggo png_debug(1, "in png_do_read_intrapixel"); 3163965825b97a5809454f5810f7e603cbd02daa036scroggo 3173965825b97a5809454f5810f7e603cbd02daa036scroggo if ( 3183965825b97a5809454f5810f7e603cbd02daa036scroggo (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) 3193965825b97a5809454f5810f7e603cbd02daa036scroggo { 3203965825b97a5809454f5810f7e603cbd02daa036scroggo int bytes_per_pixel; 3213965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 row_width = row_info->width; 3223965825b97a5809454f5810f7e603cbd02daa036scroggo 3233965825b97a5809454f5810f7e603cbd02daa036scroggo if (row_info->bit_depth == 8) 3243965825b97a5809454f5810f7e603cbd02daa036scroggo { 3253965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep rp; 3263965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 i; 3273965825b97a5809454f5810f7e603cbd02daa036scroggo 3283965825b97a5809454f5810f7e603cbd02daa036scroggo if (row_info->color_type == PNG_COLOR_TYPE_RGB) 3293965825b97a5809454f5810f7e603cbd02daa036scroggo bytes_per_pixel = 3; 3303965825b97a5809454f5810f7e603cbd02daa036scroggo 3313965825b97a5809454f5810f7e603cbd02daa036scroggo else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 3323965825b97a5809454f5810f7e603cbd02daa036scroggo bytes_per_pixel = 4; 3333965825b97a5809454f5810f7e603cbd02daa036scroggo 3343965825b97a5809454f5810f7e603cbd02daa036scroggo else 3353965825b97a5809454f5810f7e603cbd02daa036scroggo return; 3363965825b97a5809454f5810f7e603cbd02daa036scroggo 3373965825b97a5809454f5810f7e603cbd02daa036scroggo for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 3383965825b97a5809454f5810f7e603cbd02daa036scroggo { 3393965825b97a5809454f5810f7e603cbd02daa036scroggo *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff); 3403965825b97a5809454f5810f7e603cbd02daa036scroggo *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff); 3413965825b97a5809454f5810f7e603cbd02daa036scroggo } 3423965825b97a5809454f5810f7e603cbd02daa036scroggo } 3433965825b97a5809454f5810f7e603cbd02daa036scroggo else if (row_info->bit_depth == 16) 3443965825b97a5809454f5810f7e603cbd02daa036scroggo { 3453965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep rp; 3463965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 i; 3473965825b97a5809454f5810f7e603cbd02daa036scroggo 3483965825b97a5809454f5810f7e603cbd02daa036scroggo if (row_info->color_type == PNG_COLOR_TYPE_RGB) 3493965825b97a5809454f5810f7e603cbd02daa036scroggo bytes_per_pixel = 6; 3503965825b97a5809454f5810f7e603cbd02daa036scroggo 3513965825b97a5809454f5810f7e603cbd02daa036scroggo else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 3523965825b97a5809454f5810f7e603cbd02daa036scroggo bytes_per_pixel = 8; 3533965825b97a5809454f5810f7e603cbd02daa036scroggo 3543965825b97a5809454f5810f7e603cbd02daa036scroggo else 3553965825b97a5809454f5810f7e603cbd02daa036scroggo return; 3563965825b97a5809454f5810f7e603cbd02daa036scroggo 3573965825b97a5809454f5810f7e603cbd02daa036scroggo for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 3583965825b97a5809454f5810f7e603cbd02daa036scroggo { 3593965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); 3603965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); 3613965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); 3623965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 red = (s0 + s1 + 65536) & 0xffff; 3633965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; 3643965825b97a5809454f5810f7e603cbd02daa036scroggo *(rp ) = (png_byte)((red >> 8) & 0xff); 3653965825b97a5809454f5810f7e603cbd02daa036scroggo *(rp + 1) = (png_byte)(red & 0xff); 3663965825b97a5809454f5810f7e603cbd02daa036scroggo *(rp + 4) = (png_byte)((blue >> 8) & 0xff); 3673965825b97a5809454f5810f7e603cbd02daa036scroggo *(rp + 5) = (png_byte)(blue & 0xff); 3683965825b97a5809454f5810f7e603cbd02daa036scroggo } 3693965825b97a5809454f5810f7e603cbd02daa036scroggo } 3703965825b97a5809454f5810f7e603cbd02daa036scroggo } 3713965825b97a5809454f5810f7e603cbd02daa036scroggo} 3723965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* MNG_FEATURES */ 3733965825b97a5809454f5810f7e603cbd02daa036scroggo 3743965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI 3753965825b97a5809454f5810f7e603cbd02daa036scroggopng_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) 3763965825b97a5809454f5810f7e603cbd02daa036scroggo{ 3773965825b97a5809454f5810f7e603cbd02daa036scroggo png_row_info row_info; 3783965825b97a5809454f5810f7e603cbd02daa036scroggo 3793965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr == NULL) 3803965825b97a5809454f5810f7e603cbd02daa036scroggo return; 3813965825b97a5809454f5810f7e603cbd02daa036scroggo 3823965825b97a5809454f5810f7e603cbd02daa036scroggo png_debug2(1, "in png_read_row (row %lu, pass %d)", 3833965825b97a5809454f5810f7e603cbd02daa036scroggo (unsigned long)png_ptr->row_number, png_ptr->pass); 3843965825b97a5809454f5810f7e603cbd02daa036scroggo 3853965825b97a5809454f5810f7e603cbd02daa036scroggo /* png_read_start_row sets the information (in particular iwidth) for this 3863965825b97a5809454f5810f7e603cbd02daa036scroggo * interlace pass. 3873965825b97a5809454f5810f7e603cbd02daa036scroggo */ 3883965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) 3893965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_start_row(png_ptr); 3903965825b97a5809454f5810f7e603cbd02daa036scroggo 3913965825b97a5809454f5810f7e603cbd02daa036scroggo /* 1.5.6: row_info moved out of png_struct to a local here. */ 3923965825b97a5809454f5810f7e603cbd02daa036scroggo row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ 3933965825b97a5809454f5810f7e603cbd02daa036scroggo row_info.color_type = png_ptr->color_type; 3943965825b97a5809454f5810f7e603cbd02daa036scroggo row_info.bit_depth = png_ptr->bit_depth; 3953965825b97a5809454f5810f7e603cbd02daa036scroggo row_info.channels = png_ptr->channels; 3963965825b97a5809454f5810f7e603cbd02daa036scroggo row_info.pixel_depth = png_ptr->pixel_depth; 3973965825b97a5809454f5810f7e603cbd02daa036scroggo row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); 3983965825b97a5809454f5810f7e603cbd02daa036scroggo 3993965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_WARNINGS_SUPPORTED 4003965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->row_number == 0 && png_ptr->pass == 0) 4013965825b97a5809454f5810f7e603cbd02daa036scroggo { 4023965825b97a5809454f5810f7e603cbd02daa036scroggo /* Check for transforms that have been set but were defined out */ 4033965825b97a5809454f5810f7e603cbd02daa036scroggo#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) 4043965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->transformations & PNG_INVERT_MONO) != 0) 4053965825b97a5809454f5810f7e603cbd02daa036scroggo png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined"); 4063965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 4073965825b97a5809454f5810f7e603cbd02daa036scroggo 4083965825b97a5809454f5810f7e603cbd02daa036scroggo#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) 4093965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->transformations & PNG_FILLER) != 0) 4103965825b97a5809454f5810f7e603cbd02daa036scroggo png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined"); 4113965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 4123965825b97a5809454f5810f7e603cbd02daa036scroggo 4133965825b97a5809454f5810f7e603cbd02daa036scroggo#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ 4143965825b97a5809454f5810f7e603cbd02daa036scroggo !defined(PNG_READ_PACKSWAP_SUPPORTED) 4153965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->transformations & PNG_PACKSWAP) != 0) 4163965825b97a5809454f5810f7e603cbd02daa036scroggo png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined"); 4173965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 4183965825b97a5809454f5810f7e603cbd02daa036scroggo 4193965825b97a5809454f5810f7e603cbd02daa036scroggo#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) 4203965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->transformations & PNG_PACK) != 0) 4213965825b97a5809454f5810f7e603cbd02daa036scroggo png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined"); 4223965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 4233965825b97a5809454f5810f7e603cbd02daa036scroggo 4243965825b97a5809454f5810f7e603cbd02daa036scroggo#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) 4253965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->transformations & PNG_SHIFT) != 0) 4263965825b97a5809454f5810f7e603cbd02daa036scroggo png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined"); 4273965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 4283965825b97a5809454f5810f7e603cbd02daa036scroggo 4293965825b97a5809454f5810f7e603cbd02daa036scroggo#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) 4303965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->transformations & PNG_BGR) != 0) 4313965825b97a5809454f5810f7e603cbd02daa036scroggo png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined"); 4323965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 4333965825b97a5809454f5810f7e603cbd02daa036scroggo 4343965825b97a5809454f5810f7e603cbd02daa036scroggo#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) 4353965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0) 4363965825b97a5809454f5810f7e603cbd02daa036scroggo png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined"); 4373965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 4383965825b97a5809454f5810f7e603cbd02daa036scroggo } 4393965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* WARNINGS */ 4403965825b97a5809454f5810f7e603cbd02daa036scroggo 4413965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_INTERLACING_SUPPORTED 4423965825b97a5809454f5810f7e603cbd02daa036scroggo /* If interlaced and we do not need a new row, combine row and return. 4433965825b97a5809454f5810f7e603cbd02daa036scroggo * Notice that the pixels we have from previous rows have been transformed 4443965825b97a5809454f5810f7e603cbd02daa036scroggo * already; we can only combine like with like (transformed or 4453965825b97a5809454f5810f7e603cbd02daa036scroggo * untransformed) and, because of the libpng API for interlaced images, this 4463965825b97a5809454f5810f7e603cbd02daa036scroggo * means we must transform before de-interlacing. 4473965825b97a5809454f5810f7e603cbd02daa036scroggo */ 4483965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->interlaced != 0 && 4493965825b97a5809454f5810f7e603cbd02daa036scroggo (png_ptr->transformations & PNG_INTERLACE) != 0) 4503965825b97a5809454f5810f7e603cbd02daa036scroggo { 4513965825b97a5809454f5810f7e603cbd02daa036scroggo switch (png_ptr->pass) 4523965825b97a5809454f5810f7e603cbd02daa036scroggo { 4533965825b97a5809454f5810f7e603cbd02daa036scroggo case 0: 4543965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->row_number & 0x07) 4553965825b97a5809454f5810f7e603cbd02daa036scroggo { 4563965825b97a5809454f5810f7e603cbd02daa036scroggo if (dsp_row != NULL) 4573965825b97a5809454f5810f7e603cbd02daa036scroggo png_combine_row(png_ptr, dsp_row, 1/*display*/); 4583965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_finish_row(png_ptr); 4593965825b97a5809454f5810f7e603cbd02daa036scroggo return; 4603965825b97a5809454f5810f7e603cbd02daa036scroggo } 4613965825b97a5809454f5810f7e603cbd02daa036scroggo break; 4623965825b97a5809454f5810f7e603cbd02daa036scroggo 4633965825b97a5809454f5810f7e603cbd02daa036scroggo case 1: 4643965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) 4653965825b97a5809454f5810f7e603cbd02daa036scroggo { 4663965825b97a5809454f5810f7e603cbd02daa036scroggo if (dsp_row != NULL) 4673965825b97a5809454f5810f7e603cbd02daa036scroggo png_combine_row(png_ptr, dsp_row, 1/*display*/); 4683965825b97a5809454f5810f7e603cbd02daa036scroggo 4693965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_finish_row(png_ptr); 4703965825b97a5809454f5810f7e603cbd02daa036scroggo return; 4713965825b97a5809454f5810f7e603cbd02daa036scroggo } 4723965825b97a5809454f5810f7e603cbd02daa036scroggo break; 4733965825b97a5809454f5810f7e603cbd02daa036scroggo 4743965825b97a5809454f5810f7e603cbd02daa036scroggo case 2: 4753965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->row_number & 0x07) != 4) 4763965825b97a5809454f5810f7e603cbd02daa036scroggo { 4773965825b97a5809454f5810f7e603cbd02daa036scroggo if (dsp_row != NULL && (png_ptr->row_number & 4)) 4783965825b97a5809454f5810f7e603cbd02daa036scroggo png_combine_row(png_ptr, dsp_row, 1/*display*/); 4793965825b97a5809454f5810f7e603cbd02daa036scroggo 4803965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_finish_row(png_ptr); 4813965825b97a5809454f5810f7e603cbd02daa036scroggo return; 4823965825b97a5809454f5810f7e603cbd02daa036scroggo } 4833965825b97a5809454f5810f7e603cbd02daa036scroggo break; 4843965825b97a5809454f5810f7e603cbd02daa036scroggo 4853965825b97a5809454f5810f7e603cbd02daa036scroggo case 3: 4863965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->row_number & 3) || png_ptr->width < 3) 4873965825b97a5809454f5810f7e603cbd02daa036scroggo { 4883965825b97a5809454f5810f7e603cbd02daa036scroggo if (dsp_row != NULL) 4893965825b97a5809454f5810f7e603cbd02daa036scroggo png_combine_row(png_ptr, dsp_row, 1/*display*/); 4903965825b97a5809454f5810f7e603cbd02daa036scroggo 4913965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_finish_row(png_ptr); 4923965825b97a5809454f5810f7e603cbd02daa036scroggo return; 4933965825b97a5809454f5810f7e603cbd02daa036scroggo } 4943965825b97a5809454f5810f7e603cbd02daa036scroggo break; 4953965825b97a5809454f5810f7e603cbd02daa036scroggo 4963965825b97a5809454f5810f7e603cbd02daa036scroggo case 4: 4973965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->row_number & 3) != 2) 4983965825b97a5809454f5810f7e603cbd02daa036scroggo { 4993965825b97a5809454f5810f7e603cbd02daa036scroggo if (dsp_row != NULL && (png_ptr->row_number & 2)) 5003965825b97a5809454f5810f7e603cbd02daa036scroggo png_combine_row(png_ptr, dsp_row, 1/*display*/); 5013965825b97a5809454f5810f7e603cbd02daa036scroggo 5023965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_finish_row(png_ptr); 5033965825b97a5809454f5810f7e603cbd02daa036scroggo return; 5043965825b97a5809454f5810f7e603cbd02daa036scroggo } 5053965825b97a5809454f5810f7e603cbd02daa036scroggo break; 5063965825b97a5809454f5810f7e603cbd02daa036scroggo 5073965825b97a5809454f5810f7e603cbd02daa036scroggo case 5: 5083965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->row_number & 1) || png_ptr->width < 2) 5093965825b97a5809454f5810f7e603cbd02daa036scroggo { 5103965825b97a5809454f5810f7e603cbd02daa036scroggo if (dsp_row != NULL) 5113965825b97a5809454f5810f7e603cbd02daa036scroggo png_combine_row(png_ptr, dsp_row, 1/*display*/); 5123965825b97a5809454f5810f7e603cbd02daa036scroggo 5133965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_finish_row(png_ptr); 5143965825b97a5809454f5810f7e603cbd02daa036scroggo return; 5153965825b97a5809454f5810f7e603cbd02daa036scroggo } 5163965825b97a5809454f5810f7e603cbd02daa036scroggo break; 5173965825b97a5809454f5810f7e603cbd02daa036scroggo 5183965825b97a5809454f5810f7e603cbd02daa036scroggo default: 5193965825b97a5809454f5810f7e603cbd02daa036scroggo case 6: 5203965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->row_number & 1) == 0) 5213965825b97a5809454f5810f7e603cbd02daa036scroggo { 5223965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_finish_row(png_ptr); 5233965825b97a5809454f5810f7e603cbd02daa036scroggo return; 5243965825b97a5809454f5810f7e603cbd02daa036scroggo } 5253965825b97a5809454f5810f7e603cbd02daa036scroggo break; 5263965825b97a5809454f5810f7e603cbd02daa036scroggo } 5273965825b97a5809454f5810f7e603cbd02daa036scroggo } 5283965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 5293965825b97a5809454f5810f7e603cbd02daa036scroggo 5303965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->mode & PNG_HAVE_IDAT) == 0) 5313965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "Invalid attempt to read row data"); 5323965825b97a5809454f5810f7e603cbd02daa036scroggo 5333965825b97a5809454f5810f7e603cbd02daa036scroggo /* Fill the row with IDAT data: */ 5343965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1); 5353965825b97a5809454f5810f7e603cbd02daa036scroggo 5363965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) 5373965825b97a5809454f5810f7e603cbd02daa036scroggo { 5383965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) 5393965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, 5403965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->prev_row + 1, png_ptr->row_buf[0]); 5413965825b97a5809454f5810f7e603cbd02daa036scroggo else 5423965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "bad adaptive filter value"); 5433965825b97a5809454f5810f7e603cbd02daa036scroggo } 5443965825b97a5809454f5810f7e603cbd02daa036scroggo 5453965825b97a5809454f5810f7e603cbd02daa036scroggo /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before 5463965825b97a5809454f5810f7e603cbd02daa036scroggo * 1.5.6, while the buffer really is this big in current versions of libpng 5473965825b97a5809454f5810f7e603cbd02daa036scroggo * it may not be in the future, so this was changed just to copy the 5483965825b97a5809454f5810f7e603cbd02daa036scroggo * interlaced count: 5493965825b97a5809454f5810f7e603cbd02daa036scroggo */ 5503965825b97a5809454f5810f7e603cbd02daa036scroggo memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); 5513965825b97a5809454f5810f7e603cbd02daa036scroggo 5523965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_MNG_FEATURES_SUPPORTED 5533965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 && 5543965825b97a5809454f5810f7e603cbd02daa036scroggo (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) 5553965825b97a5809454f5810f7e603cbd02daa036scroggo { 5563965825b97a5809454f5810f7e603cbd02daa036scroggo /* Intrapixel differencing */ 5573965825b97a5809454f5810f7e603cbd02daa036scroggo png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1); 5583965825b97a5809454f5810f7e603cbd02daa036scroggo } 5593965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 5603965825b97a5809454f5810f7e603cbd02daa036scroggo 5613965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_TRANSFORMS_SUPPORTED 5623965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->transformations) 5633965825b97a5809454f5810f7e603cbd02daa036scroggo png_do_read_transformations(png_ptr, &row_info); 5643965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 5653965825b97a5809454f5810f7e603cbd02daa036scroggo 5663965825b97a5809454f5810f7e603cbd02daa036scroggo /* The transformed pixel depth should match the depth now in row_info. */ 5673965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->transformed_pixel_depth == 0) 5683965825b97a5809454f5810f7e603cbd02daa036scroggo { 5693965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->transformed_pixel_depth = row_info.pixel_depth; 5703965825b97a5809454f5810f7e603cbd02daa036scroggo if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) 5713965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "sequential row overflow"); 5723965825b97a5809454f5810f7e603cbd02daa036scroggo } 5733965825b97a5809454f5810f7e603cbd02daa036scroggo 5743965825b97a5809454f5810f7e603cbd02daa036scroggo else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) 5753965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "internal sequential row size calculation error"); 5763965825b97a5809454f5810f7e603cbd02daa036scroggo 5773965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_INTERLACING_SUPPORTED 5783965825b97a5809454f5810f7e603cbd02daa036scroggo /* Expand interlaced rows to full size */ 5793965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->interlaced != 0 && 5803965825b97a5809454f5810f7e603cbd02daa036scroggo (png_ptr->transformations & PNG_INTERLACE) != 0) 5813965825b97a5809454f5810f7e603cbd02daa036scroggo { 5823965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->pass < 6) 5833965825b97a5809454f5810f7e603cbd02daa036scroggo png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, 5843965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->transformations); 5853965825b97a5809454f5810f7e603cbd02daa036scroggo 5863965825b97a5809454f5810f7e603cbd02daa036scroggo if (dsp_row != NULL) 5873965825b97a5809454f5810f7e603cbd02daa036scroggo png_combine_row(png_ptr, dsp_row, 1/*display*/); 5883965825b97a5809454f5810f7e603cbd02daa036scroggo 5893965825b97a5809454f5810f7e603cbd02daa036scroggo if (row != NULL) 5903965825b97a5809454f5810f7e603cbd02daa036scroggo png_combine_row(png_ptr, row, 0/*row*/); 5913965825b97a5809454f5810f7e603cbd02daa036scroggo } 5923965825b97a5809454f5810f7e603cbd02daa036scroggo 5933965825b97a5809454f5810f7e603cbd02daa036scroggo else 5943965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 5953965825b97a5809454f5810f7e603cbd02daa036scroggo { 5963965825b97a5809454f5810f7e603cbd02daa036scroggo if (row != NULL) 5973965825b97a5809454f5810f7e603cbd02daa036scroggo png_combine_row(png_ptr, row, -1/*ignored*/); 5983965825b97a5809454f5810f7e603cbd02daa036scroggo 5993965825b97a5809454f5810f7e603cbd02daa036scroggo if (dsp_row != NULL) 6003965825b97a5809454f5810f7e603cbd02daa036scroggo png_combine_row(png_ptr, dsp_row, -1/*ignored*/); 6013965825b97a5809454f5810f7e603cbd02daa036scroggo } 6023965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_finish_row(png_ptr); 6033965825b97a5809454f5810f7e603cbd02daa036scroggo 6043965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->read_row_fn != NULL) 6053965825b97a5809454f5810f7e603cbd02daa036scroggo (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); 6063965825b97a5809454f5810f7e603cbd02daa036scroggo 6073965825b97a5809454f5810f7e603cbd02daa036scroggo} 6083965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* SEQUENTIAL_READ */ 6093965825b97a5809454f5810f7e603cbd02daa036scroggo 6103965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 6113965825b97a5809454f5810f7e603cbd02daa036scroggo/* Read one or more rows of image data. If the image is interlaced, 6123965825b97a5809454f5810f7e603cbd02daa036scroggo * and png_set_interlace_handling() has been called, the rows need to 6133965825b97a5809454f5810f7e603cbd02daa036scroggo * contain the contents of the rows from the previous pass. If the 6143965825b97a5809454f5810f7e603cbd02daa036scroggo * image has alpha or transparency, and png_handle_alpha()[*] has been 6153965825b97a5809454f5810f7e603cbd02daa036scroggo * called, the rows contents must be initialized to the contents of the 6163965825b97a5809454f5810f7e603cbd02daa036scroggo * screen. 6173965825b97a5809454f5810f7e603cbd02daa036scroggo * 6183965825b97a5809454f5810f7e603cbd02daa036scroggo * "row" holds the actual image, and pixels are placed in it 6193965825b97a5809454f5810f7e603cbd02daa036scroggo * as they arrive. If the image is displayed after each pass, it will 6203965825b97a5809454f5810f7e603cbd02daa036scroggo * appear to "sparkle" in. "display_row" can be used to display a 6213965825b97a5809454f5810f7e603cbd02daa036scroggo * "chunky" progressive image, with finer detail added as it becomes 6223965825b97a5809454f5810f7e603cbd02daa036scroggo * available. If you do not want this "chunky" display, you may pass 6233965825b97a5809454f5810f7e603cbd02daa036scroggo * NULL for display_row. If you do not want the sparkle display, and 6243965825b97a5809454f5810f7e603cbd02daa036scroggo * you have not called png_handle_alpha(), you may pass NULL for rows. 6253965825b97a5809454f5810f7e603cbd02daa036scroggo * If you have called png_handle_alpha(), and the image has either an 6263965825b97a5809454f5810f7e603cbd02daa036scroggo * alpha channel or a transparency chunk, you must provide a buffer for 6273965825b97a5809454f5810f7e603cbd02daa036scroggo * rows. In this case, you do not have to provide a display_row buffer 6283965825b97a5809454f5810f7e603cbd02daa036scroggo * also, but you may. If the image is not interlaced, or if you have 6293965825b97a5809454f5810f7e603cbd02daa036scroggo * not called png_set_interlace_handling(), the display_row buffer will 6303965825b97a5809454f5810f7e603cbd02daa036scroggo * be ignored, so pass NULL to it. 6313965825b97a5809454f5810f7e603cbd02daa036scroggo * 6323965825b97a5809454f5810f7e603cbd02daa036scroggo * [*] png_handle_alpha() does not exist yet, as of this version of libpng 6333965825b97a5809454f5810f7e603cbd02daa036scroggo */ 6343965825b97a5809454f5810f7e603cbd02daa036scroggo 6353965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI 6363965825b97a5809454f5810f7e603cbd02daa036scroggopng_read_rows(png_structrp png_ptr, png_bytepp row, 6373965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytepp display_row, png_uint_32 num_rows) 6383965825b97a5809454f5810f7e603cbd02daa036scroggo{ 6393965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 i; 6403965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytepp rp; 6413965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytepp dp; 6423965825b97a5809454f5810f7e603cbd02daa036scroggo 6433965825b97a5809454f5810f7e603cbd02daa036scroggo png_debug(1, "in png_read_rows"); 6443965825b97a5809454f5810f7e603cbd02daa036scroggo 6453965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr == NULL) 6463965825b97a5809454f5810f7e603cbd02daa036scroggo return; 6473965825b97a5809454f5810f7e603cbd02daa036scroggo 6483965825b97a5809454f5810f7e603cbd02daa036scroggo rp = row; 6493965825b97a5809454f5810f7e603cbd02daa036scroggo dp = display_row; 6503965825b97a5809454f5810f7e603cbd02daa036scroggo if (rp != NULL && dp != NULL) 6513965825b97a5809454f5810f7e603cbd02daa036scroggo for (i = 0; i < num_rows; i++) 6523965825b97a5809454f5810f7e603cbd02daa036scroggo { 6533965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep rptr = *rp++; 6543965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep dptr = *dp++; 6553965825b97a5809454f5810f7e603cbd02daa036scroggo 6563965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_row(png_ptr, rptr, dptr); 6573965825b97a5809454f5810f7e603cbd02daa036scroggo } 6583965825b97a5809454f5810f7e603cbd02daa036scroggo 6593965825b97a5809454f5810f7e603cbd02daa036scroggo else if (rp != NULL) 6603965825b97a5809454f5810f7e603cbd02daa036scroggo for (i = 0; i < num_rows; i++) 6613965825b97a5809454f5810f7e603cbd02daa036scroggo { 6623965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep rptr = *rp; 6633965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_row(png_ptr, rptr, NULL); 6643965825b97a5809454f5810f7e603cbd02daa036scroggo rp++; 6653965825b97a5809454f5810f7e603cbd02daa036scroggo } 6663965825b97a5809454f5810f7e603cbd02daa036scroggo 6673965825b97a5809454f5810f7e603cbd02daa036scroggo else if (dp != NULL) 6683965825b97a5809454f5810f7e603cbd02daa036scroggo for (i = 0; i < num_rows; i++) 6693965825b97a5809454f5810f7e603cbd02daa036scroggo { 6703965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep dptr = *dp; 6713965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_row(png_ptr, NULL, dptr); 6723965825b97a5809454f5810f7e603cbd02daa036scroggo dp++; 6733965825b97a5809454f5810f7e603cbd02daa036scroggo } 6743965825b97a5809454f5810f7e603cbd02daa036scroggo} 6753965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* SEQUENTIAL_READ */ 6763965825b97a5809454f5810f7e603cbd02daa036scroggo 6773965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 6783965825b97a5809454f5810f7e603cbd02daa036scroggo/* Read the entire image. If the image has an alpha channel or a tRNS 6793965825b97a5809454f5810f7e603cbd02daa036scroggo * chunk, and you have called png_handle_alpha()[*], you will need to 6803965825b97a5809454f5810f7e603cbd02daa036scroggo * initialize the image to the current image that PNG will be overlaying. 6813965825b97a5809454f5810f7e603cbd02daa036scroggo * We set the num_rows again here, in case it was incorrectly set in 6823965825b97a5809454f5810f7e603cbd02daa036scroggo * png_read_start_row() by a call to png_read_update_info() or 6833965825b97a5809454f5810f7e603cbd02daa036scroggo * png_start_read_image() if png_set_interlace_handling() wasn't called 6843965825b97a5809454f5810f7e603cbd02daa036scroggo * prior to either of these functions like it should have been. You can 6853965825b97a5809454f5810f7e603cbd02daa036scroggo * only call this function once. If you desire to have an image for 6863965825b97a5809454f5810f7e603cbd02daa036scroggo * each pass of a interlaced image, use png_read_rows() instead. 6873965825b97a5809454f5810f7e603cbd02daa036scroggo * 6883965825b97a5809454f5810f7e603cbd02daa036scroggo * [*] png_handle_alpha() does not exist yet, as of this version of libpng 6893965825b97a5809454f5810f7e603cbd02daa036scroggo */ 6903965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI 6913965825b97a5809454f5810f7e603cbd02daa036scroggopng_read_image(png_structrp png_ptr, png_bytepp image) 6923965825b97a5809454f5810f7e603cbd02daa036scroggo{ 6933965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 i, image_height; 6943965825b97a5809454f5810f7e603cbd02daa036scroggo int pass, j; 6953965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytepp rp; 6963965825b97a5809454f5810f7e603cbd02daa036scroggo 6973965825b97a5809454f5810f7e603cbd02daa036scroggo png_debug(1, "in png_read_image"); 6983965825b97a5809454f5810f7e603cbd02daa036scroggo 6993965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr == NULL) 7003965825b97a5809454f5810f7e603cbd02daa036scroggo return; 7013965825b97a5809454f5810f7e603cbd02daa036scroggo 7023965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_INTERLACING_SUPPORTED 7033965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) 7043965825b97a5809454f5810f7e603cbd02daa036scroggo { 7053965825b97a5809454f5810f7e603cbd02daa036scroggo pass = png_set_interlace_handling(png_ptr); 7063965825b97a5809454f5810f7e603cbd02daa036scroggo /* And make sure transforms are initialized. */ 7073965825b97a5809454f5810f7e603cbd02daa036scroggo png_start_read_image(png_ptr); 7083965825b97a5809454f5810f7e603cbd02daa036scroggo } 7093965825b97a5809454f5810f7e603cbd02daa036scroggo else 7103965825b97a5809454f5810f7e603cbd02daa036scroggo { 7113965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->interlaced != 0 && 7123965825b97a5809454f5810f7e603cbd02daa036scroggo (png_ptr->transformations & PNG_INTERLACE) == 0) 7133965825b97a5809454f5810f7e603cbd02daa036scroggo { 7143965825b97a5809454f5810f7e603cbd02daa036scroggo /* Caller called png_start_read_image or png_read_update_info without 7153965825b97a5809454f5810f7e603cbd02daa036scroggo * first turning on the PNG_INTERLACE transform. We can fix this here, 7163965825b97a5809454f5810f7e603cbd02daa036scroggo * but the caller should do it! 7173965825b97a5809454f5810f7e603cbd02daa036scroggo */ 7183965825b97a5809454f5810f7e603cbd02daa036scroggo png_warning(png_ptr, "Interlace handling should be turned on when " 7193965825b97a5809454f5810f7e603cbd02daa036scroggo "using png_read_image"); 7203965825b97a5809454f5810f7e603cbd02daa036scroggo /* Make sure this is set correctly */ 7213965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->num_rows = png_ptr->height; 7223965825b97a5809454f5810f7e603cbd02daa036scroggo } 7233965825b97a5809454f5810f7e603cbd02daa036scroggo 7243965825b97a5809454f5810f7e603cbd02daa036scroggo /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in 7253965825b97a5809454f5810f7e603cbd02daa036scroggo * the above error case. 7263965825b97a5809454f5810f7e603cbd02daa036scroggo */ 7273965825b97a5809454f5810f7e603cbd02daa036scroggo pass = png_set_interlace_handling(png_ptr); 7283965825b97a5809454f5810f7e603cbd02daa036scroggo } 7293965825b97a5809454f5810f7e603cbd02daa036scroggo#else 7303965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->interlaced) 7313965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, 7323965825b97a5809454f5810f7e603cbd02daa036scroggo "Cannot read interlaced image -- interlace handler disabled"); 7333965825b97a5809454f5810f7e603cbd02daa036scroggo 7343965825b97a5809454f5810f7e603cbd02daa036scroggo pass = 1; 7353965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 7363965825b97a5809454f5810f7e603cbd02daa036scroggo 7373965825b97a5809454f5810f7e603cbd02daa036scroggo image_height=png_ptr->height; 7383965825b97a5809454f5810f7e603cbd02daa036scroggo 7393965825b97a5809454f5810f7e603cbd02daa036scroggo for (j = 0; j < pass; j++) 7403965825b97a5809454f5810f7e603cbd02daa036scroggo { 7413965825b97a5809454f5810f7e603cbd02daa036scroggo rp = image; 7423965825b97a5809454f5810f7e603cbd02daa036scroggo for (i = 0; i < image_height; i++) 7433965825b97a5809454f5810f7e603cbd02daa036scroggo { 7443965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_row(png_ptr, *rp, NULL); 7453965825b97a5809454f5810f7e603cbd02daa036scroggo rp++; 7463965825b97a5809454f5810f7e603cbd02daa036scroggo } 7473965825b97a5809454f5810f7e603cbd02daa036scroggo } 7483965825b97a5809454f5810f7e603cbd02daa036scroggo} 7493965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* SEQUENTIAL_READ */ 7503965825b97a5809454f5810f7e603cbd02daa036scroggo 7513965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 7523965825b97a5809454f5810f7e603cbd02daa036scroggo/* Read the end of the PNG file. Will not read past the end of the 7533965825b97a5809454f5810f7e603cbd02daa036scroggo * file, will verify the end is accurate, and will read any comments 7543965825b97a5809454f5810f7e603cbd02daa036scroggo * or time information at the end of the file, if info is not NULL. 7553965825b97a5809454f5810f7e603cbd02daa036scroggo */ 7563965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI 7573965825b97a5809454f5810f7e603cbd02daa036scroggopng_read_end(png_structrp png_ptr, png_inforp info_ptr) 7583965825b97a5809454f5810f7e603cbd02daa036scroggo{ 7593965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 7603965825b97a5809454f5810f7e603cbd02daa036scroggo int keep; 7613965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 7623965825b97a5809454f5810f7e603cbd02daa036scroggo 7633965825b97a5809454f5810f7e603cbd02daa036scroggo png_debug(1, "in png_read_end"); 7643965825b97a5809454f5810f7e603cbd02daa036scroggo 7653965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr == NULL) 7663965825b97a5809454f5810f7e603cbd02daa036scroggo return; 7673965825b97a5809454f5810f7e603cbd02daa036scroggo 7683965825b97a5809454f5810f7e603cbd02daa036scroggo /* If png_read_end is called in the middle of reading the rows there may 7693965825b97a5809454f5810f7e603cbd02daa036scroggo * still be pending IDAT data and an owned zstream. Deal with this here. 7703965825b97a5809454f5810f7e603cbd02daa036scroggo */ 7713965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 7723965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_chunk_unknown_handling(png_ptr, png_IDAT) == 0) 7733965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 7743965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_finish_IDAT(png_ptr); 7753965825b97a5809454f5810f7e603cbd02daa036scroggo 7763965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED 7773965825b97a5809454f5810f7e603cbd02daa036scroggo /* Report invalid palette index; added at libng-1.5.10 */ 7783965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && 7793965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->num_palette_max > png_ptr->num_palette) 7803965825b97a5809454f5810f7e603cbd02daa036scroggo png_benign_error(png_ptr, "Read palette index exceeding num_palette"); 7813965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 7823965825b97a5809454f5810f7e603cbd02daa036scroggo 7833965825b97a5809454f5810f7e603cbd02daa036scroggo do 7843965825b97a5809454f5810f7e603cbd02daa036scroggo { 7853965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 length = png_read_chunk_header(png_ptr); 7863965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 chunk_name = png_ptr->chunk_name; 7873965825b97a5809454f5810f7e603cbd02daa036scroggo 7883965825b97a5809454f5810f7e603cbd02daa036scroggo if (chunk_name == png_IEND) 7893965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_IEND(png_ptr, info_ptr, length); 7903965825b97a5809454f5810f7e603cbd02daa036scroggo 7913965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_IHDR) 7923965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_IHDR(png_ptr, info_ptr, length); 7933965825b97a5809454f5810f7e603cbd02daa036scroggo 7943965825b97a5809454f5810f7e603cbd02daa036scroggo else if (info_ptr == NULL) 7953965825b97a5809454f5810f7e603cbd02daa036scroggo png_crc_finish(png_ptr, length); 7963965825b97a5809454f5810f7e603cbd02daa036scroggo 7973965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 7983965825b97a5809454f5810f7e603cbd02daa036scroggo else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) 7993965825b97a5809454f5810f7e603cbd02daa036scroggo { 8003965825b97a5809454f5810f7e603cbd02daa036scroggo if (chunk_name == png_IDAT) 8013965825b97a5809454f5810f7e603cbd02daa036scroggo { 8023965825b97a5809454f5810f7e603cbd02daa036scroggo if ((length > 0) || 8033965825b97a5809454f5810f7e603cbd02daa036scroggo (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) 8043965825b97a5809454f5810f7e603cbd02daa036scroggo png_benign_error(png_ptr, "Too many IDATs found"); 8053965825b97a5809454f5810f7e603cbd02daa036scroggo } 8063965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_unknown(png_ptr, info_ptr, length, keep); 8073965825b97a5809454f5810f7e603cbd02daa036scroggo if (chunk_name == png_PLTE) 8083965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->mode |= PNG_HAVE_PLTE; 8093965825b97a5809454f5810f7e603cbd02daa036scroggo } 8103965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8113965825b97a5809454f5810f7e603cbd02daa036scroggo 8123965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_IDAT) 8133965825b97a5809454f5810f7e603cbd02daa036scroggo { 8143965825b97a5809454f5810f7e603cbd02daa036scroggo /* Zero length IDATs are legal after the last IDAT has been 8153965825b97a5809454f5810f7e603cbd02daa036scroggo * read, but not after other chunks have been read. 8163965825b97a5809454f5810f7e603cbd02daa036scroggo */ 8173965825b97a5809454f5810f7e603cbd02daa036scroggo if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0) 8183965825b97a5809454f5810f7e603cbd02daa036scroggo png_benign_error(png_ptr, "Too many IDATs found"); 8193965825b97a5809454f5810f7e603cbd02daa036scroggo 8203965825b97a5809454f5810f7e603cbd02daa036scroggo png_crc_finish(png_ptr, length); 8213965825b97a5809454f5810f7e603cbd02daa036scroggo } 8223965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_PLTE) 8233965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_PLTE(png_ptr, info_ptr, length); 8243965825b97a5809454f5810f7e603cbd02daa036scroggo 8253965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_bKGD_SUPPORTED 8263965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_bKGD) 8273965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_bKGD(png_ptr, info_ptr, length); 8283965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8293965825b97a5809454f5810f7e603cbd02daa036scroggo 8303965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_cHRM_SUPPORTED 8313965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_cHRM) 8323965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_cHRM(png_ptr, info_ptr, length); 8333965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8343965825b97a5809454f5810f7e603cbd02daa036scroggo 8353965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_gAMA_SUPPORTED 8363965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_gAMA) 8373965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_gAMA(png_ptr, info_ptr, length); 8383965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8393965825b97a5809454f5810f7e603cbd02daa036scroggo 8403965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_hIST_SUPPORTED 8413965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_hIST) 8423965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_hIST(png_ptr, info_ptr, length); 8433965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8443965825b97a5809454f5810f7e603cbd02daa036scroggo 8453965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_oFFs_SUPPORTED 8463965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_oFFs) 8473965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_oFFs(png_ptr, info_ptr, length); 8483965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8493965825b97a5809454f5810f7e603cbd02daa036scroggo 8503965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_pCAL_SUPPORTED 8513965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_pCAL) 8523965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_pCAL(png_ptr, info_ptr, length); 8533965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8543965825b97a5809454f5810f7e603cbd02daa036scroggo 8553965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sCAL_SUPPORTED 8563965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_sCAL) 8573965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_sCAL(png_ptr, info_ptr, length); 8583965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8593965825b97a5809454f5810f7e603cbd02daa036scroggo 8603965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_pHYs_SUPPORTED 8613965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_pHYs) 8623965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_pHYs(png_ptr, info_ptr, length); 8633965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8643965825b97a5809454f5810f7e603cbd02daa036scroggo 8653965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sBIT_SUPPORTED 8663965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_sBIT) 8673965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_sBIT(png_ptr, info_ptr, length); 8683965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8693965825b97a5809454f5810f7e603cbd02daa036scroggo 8703965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sRGB_SUPPORTED 8713965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_sRGB) 8723965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_sRGB(png_ptr, info_ptr, length); 8733965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8743965825b97a5809454f5810f7e603cbd02daa036scroggo 8753965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_iCCP_SUPPORTED 8763965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_iCCP) 8773965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_iCCP(png_ptr, info_ptr, length); 8783965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8793965825b97a5809454f5810f7e603cbd02daa036scroggo 8803965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_sPLT_SUPPORTED 8813965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_sPLT) 8823965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_sPLT(png_ptr, info_ptr, length); 8833965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8843965825b97a5809454f5810f7e603cbd02daa036scroggo 8853965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_tEXt_SUPPORTED 8863965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_tEXt) 8873965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_tEXt(png_ptr, info_ptr, length); 8883965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8893965825b97a5809454f5810f7e603cbd02daa036scroggo 8903965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_tIME_SUPPORTED 8913965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_tIME) 8923965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_tIME(png_ptr, info_ptr, length); 8933965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8943965825b97a5809454f5810f7e603cbd02daa036scroggo 8953965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_tRNS_SUPPORTED 8963965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_tRNS) 8973965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_tRNS(png_ptr, info_ptr, length); 8983965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 8993965825b97a5809454f5810f7e603cbd02daa036scroggo 9003965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_zTXt_SUPPORTED 9013965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_zTXt) 9023965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_zTXt(png_ptr, info_ptr, length); 9033965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 9043965825b97a5809454f5810f7e603cbd02daa036scroggo 9053965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_iTXt_SUPPORTED 9063965825b97a5809454f5810f7e603cbd02daa036scroggo else if (chunk_name == png_iTXt) 9073965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_iTXt(png_ptr, info_ptr, length); 9083965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 9093965825b97a5809454f5810f7e603cbd02daa036scroggo 9103965825b97a5809454f5810f7e603cbd02daa036scroggo else 9113965825b97a5809454f5810f7e603cbd02daa036scroggo png_handle_unknown(png_ptr, info_ptr, length, 9123965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_HANDLE_CHUNK_AS_DEFAULT); 9133965825b97a5809454f5810f7e603cbd02daa036scroggo } while ((png_ptr->mode & PNG_HAVE_IEND) == 0); 9143965825b97a5809454f5810f7e603cbd02daa036scroggo} 9153965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* SEQUENTIAL_READ */ 9163965825b97a5809454f5810f7e603cbd02daa036scroggo 9173965825b97a5809454f5810f7e603cbd02daa036scroggo/* Free all memory used in the read struct */ 9183965825b97a5809454f5810f7e603cbd02daa036scroggostatic void 9193965825b97a5809454f5810f7e603cbd02daa036scroggopng_read_destroy(png_structrp png_ptr) 9203965825b97a5809454f5810f7e603cbd02daa036scroggo{ 9213965825b97a5809454f5810f7e603cbd02daa036scroggo png_debug(1, "in png_read_destroy"); 9223965825b97a5809454f5810f7e603cbd02daa036scroggo 9233965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_GAMMA_SUPPORTED 9243965825b97a5809454f5810f7e603cbd02daa036scroggo png_destroy_gamma_table(png_ptr); 9253965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 9263965825b97a5809454f5810f7e603cbd02daa036scroggo 9273965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, png_ptr->big_row_buf); 9283965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->big_row_buf = NULL; 9293965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, png_ptr->big_prev_row); 9303965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->big_prev_row = NULL; 9313965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, png_ptr->read_buffer); 9323965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->read_buffer = NULL; 9333965825b97a5809454f5810f7e603cbd02daa036scroggo 9343965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_QUANTIZE_SUPPORTED 9353965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, png_ptr->palette_lookup); 9363965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->palette_lookup = NULL; 9373965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, png_ptr->quantize_index); 9383965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->quantize_index = NULL; 9393965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 9403965825b97a5809454f5810f7e603cbd02daa036scroggo 9413965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->free_me & PNG_FREE_PLTE) != 0) 9423965825b97a5809454f5810f7e603cbd02daa036scroggo { 9433965825b97a5809454f5810f7e603cbd02daa036scroggo png_zfree(png_ptr, png_ptr->palette); 9443965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->palette = NULL; 9453965825b97a5809454f5810f7e603cbd02daa036scroggo } 9463965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->free_me &= ~PNG_FREE_PLTE; 9473965825b97a5809454f5810f7e603cbd02daa036scroggo 9483965825b97a5809454f5810f7e603cbd02daa036scroggo#if defined(PNG_tRNS_SUPPORTED) || \ 9493965825b97a5809454f5810f7e603cbd02daa036scroggo defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 9503965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->free_me & PNG_FREE_TRNS) != 0) 9513965825b97a5809454f5810f7e603cbd02daa036scroggo { 9523965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, png_ptr->trans_alpha); 9533965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->trans_alpha = NULL; 9543965825b97a5809454f5810f7e603cbd02daa036scroggo } 9553965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->free_me &= ~PNG_FREE_TRNS; 9563965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 9573965825b97a5809454f5810f7e603cbd02daa036scroggo 9583965825b97a5809454f5810f7e603cbd02daa036scroggo inflateEnd(&png_ptr->zstream); 9593965825b97a5809454f5810f7e603cbd02daa036scroggo 9603965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_PROGRESSIVE_READ_SUPPORTED 9613965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, png_ptr->save_buffer); 9623965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->save_buffer = NULL; 9633965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 9643965825b97a5809454f5810f7e603cbd02daa036scroggo 9653965825b97a5809454f5810f7e603cbd02daa036scroggo#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) && \ 9663965825b97a5809454f5810f7e603cbd02daa036scroggo defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) 9673965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, png_ptr->unknown_chunk.data); 9683965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->unknown_chunk.data = NULL; 9693965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 9703965825b97a5809454f5810f7e603cbd02daa036scroggo 9713965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED 9723965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, png_ptr->chunk_list); 9733965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->chunk_list = NULL; 9743965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 9753965825b97a5809454f5810f7e603cbd02daa036scroggo 9763965825b97a5809454f5810f7e603cbd02daa036scroggo /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error 9773965825b97a5809454f5810f7e603cbd02daa036scroggo * callbacks are still set at this point. They are required to complete the 9783965825b97a5809454f5810f7e603cbd02daa036scroggo * destruction of the png_struct itself. 9793965825b97a5809454f5810f7e603cbd02daa036scroggo */ 9803965825b97a5809454f5810f7e603cbd02daa036scroggo} 9813965825b97a5809454f5810f7e603cbd02daa036scroggo 9823965825b97a5809454f5810f7e603cbd02daa036scroggo/* Free all memory used by the read */ 9833965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI 9843965825b97a5809454f5810f7e603cbd02daa036scroggopng_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, 9853965825b97a5809454f5810f7e603cbd02daa036scroggo png_infopp end_info_ptr_ptr) 9863965825b97a5809454f5810f7e603cbd02daa036scroggo{ 9873965825b97a5809454f5810f7e603cbd02daa036scroggo png_structrp png_ptr = NULL; 9883965825b97a5809454f5810f7e603cbd02daa036scroggo 9893965825b97a5809454f5810f7e603cbd02daa036scroggo png_debug(1, "in png_destroy_read_struct"); 9903965825b97a5809454f5810f7e603cbd02daa036scroggo 9913965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr_ptr != NULL) 9923965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr = *png_ptr_ptr; 9933965825b97a5809454f5810f7e603cbd02daa036scroggo 9943965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr == NULL) 9953965825b97a5809454f5810f7e603cbd02daa036scroggo return; 9963965825b97a5809454f5810f7e603cbd02daa036scroggo 9973965825b97a5809454f5810f7e603cbd02daa036scroggo /* libpng 1.6.0: use the API to destroy info structs to ensure consistent 9983965825b97a5809454f5810f7e603cbd02daa036scroggo * behavior. Prior to 1.6.0 libpng did extra 'info' destruction in this API. 9993965825b97a5809454f5810f7e603cbd02daa036scroggo * The extra was, apparently, unnecessary yet this hides memory leak bugs. 10003965825b97a5809454f5810f7e603cbd02daa036scroggo */ 10013965825b97a5809454f5810f7e603cbd02daa036scroggo png_destroy_info_struct(png_ptr, end_info_ptr_ptr); 10023965825b97a5809454f5810f7e603cbd02daa036scroggo png_destroy_info_struct(png_ptr, info_ptr_ptr); 10033965825b97a5809454f5810f7e603cbd02daa036scroggo 10043965825b97a5809454f5810f7e603cbd02daa036scroggo *png_ptr_ptr = NULL; 10053965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_destroy(png_ptr); 10063965825b97a5809454f5810f7e603cbd02daa036scroggo png_destroy_png_struct(png_ptr); 10073965825b97a5809454f5810f7e603cbd02daa036scroggo} 10083965825b97a5809454f5810f7e603cbd02daa036scroggo 10093965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI 10103965825b97a5809454f5810f7e603cbd02daa036scroggopng_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn) 10113965825b97a5809454f5810f7e603cbd02daa036scroggo{ 10123965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr == NULL) 10133965825b97a5809454f5810f7e603cbd02daa036scroggo return; 10143965825b97a5809454f5810f7e603cbd02daa036scroggo 10153965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->read_row_fn = read_row_fn; 10163965825b97a5809454f5810f7e603cbd02daa036scroggo} 10173965825b97a5809454f5810f7e603cbd02daa036scroggo 10183965825b97a5809454f5810f7e603cbd02daa036scroggo 10193965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 10203965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_INFO_IMAGE_SUPPORTED 10213965825b97a5809454f5810f7e603cbd02daa036scroggovoid PNGAPI 10223965825b97a5809454f5810f7e603cbd02daa036scroggopng_read_png(png_structrp png_ptr, png_inforp info_ptr, 10233965825b97a5809454f5810f7e603cbd02daa036scroggo int transforms, 10243965825b97a5809454f5810f7e603cbd02daa036scroggo voidp params) 10253965825b97a5809454f5810f7e603cbd02daa036scroggo{ 10263965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr == NULL || info_ptr == NULL) 10273965825b97a5809454f5810f7e603cbd02daa036scroggo return; 10283965825b97a5809454f5810f7e603cbd02daa036scroggo 10293965825b97a5809454f5810f7e603cbd02daa036scroggo /* png_read_info() gives us all of the information from the 10303965825b97a5809454f5810f7e603cbd02daa036scroggo * PNG file before the first IDAT (image data chunk). 10313965825b97a5809454f5810f7e603cbd02daa036scroggo */ 10323965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_info(png_ptr, info_ptr); 10333965825b97a5809454f5810f7e603cbd02daa036scroggo if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep))) 10343965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "Image is too high to process with png_read_png()"); 10353965825b97a5809454f5810f7e603cbd02daa036scroggo 10363965825b97a5809454f5810f7e603cbd02daa036scroggo /* -------------- image transformations start here ------------------- */ 10373965825b97a5809454f5810f7e603cbd02daa036scroggo /* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM 10383965825b97a5809454f5810f7e603cbd02daa036scroggo * is not implemented. This will only happen in de-configured (non-default) 10393965825b97a5809454f5810f7e603cbd02daa036scroggo * libpng builds. The results can be unexpected - png_read_png may return 10403965825b97a5809454f5810f7e603cbd02daa036scroggo * short or mal-formed rows because the transform is skipped. 10413965825b97a5809454f5810f7e603cbd02daa036scroggo */ 10423965825b97a5809454f5810f7e603cbd02daa036scroggo 10433965825b97a5809454f5810f7e603cbd02daa036scroggo /* Tell libpng to strip 16-bit/color files down to 8 bits per color. 10443965825b97a5809454f5810f7e603cbd02daa036scroggo */ 10453965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_SCALE_16) != 0) 10463965825b97a5809454f5810f7e603cbd02daa036scroggo /* Added at libpng-1.5.4. "strip_16" produces the same result that it 10473965825b97a5809454f5810f7e603cbd02daa036scroggo * did in earlier versions, while "scale_16" is now more accurate. 10483965825b97a5809454f5810f7e603cbd02daa036scroggo */ 10493965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 10503965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_scale_16(png_ptr); 10513965825b97a5809454f5810f7e603cbd02daa036scroggo#else 10523965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported"); 10533965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 10543965825b97a5809454f5810f7e603cbd02daa036scroggo 10553965825b97a5809454f5810f7e603cbd02daa036scroggo /* If both SCALE and STRIP are required pngrtran will effectively cancel the 10563965825b97a5809454f5810f7e603cbd02daa036scroggo * latter by doing SCALE first. This is ok and allows apps not to check for 10573965825b97a5809454f5810f7e603cbd02daa036scroggo * which is supported to get the right answer. 10583965825b97a5809454f5810f7e603cbd02daa036scroggo */ 10593965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_STRIP_16) != 0) 10603965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 10613965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_strip_16(png_ptr); 10623965825b97a5809454f5810f7e603cbd02daa036scroggo#else 10633965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported"); 10643965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 10653965825b97a5809454f5810f7e603cbd02daa036scroggo 10663965825b97a5809454f5810f7e603cbd02daa036scroggo /* Strip alpha bytes from the input data without combining with 10673965825b97a5809454f5810f7e603cbd02daa036scroggo * the background (not recommended). 10683965825b97a5809454f5810f7e603cbd02daa036scroggo */ 10693965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_STRIP_ALPHA) != 0) 10703965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 10713965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_strip_alpha(png_ptr); 10723965825b97a5809454f5810f7e603cbd02daa036scroggo#else 10733965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported"); 10743965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 10753965825b97a5809454f5810f7e603cbd02daa036scroggo 10763965825b97a5809454f5810f7e603cbd02daa036scroggo /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single 10773965825b97a5809454f5810f7e603cbd02daa036scroggo * byte into separate bytes (useful for paletted and grayscale images). 10783965825b97a5809454f5810f7e603cbd02daa036scroggo */ 10793965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_PACKING) != 0) 10803965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_PACK_SUPPORTED 10813965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_packing(png_ptr); 10823965825b97a5809454f5810f7e603cbd02daa036scroggo#else 10833965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported"); 10843965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 10853965825b97a5809454f5810f7e603cbd02daa036scroggo 10863965825b97a5809454f5810f7e603cbd02daa036scroggo /* Change the order of packed pixels to least significant bit first 10873965825b97a5809454f5810f7e603cbd02daa036scroggo * (not useful if you are using png_set_packing). 10883965825b97a5809454f5810f7e603cbd02daa036scroggo */ 10893965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0) 10903965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_PACKSWAP_SUPPORTED 10913965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_packswap(png_ptr); 10923965825b97a5809454f5810f7e603cbd02daa036scroggo#else 10933965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported"); 10943965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 10953965825b97a5809454f5810f7e603cbd02daa036scroggo 10963965825b97a5809454f5810f7e603cbd02daa036scroggo /* Expand paletted colors into true RGB triplets 10973965825b97a5809454f5810f7e603cbd02daa036scroggo * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel 10983965825b97a5809454f5810f7e603cbd02daa036scroggo * Expand paletted or RGB images with transparency to full alpha 10993965825b97a5809454f5810f7e603cbd02daa036scroggo * channels so the data will be available as RGBA quartets. 11003965825b97a5809454f5810f7e603cbd02daa036scroggo */ 11013965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_EXPAND) != 0) 11023965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_EXPAND_SUPPORTED 11033965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_expand(png_ptr); 11043965825b97a5809454f5810f7e603cbd02daa036scroggo#else 11053965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported"); 11063965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 11073965825b97a5809454f5810f7e603cbd02daa036scroggo 11083965825b97a5809454f5810f7e603cbd02daa036scroggo /* We don't handle background color or gamma transformation or quantizing. 11093965825b97a5809454f5810f7e603cbd02daa036scroggo */ 11103965825b97a5809454f5810f7e603cbd02daa036scroggo 11113965825b97a5809454f5810f7e603cbd02daa036scroggo /* Invert monochrome files to have 0 as white and 1 as black 11123965825b97a5809454f5810f7e603cbd02daa036scroggo */ 11133965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0) 11143965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_INVERT_SUPPORTED 11153965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_invert_mono(png_ptr); 11163965825b97a5809454f5810f7e603cbd02daa036scroggo#else 11173965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported"); 11183965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 11193965825b97a5809454f5810f7e603cbd02daa036scroggo 11203965825b97a5809454f5810f7e603cbd02daa036scroggo /* If you want to shift the pixel values from the range [0,255] or 11213965825b97a5809454f5810f7e603cbd02daa036scroggo * [0,65535] to the original [0,7] or [0,31], or whatever range the 11223965825b97a5809454f5810f7e603cbd02daa036scroggo * colors were originally in: 11233965825b97a5809454f5810f7e603cbd02daa036scroggo */ 11243965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_SHIFT) != 0) 11253965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_SHIFT_SUPPORTED 11263965825b97a5809454f5810f7e603cbd02daa036scroggo if ((info_ptr->valid & PNG_INFO_sBIT) != 0) 11273965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_shift(png_ptr, &info_ptr->sig_bit); 11283965825b97a5809454f5810f7e603cbd02daa036scroggo#else 11293965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported"); 11303965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 11313965825b97a5809454f5810f7e603cbd02daa036scroggo 11323965825b97a5809454f5810f7e603cbd02daa036scroggo /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ 11333965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_BGR) != 0) 11343965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_BGR_SUPPORTED 11353965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_bgr(png_ptr); 11363965825b97a5809454f5810f7e603cbd02daa036scroggo#else 11373965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported"); 11383965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 11393965825b97a5809454f5810f7e603cbd02daa036scroggo 11403965825b97a5809454f5810f7e603cbd02daa036scroggo /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ 11413965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0) 11423965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 11433965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_swap_alpha(png_ptr); 11443965825b97a5809454f5810f7e603cbd02daa036scroggo#else 11453965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported"); 11463965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 11473965825b97a5809454f5810f7e603cbd02daa036scroggo 11483965825b97a5809454f5810f7e603cbd02daa036scroggo /* Swap bytes of 16-bit files to least significant byte first */ 11493965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0) 11503965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_SWAP_SUPPORTED 11513965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_swap(png_ptr); 11523965825b97a5809454f5810f7e603cbd02daa036scroggo#else 11533965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported"); 11543965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 11553965825b97a5809454f5810f7e603cbd02daa036scroggo 11563965825b97a5809454f5810f7e603cbd02daa036scroggo/* Added at libpng-1.2.41 */ 11573965825b97a5809454f5810f7e603cbd02daa036scroggo /* Invert the alpha channel from opacity to transparency */ 11583965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0) 11593965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 11603965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_invert_alpha(png_ptr); 11613965825b97a5809454f5810f7e603cbd02daa036scroggo#else 11623965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported"); 11633965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 11643965825b97a5809454f5810f7e603cbd02daa036scroggo 11653965825b97a5809454f5810f7e603cbd02daa036scroggo/* Added at libpng-1.2.41 */ 11663965825b97a5809454f5810f7e603cbd02daa036scroggo /* Expand grayscale image to RGB */ 11673965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_GRAY_TO_RGB) != 0) 11683965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 11693965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_gray_to_rgb(png_ptr); 11703965825b97a5809454f5810f7e603cbd02daa036scroggo#else 11713965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported"); 11723965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 11733965825b97a5809454f5810f7e603cbd02daa036scroggo 11743965825b97a5809454f5810f7e603cbd02daa036scroggo/* Added at libpng-1.5.4 */ 11753965825b97a5809454f5810f7e603cbd02daa036scroggo if ((transforms & PNG_TRANSFORM_EXPAND_16) != 0) 11763965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_READ_EXPAND_16_SUPPORTED 11773965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_expand_16(png_ptr); 11783965825b97a5809454f5810f7e603cbd02daa036scroggo#else 11793965825b97a5809454f5810f7e603cbd02daa036scroggo png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported"); 11803965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 11813965825b97a5809454f5810f7e603cbd02daa036scroggo 11823965825b97a5809454f5810f7e603cbd02daa036scroggo /* We don't handle adding filler bytes */ 11833965825b97a5809454f5810f7e603cbd02daa036scroggo 11843965825b97a5809454f5810f7e603cbd02daa036scroggo /* We use png_read_image and rely on that for interlace handling, but we also 11853965825b97a5809454f5810f7e603cbd02daa036scroggo * call png_read_update_info therefore must turn on interlace handling now: 11863965825b97a5809454f5810f7e603cbd02daa036scroggo */ 11873965825b97a5809454f5810f7e603cbd02daa036scroggo (void)png_set_interlace_handling(png_ptr); 11883965825b97a5809454f5810f7e603cbd02daa036scroggo 11893965825b97a5809454f5810f7e603cbd02daa036scroggo /* Optional call to gamma correct and add the background to the palette 11903965825b97a5809454f5810f7e603cbd02daa036scroggo * and update info structure. REQUIRED if you are expecting libpng to 11913965825b97a5809454f5810f7e603cbd02daa036scroggo * update the palette for you (i.e., you selected such a transform above). 11923965825b97a5809454f5810f7e603cbd02daa036scroggo */ 11933965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_update_info(png_ptr, info_ptr); 11943965825b97a5809454f5810f7e603cbd02daa036scroggo 11953965825b97a5809454f5810f7e603cbd02daa036scroggo /* -------------- image transformations end here ------------------- */ 11963965825b97a5809454f5810f7e603cbd02daa036scroggo 11973965825b97a5809454f5810f7e603cbd02daa036scroggo png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); 11983965825b97a5809454f5810f7e603cbd02daa036scroggo if (info_ptr->row_pointers == NULL) 11993965825b97a5809454f5810f7e603cbd02daa036scroggo { 12003965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 iptr; 12013965825b97a5809454f5810f7e603cbd02daa036scroggo 12023965825b97a5809454f5810f7e603cbd02daa036scroggo info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr, 12033965825b97a5809454f5810f7e603cbd02daa036scroggo info_ptr->height * (sizeof (png_bytep)))); 12043965825b97a5809454f5810f7e603cbd02daa036scroggo 12053965825b97a5809454f5810f7e603cbd02daa036scroggo for (iptr=0; iptr<info_ptr->height; iptr++) 12063965825b97a5809454f5810f7e603cbd02daa036scroggo info_ptr->row_pointers[iptr] = NULL; 12073965825b97a5809454f5810f7e603cbd02daa036scroggo 12083965825b97a5809454f5810f7e603cbd02daa036scroggo info_ptr->free_me |= PNG_FREE_ROWS; 12093965825b97a5809454f5810f7e603cbd02daa036scroggo 12103965825b97a5809454f5810f7e603cbd02daa036scroggo for (iptr = 0; iptr < info_ptr->height; iptr++) 12113965825b97a5809454f5810f7e603cbd02daa036scroggo info_ptr->row_pointers[iptr] = png_voidcast(png_bytep, 12123965825b97a5809454f5810f7e603cbd02daa036scroggo png_malloc(png_ptr, info_ptr->rowbytes)); 12133965825b97a5809454f5810f7e603cbd02daa036scroggo } 12143965825b97a5809454f5810f7e603cbd02daa036scroggo 12153965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_image(png_ptr, info_ptr->row_pointers); 12163965825b97a5809454f5810f7e603cbd02daa036scroggo info_ptr->valid |= PNG_INFO_IDAT; 12173965825b97a5809454f5810f7e603cbd02daa036scroggo 12183965825b97a5809454f5810f7e603cbd02daa036scroggo /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ 12193965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_end(png_ptr, info_ptr); 12203965825b97a5809454f5810f7e603cbd02daa036scroggo 12213965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_UNUSED(params) 12223965825b97a5809454f5810f7e603cbd02daa036scroggo} 12233965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* INFO_IMAGE */ 12243965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* SEQUENTIAL_READ */ 12253965825b97a5809454f5810f7e603cbd02daa036scroggo 12263965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_SIMPLIFIED_READ_SUPPORTED 12273965825b97a5809454f5810f7e603cbd02daa036scroggo/* SIMPLIFIED READ 12283965825b97a5809454f5810f7e603cbd02daa036scroggo * 12293965825b97a5809454f5810f7e603cbd02daa036scroggo * This code currently relies on the sequential reader, though it could easily 12303965825b97a5809454f5810f7e603cbd02daa036scroggo * be made to work with the progressive one. 12313965825b97a5809454f5810f7e603cbd02daa036scroggo */ 12323965825b97a5809454f5810f7e603cbd02daa036scroggo/* Arguments to png_image_finish_read: */ 12333965825b97a5809454f5810f7e603cbd02daa036scroggo 12343965825b97a5809454f5810f7e603cbd02daa036scroggo/* Encoding of PNG data (used by the color-map code) */ 12353965825b97a5809454f5810f7e603cbd02daa036scroggo# define P_NOTSET 0 /* File encoding not yet known */ 12363965825b97a5809454f5810f7e603cbd02daa036scroggo# define P_sRGB 1 /* 8-bit encoded to sRGB gamma */ 12373965825b97a5809454f5810f7e603cbd02daa036scroggo# define P_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */ 12383965825b97a5809454f5810f7e603cbd02daa036scroggo# define P_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */ 12393965825b97a5809454f5810f7e603cbd02daa036scroggo# define P_LINEAR8 4 /* 8-bit linear: only from a file value */ 12403965825b97a5809454f5810f7e603cbd02daa036scroggo 12413965825b97a5809454f5810f7e603cbd02daa036scroggo/* Color-map processing: after libpng has run on the PNG image further 12423965825b97a5809454f5810f7e603cbd02daa036scroggo * processing may be needed to convert the data to color-map indices. 12433965825b97a5809454f5810f7e603cbd02daa036scroggo */ 12443965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_CMAP_NONE 0 12453965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_CMAP_GA 1 /* Process GA data to a color-map with alpha */ 12463965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_CMAP_TRANS 2 /* Process GA data to a background index */ 12473965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_CMAP_RGB 3 /* Process RGB data */ 12483965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */ 12493965825b97a5809454f5810f7e603cbd02daa036scroggo 12503965825b97a5809454f5810f7e603cbd02daa036scroggo/* The following document where the background is for each processing case. */ 12513965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_CMAP_NONE_BACKGROUND 256 12523965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_CMAP_GA_BACKGROUND 231 12533965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_CMAP_TRANS_BACKGROUND 254 12543965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_CMAP_RGB_BACKGROUND 256 12553965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_CMAP_RGB_ALPHA_BACKGROUND 216 12563965825b97a5809454f5810f7e603cbd02daa036scroggo 12573965825b97a5809454f5810f7e603cbd02daa036scroggotypedef struct 12583965825b97a5809454f5810f7e603cbd02daa036scroggo{ 12593965825b97a5809454f5810f7e603cbd02daa036scroggo /* Arguments: */ 12603965825b97a5809454f5810f7e603cbd02daa036scroggo png_imagep image; 12613965825b97a5809454f5810f7e603cbd02daa036scroggo png_voidp buffer; 12623965825b97a5809454f5810f7e603cbd02daa036scroggo png_int_32 row_stride; 12633965825b97a5809454f5810f7e603cbd02daa036scroggo png_voidp colormap; 12643965825b97a5809454f5810f7e603cbd02daa036scroggo png_const_colorp background; 12653965825b97a5809454f5810f7e603cbd02daa036scroggo /* Local variables: */ 12663965825b97a5809454f5810f7e603cbd02daa036scroggo png_voidp local_row; 12673965825b97a5809454f5810f7e603cbd02daa036scroggo png_voidp first_row; 12683965825b97a5809454f5810f7e603cbd02daa036scroggo ptrdiff_t row_bytes; /* step between rows */ 12693965825b97a5809454f5810f7e603cbd02daa036scroggo int file_encoding; /* E_ values above */ 12703965825b97a5809454f5810f7e603cbd02daa036scroggo png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */ 12713965825b97a5809454f5810f7e603cbd02daa036scroggo int colormap_processing; /* PNG_CMAP_ values above */ 12723965825b97a5809454f5810f7e603cbd02daa036scroggo} png_image_read_control; 12733965825b97a5809454f5810f7e603cbd02daa036scroggo 12743965825b97a5809454f5810f7e603cbd02daa036scroggo/* Do all the *safe* initialization - 'safe' means that png_error won't be 12753965825b97a5809454f5810f7e603cbd02daa036scroggo * called, so setting up the jmp_buf is not required. This means that anything 12763965825b97a5809454f5810f7e603cbd02daa036scroggo * called from here must *not* call png_malloc - it has to call png_malloc_warn 12773965825b97a5809454f5810f7e603cbd02daa036scroggo * instead so that control is returned safely back to this routine. 12783965825b97a5809454f5810f7e603cbd02daa036scroggo */ 12793965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 12803965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_read_init(png_imagep image) 12813965825b97a5809454f5810f7e603cbd02daa036scroggo{ 12823965825b97a5809454f5810f7e603cbd02daa036scroggo if (image->opaque == NULL) 12833965825b97a5809454f5810f7e603cbd02daa036scroggo { 12843965825b97a5809454f5810f7e603cbd02daa036scroggo png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image, 12853965825b97a5809454f5810f7e603cbd02daa036scroggo png_safe_error, png_safe_warning); 12863965825b97a5809454f5810f7e603cbd02daa036scroggo 12873965825b97a5809454f5810f7e603cbd02daa036scroggo /* And set the rest of the structure to NULL to ensure that the various 12883965825b97a5809454f5810f7e603cbd02daa036scroggo * fields are consistent. 12893965825b97a5809454f5810f7e603cbd02daa036scroggo */ 12903965825b97a5809454f5810f7e603cbd02daa036scroggo memset(image, 0, (sizeof *image)); 12913965825b97a5809454f5810f7e603cbd02daa036scroggo image->version = PNG_IMAGE_VERSION; 12923965825b97a5809454f5810f7e603cbd02daa036scroggo 12933965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr != NULL) 12943965825b97a5809454f5810f7e603cbd02daa036scroggo { 12953965825b97a5809454f5810f7e603cbd02daa036scroggo png_infop info_ptr = png_create_info_struct(png_ptr); 12963965825b97a5809454f5810f7e603cbd02daa036scroggo 12973965825b97a5809454f5810f7e603cbd02daa036scroggo if (info_ptr != NULL) 12983965825b97a5809454f5810f7e603cbd02daa036scroggo { 12993965825b97a5809454f5810f7e603cbd02daa036scroggo png_controlp control = png_voidcast(png_controlp, 13003965825b97a5809454f5810f7e603cbd02daa036scroggo png_malloc_warn(png_ptr, (sizeof *control))); 13013965825b97a5809454f5810f7e603cbd02daa036scroggo 13023965825b97a5809454f5810f7e603cbd02daa036scroggo if (control != NULL) 13033965825b97a5809454f5810f7e603cbd02daa036scroggo { 13043965825b97a5809454f5810f7e603cbd02daa036scroggo memset(control, 0, (sizeof *control)); 13053965825b97a5809454f5810f7e603cbd02daa036scroggo 13063965825b97a5809454f5810f7e603cbd02daa036scroggo control->png_ptr = png_ptr; 13073965825b97a5809454f5810f7e603cbd02daa036scroggo control->info_ptr = info_ptr; 13083965825b97a5809454f5810f7e603cbd02daa036scroggo control->for_write = 0; 13093965825b97a5809454f5810f7e603cbd02daa036scroggo 13103965825b97a5809454f5810f7e603cbd02daa036scroggo image->opaque = control; 13113965825b97a5809454f5810f7e603cbd02daa036scroggo return 1; 13123965825b97a5809454f5810f7e603cbd02daa036scroggo } 13133965825b97a5809454f5810f7e603cbd02daa036scroggo 13143965825b97a5809454f5810f7e603cbd02daa036scroggo /* Error clean up */ 13153965825b97a5809454f5810f7e603cbd02daa036scroggo png_destroy_info_struct(png_ptr, &info_ptr); 13163965825b97a5809454f5810f7e603cbd02daa036scroggo } 13173965825b97a5809454f5810f7e603cbd02daa036scroggo 13183965825b97a5809454f5810f7e603cbd02daa036scroggo png_destroy_read_struct(&png_ptr, NULL, NULL); 13193965825b97a5809454f5810f7e603cbd02daa036scroggo } 13203965825b97a5809454f5810f7e603cbd02daa036scroggo 13213965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, "png_image_read: out of memory"); 13223965825b97a5809454f5810f7e603cbd02daa036scroggo } 13233965825b97a5809454f5810f7e603cbd02daa036scroggo 13243965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, "png_image_read: opaque pointer not NULL"); 13253965825b97a5809454f5810f7e603cbd02daa036scroggo} 13263965825b97a5809454f5810f7e603cbd02daa036scroggo 13273965825b97a5809454f5810f7e603cbd02daa036scroggo/* Utility to find the base format of a PNG file from a png_struct. */ 13283965825b97a5809454f5810f7e603cbd02daa036scroggostatic png_uint_32 13293965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_format(png_structrp png_ptr) 13303965825b97a5809454f5810f7e603cbd02daa036scroggo{ 13313965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 format = 0; 13323965825b97a5809454f5810f7e603cbd02daa036scroggo 13333965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0) 13343965825b97a5809454f5810f7e603cbd02daa036scroggo format |= PNG_FORMAT_FLAG_COLOR; 13353965825b97a5809454f5810f7e603cbd02daa036scroggo 13363965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0) 13373965825b97a5809454f5810f7e603cbd02daa036scroggo format |= PNG_FORMAT_FLAG_ALPHA; 13383965825b97a5809454f5810f7e603cbd02daa036scroggo 13393965825b97a5809454f5810f7e603cbd02daa036scroggo /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS 13403965825b97a5809454f5810f7e603cbd02daa036scroggo * sets the png_struct fields; that's all we are interested in here. The 13413965825b97a5809454f5810f7e603cbd02daa036scroggo * precise interaction with an app call to png_set_tRNS and PNG file reading 13423965825b97a5809454f5810f7e603cbd02daa036scroggo * is unclear. 13433965825b97a5809454f5810f7e603cbd02daa036scroggo */ 13443965825b97a5809454f5810f7e603cbd02daa036scroggo else if (png_ptr->num_trans > 0) 13453965825b97a5809454f5810f7e603cbd02daa036scroggo format |= PNG_FORMAT_FLAG_ALPHA; 13463965825b97a5809454f5810f7e603cbd02daa036scroggo 13473965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->bit_depth == 16) 13483965825b97a5809454f5810f7e603cbd02daa036scroggo format |= PNG_FORMAT_FLAG_LINEAR; 13493965825b97a5809454f5810f7e603cbd02daa036scroggo 13503965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->color_type & PNG_COLOR_MASK_PALETTE) != 0) 13513965825b97a5809454f5810f7e603cbd02daa036scroggo format |= PNG_FORMAT_FLAG_COLORMAP; 13523965825b97a5809454f5810f7e603cbd02daa036scroggo 13533965825b97a5809454f5810f7e603cbd02daa036scroggo return format; 13543965825b97a5809454f5810f7e603cbd02daa036scroggo} 13553965825b97a5809454f5810f7e603cbd02daa036scroggo 13563965825b97a5809454f5810f7e603cbd02daa036scroggo/* Is the given gamma significantly different from sRGB? The test is the same 13573965825b97a5809454f5810f7e603cbd02daa036scroggo * one used in pngrtran.c when deciding whether to do gamma correction. The 13583965825b97a5809454f5810f7e603cbd02daa036scroggo * arithmetic optimizes the division by using the fact that the inverse of the 13593965825b97a5809454f5810f7e603cbd02daa036scroggo * file sRGB gamma is 2.2 13603965825b97a5809454f5810f7e603cbd02daa036scroggo */ 13613965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 13623965825b97a5809454f5810f7e603cbd02daa036scroggopng_gamma_not_sRGB(png_fixed_point g) 13633965825b97a5809454f5810f7e603cbd02daa036scroggo{ 13643965825b97a5809454f5810f7e603cbd02daa036scroggo if (g < PNG_FP_1) 13653965825b97a5809454f5810f7e603cbd02daa036scroggo { 13663965825b97a5809454f5810f7e603cbd02daa036scroggo /* An uninitialized gamma is assumed to be sRGB for the simplified API. */ 13673965825b97a5809454f5810f7e603cbd02daa036scroggo if (g == 0) 13683965825b97a5809454f5810f7e603cbd02daa036scroggo return 0; 13693965825b97a5809454f5810f7e603cbd02daa036scroggo 13703965825b97a5809454f5810f7e603cbd02daa036scroggo return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */); 13713965825b97a5809454f5810f7e603cbd02daa036scroggo } 13723965825b97a5809454f5810f7e603cbd02daa036scroggo 13733965825b97a5809454f5810f7e603cbd02daa036scroggo return 1; 13743965825b97a5809454f5810f7e603cbd02daa036scroggo} 13753965825b97a5809454f5810f7e603cbd02daa036scroggo 13763965825b97a5809454f5810f7e603cbd02daa036scroggo/* Do the main body of a 'png_image_begin_read' function; read the PNG file 13773965825b97a5809454f5810f7e603cbd02daa036scroggo * header and fill in all the information. This is executed in a safe context, 13783965825b97a5809454f5810f7e603cbd02daa036scroggo * unlike the init routine above. 13793965825b97a5809454f5810f7e603cbd02daa036scroggo */ 13803965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 13813965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_read_header(png_voidp argument) 13823965825b97a5809454f5810f7e603cbd02daa036scroggo{ 13833965825b97a5809454f5810f7e603cbd02daa036scroggo png_imagep image = png_voidcast(png_imagep, argument); 13843965825b97a5809454f5810f7e603cbd02daa036scroggo png_structrp png_ptr = image->opaque->png_ptr; 13853965825b97a5809454f5810f7e603cbd02daa036scroggo png_inforp info_ptr = image->opaque->info_ptr; 13863965825b97a5809454f5810f7e603cbd02daa036scroggo 13873965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_benign_errors(png_ptr, 1/*warn*/); 13883965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_info(png_ptr, info_ptr); 13893965825b97a5809454f5810f7e603cbd02daa036scroggo 13903965825b97a5809454f5810f7e603cbd02daa036scroggo /* Do this the fast way; just read directly out of png_struct. */ 13913965825b97a5809454f5810f7e603cbd02daa036scroggo image->width = png_ptr->width; 13923965825b97a5809454f5810f7e603cbd02daa036scroggo image->height = png_ptr->height; 13933965825b97a5809454f5810f7e603cbd02daa036scroggo 13943965825b97a5809454f5810f7e603cbd02daa036scroggo { 13953965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 format = png_image_format(png_ptr); 13963965825b97a5809454f5810f7e603cbd02daa036scroggo 13973965825b97a5809454f5810f7e603cbd02daa036scroggo image->format = format; 13983965825b97a5809454f5810f7e603cbd02daa036scroggo 13993965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_COLORSPACE_SUPPORTED 14003965825b97a5809454f5810f7e603cbd02daa036scroggo /* Does the colorspace match sRGB? If there is no color endpoint 14013965825b97a5809454f5810f7e603cbd02daa036scroggo * (colorant) information assume yes, otherwise require the 14023965825b97a5809454f5810f7e603cbd02daa036scroggo * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set. If the 14033965825b97a5809454f5810f7e603cbd02daa036scroggo * colorspace has been determined to be invalid ignore it. 14043965825b97a5809454f5810f7e603cbd02daa036scroggo */ 14053965825b97a5809454f5810f7e603cbd02daa036scroggo if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags 14063965825b97a5809454f5810f7e603cbd02daa036scroggo & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB| 14073965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS)) 14083965825b97a5809454f5810f7e603cbd02daa036scroggo image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB; 14093965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 14103965825b97a5809454f5810f7e603cbd02daa036scroggo } 14113965825b97a5809454f5810f7e603cbd02daa036scroggo 14123965825b97a5809454f5810f7e603cbd02daa036scroggo /* We need the maximum number of entries regardless of the format the 14133965825b97a5809454f5810f7e603cbd02daa036scroggo * application sets here. 14143965825b97a5809454f5810f7e603cbd02daa036scroggo */ 14153965825b97a5809454f5810f7e603cbd02daa036scroggo { 14163965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 cmap_entries; 14173965825b97a5809454f5810f7e603cbd02daa036scroggo 14183965825b97a5809454f5810f7e603cbd02daa036scroggo switch (png_ptr->color_type) 14193965825b97a5809454f5810f7e603cbd02daa036scroggo { 14203965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_COLOR_TYPE_GRAY: 14213965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = 1U << png_ptr->bit_depth; 14223965825b97a5809454f5810f7e603cbd02daa036scroggo break; 14233965825b97a5809454f5810f7e603cbd02daa036scroggo 14243965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_COLOR_TYPE_PALETTE: 14253965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = png_ptr->num_palette; 14263965825b97a5809454f5810f7e603cbd02daa036scroggo break; 14273965825b97a5809454f5810f7e603cbd02daa036scroggo 14283965825b97a5809454f5810f7e603cbd02daa036scroggo default: 14293965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = 256; 14303965825b97a5809454f5810f7e603cbd02daa036scroggo break; 14313965825b97a5809454f5810f7e603cbd02daa036scroggo } 14323965825b97a5809454f5810f7e603cbd02daa036scroggo 14333965825b97a5809454f5810f7e603cbd02daa036scroggo if (cmap_entries > 256) 14343965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = 256; 14353965825b97a5809454f5810f7e603cbd02daa036scroggo 14363965825b97a5809454f5810f7e603cbd02daa036scroggo image->colormap_entries = cmap_entries; 14373965825b97a5809454f5810f7e603cbd02daa036scroggo } 14383965825b97a5809454f5810f7e603cbd02daa036scroggo 14393965825b97a5809454f5810f7e603cbd02daa036scroggo return 1; 14403965825b97a5809454f5810f7e603cbd02daa036scroggo} 14413965825b97a5809454f5810f7e603cbd02daa036scroggo 14423965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_STDIO_SUPPORTED 14433965825b97a5809454f5810f7e603cbd02daa036scroggoint PNGAPI 14443965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_begin_read_from_stdio(png_imagep image, FILE* file) 14453965825b97a5809454f5810f7e603cbd02daa036scroggo{ 14463965825b97a5809454f5810f7e603cbd02daa036scroggo if (image != NULL && image->version == PNG_IMAGE_VERSION) 14473965825b97a5809454f5810f7e603cbd02daa036scroggo { 14483965825b97a5809454f5810f7e603cbd02daa036scroggo if (file != NULL) 14493965825b97a5809454f5810f7e603cbd02daa036scroggo { 14503965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_image_read_init(image) != 0) 14513965825b97a5809454f5810f7e603cbd02daa036scroggo { 14523965825b97a5809454f5810f7e603cbd02daa036scroggo /* This is slightly evil, but png_init_io doesn't do anything other 14533965825b97a5809454f5810f7e603cbd02daa036scroggo * than this and we haven't changed the standard IO functions so 14543965825b97a5809454f5810f7e603cbd02daa036scroggo * this saves a 'safe' function. 14553965825b97a5809454f5810f7e603cbd02daa036scroggo */ 14563965825b97a5809454f5810f7e603cbd02daa036scroggo image->opaque->png_ptr->io_ptr = file; 14573965825b97a5809454f5810f7e603cbd02daa036scroggo return png_safe_execute(image, png_image_read_header, image); 14583965825b97a5809454f5810f7e603cbd02daa036scroggo } 14593965825b97a5809454f5810f7e603cbd02daa036scroggo } 14603965825b97a5809454f5810f7e603cbd02daa036scroggo 14613965825b97a5809454f5810f7e603cbd02daa036scroggo else 14623965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, 14633965825b97a5809454f5810f7e603cbd02daa036scroggo "png_image_begin_read_from_stdio: invalid argument"); 14643965825b97a5809454f5810f7e603cbd02daa036scroggo } 14653965825b97a5809454f5810f7e603cbd02daa036scroggo 14663965825b97a5809454f5810f7e603cbd02daa036scroggo else if (image != NULL) 14673965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, 14683965825b97a5809454f5810f7e603cbd02daa036scroggo "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION"); 14693965825b97a5809454f5810f7e603cbd02daa036scroggo 14703965825b97a5809454f5810f7e603cbd02daa036scroggo return 0; 14713965825b97a5809454f5810f7e603cbd02daa036scroggo} 14723965825b97a5809454f5810f7e603cbd02daa036scroggo 14733965825b97a5809454f5810f7e603cbd02daa036scroggoint PNGAPI 14743965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_begin_read_from_file(png_imagep image, const char *file_name) 14753965825b97a5809454f5810f7e603cbd02daa036scroggo{ 14763965825b97a5809454f5810f7e603cbd02daa036scroggo if (image != NULL && image->version == PNG_IMAGE_VERSION) 14773965825b97a5809454f5810f7e603cbd02daa036scroggo { 14783965825b97a5809454f5810f7e603cbd02daa036scroggo if (file_name != NULL) 14793965825b97a5809454f5810f7e603cbd02daa036scroggo { 14803965825b97a5809454f5810f7e603cbd02daa036scroggo FILE *fp = fopen(file_name, "rb"); 14813965825b97a5809454f5810f7e603cbd02daa036scroggo 14823965825b97a5809454f5810f7e603cbd02daa036scroggo if (fp != NULL) 14833965825b97a5809454f5810f7e603cbd02daa036scroggo { 14843965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_image_read_init(image) != 0) 14853965825b97a5809454f5810f7e603cbd02daa036scroggo { 14863965825b97a5809454f5810f7e603cbd02daa036scroggo image->opaque->png_ptr->io_ptr = fp; 14873965825b97a5809454f5810f7e603cbd02daa036scroggo image->opaque->owned_file = 1; 14883965825b97a5809454f5810f7e603cbd02daa036scroggo return png_safe_execute(image, png_image_read_header, image); 14893965825b97a5809454f5810f7e603cbd02daa036scroggo } 14903965825b97a5809454f5810f7e603cbd02daa036scroggo 14913965825b97a5809454f5810f7e603cbd02daa036scroggo /* Clean up: just the opened file. */ 14923965825b97a5809454f5810f7e603cbd02daa036scroggo (void)fclose(fp); 14933965825b97a5809454f5810f7e603cbd02daa036scroggo } 14943965825b97a5809454f5810f7e603cbd02daa036scroggo 14953965825b97a5809454f5810f7e603cbd02daa036scroggo else 14963965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, strerror(errno)); 14973965825b97a5809454f5810f7e603cbd02daa036scroggo } 14983965825b97a5809454f5810f7e603cbd02daa036scroggo 14993965825b97a5809454f5810f7e603cbd02daa036scroggo else 15003965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, 15013965825b97a5809454f5810f7e603cbd02daa036scroggo "png_image_begin_read_from_file: invalid argument"); 15023965825b97a5809454f5810f7e603cbd02daa036scroggo } 15033965825b97a5809454f5810f7e603cbd02daa036scroggo 15043965825b97a5809454f5810f7e603cbd02daa036scroggo else if (image != NULL) 15053965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, 15063965825b97a5809454f5810f7e603cbd02daa036scroggo "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION"); 15073965825b97a5809454f5810f7e603cbd02daa036scroggo 15083965825b97a5809454f5810f7e603cbd02daa036scroggo return 0; 15093965825b97a5809454f5810f7e603cbd02daa036scroggo} 15103965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* STDIO */ 15113965825b97a5809454f5810f7e603cbd02daa036scroggo 15123965825b97a5809454f5810f7e603cbd02daa036scroggostatic void PNGCBAPI 15133965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) 15143965825b97a5809454f5810f7e603cbd02daa036scroggo{ 15153965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr != NULL) 15163965825b97a5809454f5810f7e603cbd02daa036scroggo { 15173965825b97a5809454f5810f7e603cbd02daa036scroggo png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr); 15183965825b97a5809454f5810f7e603cbd02daa036scroggo if (image != NULL) 15193965825b97a5809454f5810f7e603cbd02daa036scroggo { 15203965825b97a5809454f5810f7e603cbd02daa036scroggo png_controlp cp = image->opaque; 15213965825b97a5809454f5810f7e603cbd02daa036scroggo if (cp != NULL) 15223965825b97a5809454f5810f7e603cbd02daa036scroggo { 15233965825b97a5809454f5810f7e603cbd02daa036scroggo png_const_bytep memory = cp->memory; 15243965825b97a5809454f5810f7e603cbd02daa036scroggo png_size_t size = cp->size; 15253965825b97a5809454f5810f7e603cbd02daa036scroggo 15263965825b97a5809454f5810f7e603cbd02daa036scroggo if (memory != NULL && size >= need) 15273965825b97a5809454f5810f7e603cbd02daa036scroggo { 15283965825b97a5809454f5810f7e603cbd02daa036scroggo memcpy(out, memory, need); 15293965825b97a5809454f5810f7e603cbd02daa036scroggo cp->memory = memory + need; 15303965825b97a5809454f5810f7e603cbd02daa036scroggo cp->size = size - need; 15313965825b97a5809454f5810f7e603cbd02daa036scroggo return; 15323965825b97a5809454f5810f7e603cbd02daa036scroggo } 15333965825b97a5809454f5810f7e603cbd02daa036scroggo 15343965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "read beyond end of data"); 15353965825b97a5809454f5810f7e603cbd02daa036scroggo } 15363965825b97a5809454f5810f7e603cbd02daa036scroggo } 15373965825b97a5809454f5810f7e603cbd02daa036scroggo 15383965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "invalid memory read"); 15393965825b97a5809454f5810f7e603cbd02daa036scroggo } 15403965825b97a5809454f5810f7e603cbd02daa036scroggo} 15413965825b97a5809454f5810f7e603cbd02daa036scroggo 15423965825b97a5809454f5810f7e603cbd02daa036scroggoint PNGAPI png_image_begin_read_from_memory(png_imagep image, 15433965825b97a5809454f5810f7e603cbd02daa036scroggo png_const_voidp memory, png_size_t size) 15443965825b97a5809454f5810f7e603cbd02daa036scroggo{ 15453965825b97a5809454f5810f7e603cbd02daa036scroggo if (image != NULL && image->version == PNG_IMAGE_VERSION) 15463965825b97a5809454f5810f7e603cbd02daa036scroggo { 15473965825b97a5809454f5810f7e603cbd02daa036scroggo if (memory != NULL && size > 0) 15483965825b97a5809454f5810f7e603cbd02daa036scroggo { 15493965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_image_read_init(image) != 0) 15503965825b97a5809454f5810f7e603cbd02daa036scroggo { 15513965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now set the IO functions to read from the memory buffer and 15523965825b97a5809454f5810f7e603cbd02daa036scroggo * store it into io_ptr. Again do this in-place to avoid calling a 15533965825b97a5809454f5810f7e603cbd02daa036scroggo * libpng function that requires error handling. 15543965825b97a5809454f5810f7e603cbd02daa036scroggo */ 15553965825b97a5809454f5810f7e603cbd02daa036scroggo image->opaque->memory = png_voidcast(png_const_bytep, memory); 15563965825b97a5809454f5810f7e603cbd02daa036scroggo image->opaque->size = size; 15573965825b97a5809454f5810f7e603cbd02daa036scroggo image->opaque->png_ptr->io_ptr = image; 15583965825b97a5809454f5810f7e603cbd02daa036scroggo image->opaque->png_ptr->read_data_fn = png_image_memory_read; 15593965825b97a5809454f5810f7e603cbd02daa036scroggo 15603965825b97a5809454f5810f7e603cbd02daa036scroggo return png_safe_execute(image, png_image_read_header, image); 15613965825b97a5809454f5810f7e603cbd02daa036scroggo } 15623965825b97a5809454f5810f7e603cbd02daa036scroggo } 15633965825b97a5809454f5810f7e603cbd02daa036scroggo 15643965825b97a5809454f5810f7e603cbd02daa036scroggo else 15653965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, 15663965825b97a5809454f5810f7e603cbd02daa036scroggo "png_image_begin_read_from_memory: invalid argument"); 15673965825b97a5809454f5810f7e603cbd02daa036scroggo } 15683965825b97a5809454f5810f7e603cbd02daa036scroggo 15693965825b97a5809454f5810f7e603cbd02daa036scroggo else if (image != NULL) 15703965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, 15713965825b97a5809454f5810f7e603cbd02daa036scroggo "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION"); 15723965825b97a5809454f5810f7e603cbd02daa036scroggo 15733965825b97a5809454f5810f7e603cbd02daa036scroggo return 0; 15743965825b97a5809454f5810f7e603cbd02daa036scroggo} 15753965825b97a5809454f5810f7e603cbd02daa036scroggo 15763965825b97a5809454f5810f7e603cbd02daa036scroggo/* Utility function to skip chunks that are not used by the simplified image 15773965825b97a5809454f5810f7e603cbd02daa036scroggo * read functions and an appropriate macro to call it. 15783965825b97a5809454f5810f7e603cbd02daa036scroggo */ 15793965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 15803965825b97a5809454f5810f7e603cbd02daa036scroggostatic void 15813965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_skip_unused_chunks(png_structrp png_ptr) 15823965825b97a5809454f5810f7e603cbd02daa036scroggo{ 15833965825b97a5809454f5810f7e603cbd02daa036scroggo /* Prepare the reader to ignore all recognized chunks whose data will not 15843965825b97a5809454f5810f7e603cbd02daa036scroggo * be used, i.e., all chunks recognized by libpng except for those 15853965825b97a5809454f5810f7e603cbd02daa036scroggo * involved in basic image reading: 15863965825b97a5809454f5810f7e603cbd02daa036scroggo * 15873965825b97a5809454f5810f7e603cbd02daa036scroggo * IHDR, PLTE, IDAT, IEND 15883965825b97a5809454f5810f7e603cbd02daa036scroggo * 15893965825b97a5809454f5810f7e603cbd02daa036scroggo * Or image data handling: 15903965825b97a5809454f5810f7e603cbd02daa036scroggo * 15913965825b97a5809454f5810f7e603cbd02daa036scroggo * tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT. 15923965825b97a5809454f5810f7e603cbd02daa036scroggo * 15933965825b97a5809454f5810f7e603cbd02daa036scroggo * This provides a small performance improvement and eliminates any 15943965825b97a5809454f5810f7e603cbd02daa036scroggo * potential vulnerability to security problems in the unused chunks. 15953965825b97a5809454f5810f7e603cbd02daa036scroggo * 15963965825b97a5809454f5810f7e603cbd02daa036scroggo * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored 15973965825b97a5809454f5810f7e603cbd02daa036scroggo * too. This allows the simplified API to be compiled without iCCP support, 15983965825b97a5809454f5810f7e603cbd02daa036scroggo * however if the support is there the chunk is still checked to detect 15993965825b97a5809454f5810f7e603cbd02daa036scroggo * errors (which are unfortunately quite common.) 16003965825b97a5809454f5810f7e603cbd02daa036scroggo */ 16013965825b97a5809454f5810f7e603cbd02daa036scroggo { 16023965825b97a5809454f5810f7e603cbd02daa036scroggo static PNG_CONST png_byte chunks_to_process[] = { 16033965825b97a5809454f5810f7e603cbd02daa036scroggo 98, 75, 71, 68, '\0', /* bKGD */ 16043965825b97a5809454f5810f7e603cbd02daa036scroggo 99, 72, 82, 77, '\0', /* cHRM */ 16053965825b97a5809454f5810f7e603cbd02daa036scroggo 103, 65, 77, 65, '\0', /* gAMA */ 16063965825b97a5809454f5810f7e603cbd02daa036scroggo# ifdef PNG_READ_iCCP_SUPPORTED 16073965825b97a5809454f5810f7e603cbd02daa036scroggo 105, 67, 67, 80, '\0', /* iCCP */ 16083965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 16093965825b97a5809454f5810f7e603cbd02daa036scroggo 115, 66, 73, 84, '\0', /* sBIT */ 16103965825b97a5809454f5810f7e603cbd02daa036scroggo 115, 82, 71, 66, '\0', /* sRGB */ 16113965825b97a5809454f5810f7e603cbd02daa036scroggo }; 16123965825b97a5809454f5810f7e603cbd02daa036scroggo 16133965825b97a5809454f5810f7e603cbd02daa036scroggo /* Ignore unknown chunks and all other chunks except for the 16143965825b97a5809454f5810f7e603cbd02daa036scroggo * IHDR, PLTE, tRNS, IDAT, and IEND chunks. 16153965825b97a5809454f5810f7e603cbd02daa036scroggo */ 16163965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER, 16173965825b97a5809454f5810f7e603cbd02daa036scroggo NULL, -1); 16183965825b97a5809454f5810f7e603cbd02daa036scroggo 16193965825b97a5809454f5810f7e603cbd02daa036scroggo /* But do not ignore image data handling chunks */ 16203965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT, 16213965825b97a5809454f5810f7e603cbd02daa036scroggo chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5); 16223965825b97a5809454f5810f7e603cbd02daa036scroggo } 16233965825b97a5809454f5810f7e603cbd02daa036scroggo} 16243965825b97a5809454f5810f7e603cbd02daa036scroggo 16253965825b97a5809454f5810f7e603cbd02daa036scroggo# define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p) 16263965825b97a5809454f5810f7e603cbd02daa036scroggo#else 16273965825b97a5809454f5810f7e603cbd02daa036scroggo# define PNG_SKIP_CHUNKS(p) ((void)0) 16283965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* HANDLE_AS_UNKNOWN */ 16293965825b97a5809454f5810f7e603cbd02daa036scroggo 16303965825b97a5809454f5810f7e603cbd02daa036scroggo/* The following macro gives the exact rounded answer for all values in the 16313965825b97a5809454f5810f7e603cbd02daa036scroggo * range 0..255 (it actually divides by 51.2, but the rounding still generates 16323965825b97a5809454f5810f7e603cbd02daa036scroggo * the correct numbers 0..5 16333965825b97a5809454f5810f7e603cbd02daa036scroggo */ 16343965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8) 16353965825b97a5809454f5810f7e603cbd02daa036scroggo 16363965825b97a5809454f5810f7e603cbd02daa036scroggo/* Utility functions to make particular color-maps */ 16373965825b97a5809454f5810f7e603cbd02daa036scroggostatic void 16383965825b97a5809454f5810f7e603cbd02daa036scroggoset_file_encoding(png_image_read_control *display) 16393965825b97a5809454f5810f7e603cbd02daa036scroggo{ 16403965825b97a5809454f5810f7e603cbd02daa036scroggo png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma; 16413965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_gamma_significant(g) != 0) 16423965825b97a5809454f5810f7e603cbd02daa036scroggo { 16433965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_gamma_not_sRGB(g) != 0) 16443965825b97a5809454f5810f7e603cbd02daa036scroggo { 16453965825b97a5809454f5810f7e603cbd02daa036scroggo display->file_encoding = P_FILE; 16463965825b97a5809454f5810f7e603cbd02daa036scroggo display->gamma_to_linear = png_reciprocal(g); 16473965825b97a5809454f5810f7e603cbd02daa036scroggo } 16483965825b97a5809454f5810f7e603cbd02daa036scroggo 16493965825b97a5809454f5810f7e603cbd02daa036scroggo else 16503965825b97a5809454f5810f7e603cbd02daa036scroggo display->file_encoding = P_sRGB; 16513965825b97a5809454f5810f7e603cbd02daa036scroggo } 16523965825b97a5809454f5810f7e603cbd02daa036scroggo 16533965825b97a5809454f5810f7e603cbd02daa036scroggo else 16543965825b97a5809454f5810f7e603cbd02daa036scroggo display->file_encoding = P_LINEAR8; 16553965825b97a5809454f5810f7e603cbd02daa036scroggo} 16563965825b97a5809454f5810f7e603cbd02daa036scroggo 16573965825b97a5809454f5810f7e603cbd02daa036scroggostatic unsigned int 16583965825b97a5809454f5810f7e603cbd02daa036scroggodecode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) 16593965825b97a5809454f5810f7e603cbd02daa036scroggo{ 16603965825b97a5809454f5810f7e603cbd02daa036scroggo if (encoding == P_FILE) /* double check */ 16613965825b97a5809454f5810f7e603cbd02daa036scroggo encoding = display->file_encoding; 16623965825b97a5809454f5810f7e603cbd02daa036scroggo 16633965825b97a5809454f5810f7e603cbd02daa036scroggo if (encoding == P_NOTSET) /* must be the file encoding */ 16643965825b97a5809454f5810f7e603cbd02daa036scroggo { 16653965825b97a5809454f5810f7e603cbd02daa036scroggo set_file_encoding(display); 16663965825b97a5809454f5810f7e603cbd02daa036scroggo encoding = display->file_encoding; 16673965825b97a5809454f5810f7e603cbd02daa036scroggo } 16683965825b97a5809454f5810f7e603cbd02daa036scroggo 16693965825b97a5809454f5810f7e603cbd02daa036scroggo switch (encoding) 16703965825b97a5809454f5810f7e603cbd02daa036scroggo { 16713965825b97a5809454f5810f7e603cbd02daa036scroggo case P_FILE: 16723965825b97a5809454f5810f7e603cbd02daa036scroggo value = png_gamma_16bit_correct(value*257, display->gamma_to_linear); 16733965825b97a5809454f5810f7e603cbd02daa036scroggo break; 16743965825b97a5809454f5810f7e603cbd02daa036scroggo 16753965825b97a5809454f5810f7e603cbd02daa036scroggo case P_sRGB: 16763965825b97a5809454f5810f7e603cbd02daa036scroggo value = png_sRGB_table[value]; 16773965825b97a5809454f5810f7e603cbd02daa036scroggo break; 16783965825b97a5809454f5810f7e603cbd02daa036scroggo 16793965825b97a5809454f5810f7e603cbd02daa036scroggo case P_LINEAR: 16803965825b97a5809454f5810f7e603cbd02daa036scroggo break; 16813965825b97a5809454f5810f7e603cbd02daa036scroggo 16823965825b97a5809454f5810f7e603cbd02daa036scroggo case P_LINEAR8: 16833965825b97a5809454f5810f7e603cbd02daa036scroggo value *= 257; 16843965825b97a5809454f5810f7e603cbd02daa036scroggo break; 16853965825b97a5809454f5810f7e603cbd02daa036scroggo 16863965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef __GNUC__ 16873965825b97a5809454f5810f7e603cbd02daa036scroggo default: 16883965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(display->image->opaque->png_ptr, 16893965825b97a5809454f5810f7e603cbd02daa036scroggo "unexpected encoding (internal error)"); 16903965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 16913965825b97a5809454f5810f7e603cbd02daa036scroggo } 16923965825b97a5809454f5810f7e603cbd02daa036scroggo 16933965825b97a5809454f5810f7e603cbd02daa036scroggo return value; 16943965825b97a5809454f5810f7e603cbd02daa036scroggo} 16953965825b97a5809454f5810f7e603cbd02daa036scroggo 16963965825b97a5809454f5810f7e603cbd02daa036scroggostatic png_uint_32 16973965825b97a5809454f5810f7e603cbd02daa036scroggopng_colormap_compose(png_image_read_control *display, 16983965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha, 16993965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 background, int encoding) 17003965825b97a5809454f5810f7e603cbd02daa036scroggo{ 17013965825b97a5809454f5810f7e603cbd02daa036scroggo /* The file value is composed on the background, the background has the given 17023965825b97a5809454f5810f7e603cbd02daa036scroggo * encoding and so does the result, the file is encoded with P_FILE and the 17033965825b97a5809454f5810f7e603cbd02daa036scroggo * file and alpha are 8-bit values. The (output) encoding will always be 17043965825b97a5809454f5810f7e603cbd02daa036scroggo * P_LINEAR or P_sRGB. 17053965825b97a5809454f5810f7e603cbd02daa036scroggo */ 17063965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 f = decode_gamma(display, foreground, foreground_encoding); 17073965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 b = decode_gamma(display, background, encoding); 17083965825b97a5809454f5810f7e603cbd02daa036scroggo 17093965825b97a5809454f5810f7e603cbd02daa036scroggo /* The alpha is always an 8-bit value (it comes from the palette), the value 17103965825b97a5809454f5810f7e603cbd02daa036scroggo * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires. 17113965825b97a5809454f5810f7e603cbd02daa036scroggo */ 17123965825b97a5809454f5810f7e603cbd02daa036scroggo f = f * alpha + b * (255-alpha); 17133965825b97a5809454f5810f7e603cbd02daa036scroggo 17143965825b97a5809454f5810f7e603cbd02daa036scroggo if (encoding == P_LINEAR) 17153965825b97a5809454f5810f7e603cbd02daa036scroggo { 17163965825b97a5809454f5810f7e603cbd02daa036scroggo /* Scale to 65535; divide by 255, approximately (in fact this is extremely 17173965825b97a5809454f5810f7e603cbd02daa036scroggo * accurate, it divides by 255.00000005937181414556, with no overflow.) 17183965825b97a5809454f5810f7e603cbd02daa036scroggo */ 17193965825b97a5809454f5810f7e603cbd02daa036scroggo f *= 257; /* Now scaled by 65535 */ 17203965825b97a5809454f5810f7e603cbd02daa036scroggo f += f >> 16; 17213965825b97a5809454f5810f7e603cbd02daa036scroggo f = (f+32768) >> 16; 17223965825b97a5809454f5810f7e603cbd02daa036scroggo } 17233965825b97a5809454f5810f7e603cbd02daa036scroggo 17243965825b97a5809454f5810f7e603cbd02daa036scroggo else /* P_sRGB */ 17253965825b97a5809454f5810f7e603cbd02daa036scroggo f = PNG_sRGB_FROM_LINEAR(f); 17263965825b97a5809454f5810f7e603cbd02daa036scroggo 17273965825b97a5809454f5810f7e603cbd02daa036scroggo return f; 17283965825b97a5809454f5810f7e603cbd02daa036scroggo} 17293965825b97a5809454f5810f7e603cbd02daa036scroggo 17303965825b97a5809454f5810f7e603cbd02daa036scroggo/* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must 17313965825b97a5809454f5810f7e603cbd02daa036scroggo * be 8-bit. 17323965825b97a5809454f5810f7e603cbd02daa036scroggo */ 17333965825b97a5809454f5810f7e603cbd02daa036scroggostatic void 17343965825b97a5809454f5810f7e603cbd02daa036scroggopng_create_colormap_entry(png_image_read_control *display, 17353965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue, 17363965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 alpha, int encoding) 17373965825b97a5809454f5810f7e603cbd02daa036scroggo{ 17383965825b97a5809454f5810f7e603cbd02daa036scroggo png_imagep image = display->image; 17393965825b97a5809454f5810f7e603cbd02daa036scroggo const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ? 17403965825b97a5809454f5810f7e603cbd02daa036scroggo P_LINEAR : P_sRGB; 17413965825b97a5809454f5810f7e603cbd02daa036scroggo const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && 17423965825b97a5809454f5810f7e603cbd02daa036scroggo (red != green || green != blue); 17433965825b97a5809454f5810f7e603cbd02daa036scroggo 17443965825b97a5809454f5810f7e603cbd02daa036scroggo if (ip > 255) 17453965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(image->opaque->png_ptr, "color-map index out of range"); 17463965825b97a5809454f5810f7e603cbd02daa036scroggo 17473965825b97a5809454f5810f7e603cbd02daa036scroggo /* Update the cache with whether the file gamma is significantly different 17483965825b97a5809454f5810f7e603cbd02daa036scroggo * from sRGB. 17493965825b97a5809454f5810f7e603cbd02daa036scroggo */ 17503965825b97a5809454f5810f7e603cbd02daa036scroggo if (encoding == P_FILE) 17513965825b97a5809454f5810f7e603cbd02daa036scroggo { 17523965825b97a5809454f5810f7e603cbd02daa036scroggo if (display->file_encoding == P_NOTSET) 17533965825b97a5809454f5810f7e603cbd02daa036scroggo set_file_encoding(display); 17543965825b97a5809454f5810f7e603cbd02daa036scroggo 17553965825b97a5809454f5810f7e603cbd02daa036scroggo /* Note that the cached value may be P_FILE too, but if it is then the 17563965825b97a5809454f5810f7e603cbd02daa036scroggo * gamma_to_linear member has been set. 17573965825b97a5809454f5810f7e603cbd02daa036scroggo */ 17583965825b97a5809454f5810f7e603cbd02daa036scroggo encoding = display->file_encoding; 17593965825b97a5809454f5810f7e603cbd02daa036scroggo } 17603965825b97a5809454f5810f7e603cbd02daa036scroggo 17613965825b97a5809454f5810f7e603cbd02daa036scroggo if (encoding == P_FILE) 17623965825b97a5809454f5810f7e603cbd02daa036scroggo { 17633965825b97a5809454f5810f7e603cbd02daa036scroggo png_fixed_point g = display->gamma_to_linear; 17643965825b97a5809454f5810f7e603cbd02daa036scroggo 17653965825b97a5809454f5810f7e603cbd02daa036scroggo red = png_gamma_16bit_correct(red*257, g); 17663965825b97a5809454f5810f7e603cbd02daa036scroggo green = png_gamma_16bit_correct(green*257, g); 17673965825b97a5809454f5810f7e603cbd02daa036scroggo blue = png_gamma_16bit_correct(blue*257, g); 17683965825b97a5809454f5810f7e603cbd02daa036scroggo 17693965825b97a5809454f5810f7e603cbd02daa036scroggo if (convert_to_Y != 0 || output_encoding == P_LINEAR) 17703965825b97a5809454f5810f7e603cbd02daa036scroggo { 17713965825b97a5809454f5810f7e603cbd02daa036scroggo alpha *= 257; 17723965825b97a5809454f5810f7e603cbd02daa036scroggo encoding = P_LINEAR; 17733965825b97a5809454f5810f7e603cbd02daa036scroggo } 17743965825b97a5809454f5810f7e603cbd02daa036scroggo 17753965825b97a5809454f5810f7e603cbd02daa036scroggo else 17763965825b97a5809454f5810f7e603cbd02daa036scroggo { 17773965825b97a5809454f5810f7e603cbd02daa036scroggo red = PNG_sRGB_FROM_LINEAR(red * 255); 17783965825b97a5809454f5810f7e603cbd02daa036scroggo green = PNG_sRGB_FROM_LINEAR(green * 255); 17793965825b97a5809454f5810f7e603cbd02daa036scroggo blue = PNG_sRGB_FROM_LINEAR(blue * 255); 17803965825b97a5809454f5810f7e603cbd02daa036scroggo encoding = P_sRGB; 17813965825b97a5809454f5810f7e603cbd02daa036scroggo } 17823965825b97a5809454f5810f7e603cbd02daa036scroggo } 17833965825b97a5809454f5810f7e603cbd02daa036scroggo 17843965825b97a5809454f5810f7e603cbd02daa036scroggo else if (encoding == P_LINEAR8) 17853965825b97a5809454f5810f7e603cbd02daa036scroggo { 17863965825b97a5809454f5810f7e603cbd02daa036scroggo /* This encoding occurs quite frequently in test cases because PngSuite 17873965825b97a5809454f5810f7e603cbd02daa036scroggo * includes a gAMA 1.0 chunk with most images. 17883965825b97a5809454f5810f7e603cbd02daa036scroggo */ 17893965825b97a5809454f5810f7e603cbd02daa036scroggo red *= 257; 17903965825b97a5809454f5810f7e603cbd02daa036scroggo green *= 257; 17913965825b97a5809454f5810f7e603cbd02daa036scroggo blue *= 257; 17923965825b97a5809454f5810f7e603cbd02daa036scroggo alpha *= 257; 17933965825b97a5809454f5810f7e603cbd02daa036scroggo encoding = P_LINEAR; 17943965825b97a5809454f5810f7e603cbd02daa036scroggo } 17953965825b97a5809454f5810f7e603cbd02daa036scroggo 17963965825b97a5809454f5810f7e603cbd02daa036scroggo else if (encoding == P_sRGB && 17973965825b97a5809454f5810f7e603cbd02daa036scroggo (convert_to_Y != 0 || output_encoding == P_LINEAR)) 17983965825b97a5809454f5810f7e603cbd02daa036scroggo { 17993965825b97a5809454f5810f7e603cbd02daa036scroggo /* The values are 8-bit sRGB values, but must be converted to 16-bit 18003965825b97a5809454f5810f7e603cbd02daa036scroggo * linear. 18013965825b97a5809454f5810f7e603cbd02daa036scroggo */ 18023965825b97a5809454f5810f7e603cbd02daa036scroggo red = png_sRGB_table[red]; 18033965825b97a5809454f5810f7e603cbd02daa036scroggo green = png_sRGB_table[green]; 18043965825b97a5809454f5810f7e603cbd02daa036scroggo blue = png_sRGB_table[blue]; 18053965825b97a5809454f5810f7e603cbd02daa036scroggo alpha *= 257; 18063965825b97a5809454f5810f7e603cbd02daa036scroggo encoding = P_LINEAR; 18073965825b97a5809454f5810f7e603cbd02daa036scroggo } 18083965825b97a5809454f5810f7e603cbd02daa036scroggo 18093965825b97a5809454f5810f7e603cbd02daa036scroggo /* This is set if the color isn't gray but the output is. */ 18103965825b97a5809454f5810f7e603cbd02daa036scroggo if (encoding == P_LINEAR) 18113965825b97a5809454f5810f7e603cbd02daa036scroggo { 18123965825b97a5809454f5810f7e603cbd02daa036scroggo if (convert_to_Y != 0) 18133965825b97a5809454f5810f7e603cbd02daa036scroggo { 18143965825b97a5809454f5810f7e603cbd02daa036scroggo /* NOTE: these values are copied from png_do_rgb_to_gray */ 18153965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 y = (png_uint_32)6968 * red + (png_uint_32)23434 * green + 18163965825b97a5809454f5810f7e603cbd02daa036scroggo (png_uint_32)2366 * blue; 18173965825b97a5809454f5810f7e603cbd02daa036scroggo 18183965825b97a5809454f5810f7e603cbd02daa036scroggo if (output_encoding == P_LINEAR) 18193965825b97a5809454f5810f7e603cbd02daa036scroggo y = (y + 16384) >> 15; 18203965825b97a5809454f5810f7e603cbd02daa036scroggo 18213965825b97a5809454f5810f7e603cbd02daa036scroggo else 18223965825b97a5809454f5810f7e603cbd02daa036scroggo { 18233965825b97a5809454f5810f7e603cbd02daa036scroggo /* y is scaled by 32768, we need it scaled by 255: */ 18243965825b97a5809454f5810f7e603cbd02daa036scroggo y = (y + 128) >> 8; 18253965825b97a5809454f5810f7e603cbd02daa036scroggo y *= 255; 18263965825b97a5809454f5810f7e603cbd02daa036scroggo y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7); 18273965825b97a5809454f5810f7e603cbd02daa036scroggo alpha = PNG_DIV257(alpha); 18283965825b97a5809454f5810f7e603cbd02daa036scroggo encoding = P_sRGB; 18293965825b97a5809454f5810f7e603cbd02daa036scroggo } 18303965825b97a5809454f5810f7e603cbd02daa036scroggo 18313965825b97a5809454f5810f7e603cbd02daa036scroggo blue = red = green = y; 18323965825b97a5809454f5810f7e603cbd02daa036scroggo } 18333965825b97a5809454f5810f7e603cbd02daa036scroggo 18343965825b97a5809454f5810f7e603cbd02daa036scroggo else if (output_encoding == P_sRGB) 18353965825b97a5809454f5810f7e603cbd02daa036scroggo { 18363965825b97a5809454f5810f7e603cbd02daa036scroggo red = PNG_sRGB_FROM_LINEAR(red * 255); 18373965825b97a5809454f5810f7e603cbd02daa036scroggo green = PNG_sRGB_FROM_LINEAR(green * 255); 18383965825b97a5809454f5810f7e603cbd02daa036scroggo blue = PNG_sRGB_FROM_LINEAR(blue * 255); 18393965825b97a5809454f5810f7e603cbd02daa036scroggo alpha = PNG_DIV257(alpha); 18403965825b97a5809454f5810f7e603cbd02daa036scroggo encoding = P_sRGB; 18413965825b97a5809454f5810f7e603cbd02daa036scroggo } 18423965825b97a5809454f5810f7e603cbd02daa036scroggo } 18433965825b97a5809454f5810f7e603cbd02daa036scroggo 18443965825b97a5809454f5810f7e603cbd02daa036scroggo if (encoding != output_encoding) 18453965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(image->opaque->png_ptr, "bad encoding (internal error)"); 18463965825b97a5809454f5810f7e603cbd02daa036scroggo 18473965825b97a5809454f5810f7e603cbd02daa036scroggo /* Store the value. */ 18483965825b97a5809454f5810f7e603cbd02daa036scroggo { 18493965825b97a5809454f5810f7e603cbd02daa036scroggo# ifdef PNG_FORMAT_AFIRST_SUPPORTED 18503965825b97a5809454f5810f7e603cbd02daa036scroggo const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 && 18513965825b97a5809454f5810f7e603cbd02daa036scroggo (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; 18523965825b97a5809454f5810f7e603cbd02daa036scroggo# else 18533965825b97a5809454f5810f7e603cbd02daa036scroggo# define afirst 0 18543965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 18553965825b97a5809454f5810f7e603cbd02daa036scroggo# ifdef PNG_FORMAT_BGR_SUPPORTED 18563965825b97a5809454f5810f7e603cbd02daa036scroggo const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; 18573965825b97a5809454f5810f7e603cbd02daa036scroggo# else 18583965825b97a5809454f5810f7e603cbd02daa036scroggo# define bgr 0 18593965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 18603965825b97a5809454f5810f7e603cbd02daa036scroggo 18613965825b97a5809454f5810f7e603cbd02daa036scroggo if (output_encoding == P_LINEAR) 18623965825b97a5809454f5810f7e603cbd02daa036scroggo { 18633965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap); 18643965825b97a5809454f5810f7e603cbd02daa036scroggo 18653965825b97a5809454f5810f7e603cbd02daa036scroggo entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); 18663965825b97a5809454f5810f7e603cbd02daa036scroggo 18673965825b97a5809454f5810f7e603cbd02daa036scroggo /* The linear 16-bit values must be pre-multiplied by the alpha channel 18683965825b97a5809454f5810f7e603cbd02daa036scroggo * value, if less than 65535 (this is, effectively, composite on black 18693965825b97a5809454f5810f7e603cbd02daa036scroggo * if the alpha channel is removed.) 18703965825b97a5809454f5810f7e603cbd02daa036scroggo */ 18713965825b97a5809454f5810f7e603cbd02daa036scroggo switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) 18723965825b97a5809454f5810f7e603cbd02daa036scroggo { 18733965825b97a5809454f5810f7e603cbd02daa036scroggo case 4: 18743965825b97a5809454f5810f7e603cbd02daa036scroggo entry[afirst ? 0 : 3] = (png_uint_16)alpha; 18753965825b97a5809454f5810f7e603cbd02daa036scroggo /* FALL THROUGH */ 18763965825b97a5809454f5810f7e603cbd02daa036scroggo 18773965825b97a5809454f5810f7e603cbd02daa036scroggo case 3: 18783965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha < 65535) 18793965825b97a5809454f5810f7e603cbd02daa036scroggo { 18803965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha > 0) 18813965825b97a5809454f5810f7e603cbd02daa036scroggo { 18823965825b97a5809454f5810f7e603cbd02daa036scroggo blue = (blue * alpha + 32767U)/65535U; 18833965825b97a5809454f5810f7e603cbd02daa036scroggo green = (green * alpha + 32767U)/65535U; 18843965825b97a5809454f5810f7e603cbd02daa036scroggo red = (red * alpha + 32767U)/65535U; 18853965825b97a5809454f5810f7e603cbd02daa036scroggo } 18863965825b97a5809454f5810f7e603cbd02daa036scroggo 18873965825b97a5809454f5810f7e603cbd02daa036scroggo else 18883965825b97a5809454f5810f7e603cbd02daa036scroggo red = green = blue = 0; 18893965825b97a5809454f5810f7e603cbd02daa036scroggo } 18903965825b97a5809454f5810f7e603cbd02daa036scroggo entry[afirst + (2 ^ bgr)] = (png_uint_16)blue; 18913965825b97a5809454f5810f7e603cbd02daa036scroggo entry[afirst + 1] = (png_uint_16)green; 18923965825b97a5809454f5810f7e603cbd02daa036scroggo entry[afirst + bgr] = (png_uint_16)red; 18933965825b97a5809454f5810f7e603cbd02daa036scroggo break; 18943965825b97a5809454f5810f7e603cbd02daa036scroggo 18953965825b97a5809454f5810f7e603cbd02daa036scroggo case 2: 18963965825b97a5809454f5810f7e603cbd02daa036scroggo entry[1 ^ afirst] = (png_uint_16)alpha; 18973965825b97a5809454f5810f7e603cbd02daa036scroggo /* FALL THROUGH */ 18983965825b97a5809454f5810f7e603cbd02daa036scroggo 18993965825b97a5809454f5810f7e603cbd02daa036scroggo case 1: 19003965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha < 65535) 19013965825b97a5809454f5810f7e603cbd02daa036scroggo { 19023965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha > 0) 19033965825b97a5809454f5810f7e603cbd02daa036scroggo green = (green * alpha + 32767U)/65535U; 19043965825b97a5809454f5810f7e603cbd02daa036scroggo 19053965825b97a5809454f5810f7e603cbd02daa036scroggo else 19063965825b97a5809454f5810f7e603cbd02daa036scroggo green = 0; 19073965825b97a5809454f5810f7e603cbd02daa036scroggo } 19083965825b97a5809454f5810f7e603cbd02daa036scroggo entry[afirst] = (png_uint_16)green; 19093965825b97a5809454f5810f7e603cbd02daa036scroggo break; 19103965825b97a5809454f5810f7e603cbd02daa036scroggo 19113965825b97a5809454f5810f7e603cbd02daa036scroggo default: 19123965825b97a5809454f5810f7e603cbd02daa036scroggo break; 19133965825b97a5809454f5810f7e603cbd02daa036scroggo } 19143965825b97a5809454f5810f7e603cbd02daa036scroggo } 19153965825b97a5809454f5810f7e603cbd02daa036scroggo 19163965825b97a5809454f5810f7e603cbd02daa036scroggo else /* output encoding is P_sRGB */ 19173965825b97a5809454f5810f7e603cbd02daa036scroggo { 19183965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep entry = png_voidcast(png_bytep, display->colormap); 19193965825b97a5809454f5810f7e603cbd02daa036scroggo 19203965825b97a5809454f5810f7e603cbd02daa036scroggo entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); 19213965825b97a5809454f5810f7e603cbd02daa036scroggo 19223965825b97a5809454f5810f7e603cbd02daa036scroggo switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) 19233965825b97a5809454f5810f7e603cbd02daa036scroggo { 19243965825b97a5809454f5810f7e603cbd02daa036scroggo case 4: 19253965825b97a5809454f5810f7e603cbd02daa036scroggo entry[afirst ? 0 : 3] = (png_byte)alpha; 19263965825b97a5809454f5810f7e603cbd02daa036scroggo case 3: 19273965825b97a5809454f5810f7e603cbd02daa036scroggo entry[afirst + (2 ^ bgr)] = (png_byte)blue; 19283965825b97a5809454f5810f7e603cbd02daa036scroggo entry[afirst + 1] = (png_byte)green; 19293965825b97a5809454f5810f7e603cbd02daa036scroggo entry[afirst + bgr] = (png_byte)red; 19303965825b97a5809454f5810f7e603cbd02daa036scroggo break; 19313965825b97a5809454f5810f7e603cbd02daa036scroggo 19323965825b97a5809454f5810f7e603cbd02daa036scroggo case 2: 19333965825b97a5809454f5810f7e603cbd02daa036scroggo entry[1 ^ afirst] = (png_byte)alpha; 19343965825b97a5809454f5810f7e603cbd02daa036scroggo case 1: 19353965825b97a5809454f5810f7e603cbd02daa036scroggo entry[afirst] = (png_byte)green; 19363965825b97a5809454f5810f7e603cbd02daa036scroggo break; 19373965825b97a5809454f5810f7e603cbd02daa036scroggo 19383965825b97a5809454f5810f7e603cbd02daa036scroggo default: 19393965825b97a5809454f5810f7e603cbd02daa036scroggo break; 19403965825b97a5809454f5810f7e603cbd02daa036scroggo } 19413965825b97a5809454f5810f7e603cbd02daa036scroggo } 19423965825b97a5809454f5810f7e603cbd02daa036scroggo 19433965825b97a5809454f5810f7e603cbd02daa036scroggo# ifdef afirst 19443965825b97a5809454f5810f7e603cbd02daa036scroggo# undef afirst 19453965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 19463965825b97a5809454f5810f7e603cbd02daa036scroggo# ifdef bgr 19473965825b97a5809454f5810f7e603cbd02daa036scroggo# undef bgr 19483965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 19493965825b97a5809454f5810f7e603cbd02daa036scroggo } 19503965825b97a5809454f5810f7e603cbd02daa036scroggo} 19513965825b97a5809454f5810f7e603cbd02daa036scroggo 19523965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 19533965825b97a5809454f5810f7e603cbd02daa036scroggomake_gray_file_colormap(png_image_read_control *display) 19543965825b97a5809454f5810f7e603cbd02daa036scroggo{ 19553965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int i; 19563965825b97a5809454f5810f7e603cbd02daa036scroggo 19573965825b97a5809454f5810f7e603cbd02daa036scroggo for (i=0; i<256; ++i) 19583965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i, i, i, i, 255, P_FILE); 19593965825b97a5809454f5810f7e603cbd02daa036scroggo 19603965825b97a5809454f5810f7e603cbd02daa036scroggo return i; 19613965825b97a5809454f5810f7e603cbd02daa036scroggo} 19623965825b97a5809454f5810f7e603cbd02daa036scroggo 19633965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 19643965825b97a5809454f5810f7e603cbd02daa036scroggomake_gray_colormap(png_image_read_control *display) 19653965825b97a5809454f5810f7e603cbd02daa036scroggo{ 19663965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int i; 19673965825b97a5809454f5810f7e603cbd02daa036scroggo 19683965825b97a5809454f5810f7e603cbd02daa036scroggo for (i=0; i<256; ++i) 19693965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB); 19703965825b97a5809454f5810f7e603cbd02daa036scroggo 19713965825b97a5809454f5810f7e603cbd02daa036scroggo return i; 19723965825b97a5809454f5810f7e603cbd02daa036scroggo} 19733965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_GRAY_COLORMAP_ENTRIES 256 19743965825b97a5809454f5810f7e603cbd02daa036scroggo 19753965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 19763965825b97a5809454f5810f7e603cbd02daa036scroggomake_ga_colormap(png_image_read_control *display) 19773965825b97a5809454f5810f7e603cbd02daa036scroggo{ 19783965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int i, a; 19793965825b97a5809454f5810f7e603cbd02daa036scroggo 19803965825b97a5809454f5810f7e603cbd02daa036scroggo /* Alpha is retained, the output will be a color-map with entries 19813965825b97a5809454f5810f7e603cbd02daa036scroggo * selected by six levels of alpha. One transparent entry, 6 gray 19823965825b97a5809454f5810f7e603cbd02daa036scroggo * levels for all the intermediate alpha values, leaving 230 entries 19833965825b97a5809454f5810f7e603cbd02daa036scroggo * for the opaque grays. The color-map entries are the six values 19843965825b97a5809454f5810f7e603cbd02daa036scroggo * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the 19853965825b97a5809454f5810f7e603cbd02daa036scroggo * relevant entry. 19863965825b97a5809454f5810f7e603cbd02daa036scroggo * 19873965825b97a5809454f5810f7e603cbd02daa036scroggo * if (alpha > 229) // opaque 19883965825b97a5809454f5810f7e603cbd02daa036scroggo * { 19893965825b97a5809454f5810f7e603cbd02daa036scroggo * // The 231 entries are selected to make the math below work: 19903965825b97a5809454f5810f7e603cbd02daa036scroggo * base = 0; 19913965825b97a5809454f5810f7e603cbd02daa036scroggo * entry = (231 * gray + 128) >> 8; 19923965825b97a5809454f5810f7e603cbd02daa036scroggo * } 19933965825b97a5809454f5810f7e603cbd02daa036scroggo * else if (alpha < 26) // transparent 19943965825b97a5809454f5810f7e603cbd02daa036scroggo * { 19953965825b97a5809454f5810f7e603cbd02daa036scroggo * base = 231; 19963965825b97a5809454f5810f7e603cbd02daa036scroggo * entry = 0; 19973965825b97a5809454f5810f7e603cbd02daa036scroggo * } 19983965825b97a5809454f5810f7e603cbd02daa036scroggo * else // partially opaque 19993965825b97a5809454f5810f7e603cbd02daa036scroggo * { 20003965825b97a5809454f5810f7e603cbd02daa036scroggo * base = 226 + 6 * PNG_DIV51(alpha); 20013965825b97a5809454f5810f7e603cbd02daa036scroggo * entry = PNG_DIV51(gray); 20023965825b97a5809454f5810f7e603cbd02daa036scroggo * } 20033965825b97a5809454f5810f7e603cbd02daa036scroggo */ 20043965825b97a5809454f5810f7e603cbd02daa036scroggo i = 0; 20053965825b97a5809454f5810f7e603cbd02daa036scroggo while (i < 231) 20063965825b97a5809454f5810f7e603cbd02daa036scroggo { 20073965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int gray = (i * 256 + 115) / 231; 20083965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB); 20093965825b97a5809454f5810f7e603cbd02daa036scroggo } 20103965825b97a5809454f5810f7e603cbd02daa036scroggo 20113965825b97a5809454f5810f7e603cbd02daa036scroggo /* 255 is used here for the component values for consistency with the code 20123965825b97a5809454f5810f7e603cbd02daa036scroggo * that undoes premultiplication in pngwrite.c. 20133965825b97a5809454f5810f7e603cbd02daa036scroggo */ 20143965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB); 20153965825b97a5809454f5810f7e603cbd02daa036scroggo 20163965825b97a5809454f5810f7e603cbd02daa036scroggo for (a=1; a<5; ++a) 20173965825b97a5809454f5810f7e603cbd02daa036scroggo { 20183965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int g; 20193965825b97a5809454f5810f7e603cbd02daa036scroggo 20203965825b97a5809454f5810f7e603cbd02daa036scroggo for (g=0; g<6; ++g) 20213965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51, 20223965825b97a5809454f5810f7e603cbd02daa036scroggo P_sRGB); 20233965825b97a5809454f5810f7e603cbd02daa036scroggo } 20243965825b97a5809454f5810f7e603cbd02daa036scroggo 20253965825b97a5809454f5810f7e603cbd02daa036scroggo return i; 20263965825b97a5809454f5810f7e603cbd02daa036scroggo} 20273965825b97a5809454f5810f7e603cbd02daa036scroggo 20283965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_GA_COLORMAP_ENTRIES 256 20293965825b97a5809454f5810f7e603cbd02daa036scroggo 20303965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 20313965825b97a5809454f5810f7e603cbd02daa036scroggomake_rgb_colormap(png_image_read_control *display) 20323965825b97a5809454f5810f7e603cbd02daa036scroggo{ 20333965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int i, r; 20343965825b97a5809454f5810f7e603cbd02daa036scroggo 20353965825b97a5809454f5810f7e603cbd02daa036scroggo /* Build a 6x6x6 opaque RGB cube */ 20363965825b97a5809454f5810f7e603cbd02daa036scroggo for (i=r=0; r<6; ++r) 20373965825b97a5809454f5810f7e603cbd02daa036scroggo { 20383965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int g; 20393965825b97a5809454f5810f7e603cbd02daa036scroggo 20403965825b97a5809454f5810f7e603cbd02daa036scroggo for (g=0; g<6; ++g) 20413965825b97a5809454f5810f7e603cbd02daa036scroggo { 20423965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int b; 20433965825b97a5809454f5810f7e603cbd02daa036scroggo 20443965825b97a5809454f5810f7e603cbd02daa036scroggo for (b=0; b<6; ++b) 20453965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255, 20463965825b97a5809454f5810f7e603cbd02daa036scroggo P_sRGB); 20473965825b97a5809454f5810f7e603cbd02daa036scroggo } 20483965825b97a5809454f5810f7e603cbd02daa036scroggo } 20493965825b97a5809454f5810f7e603cbd02daa036scroggo 20503965825b97a5809454f5810f7e603cbd02daa036scroggo return i; 20513965825b97a5809454f5810f7e603cbd02daa036scroggo} 20523965825b97a5809454f5810f7e603cbd02daa036scroggo 20533965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_RGB_COLORMAP_ENTRIES 216 20543965825b97a5809454f5810f7e603cbd02daa036scroggo 20553965825b97a5809454f5810f7e603cbd02daa036scroggo/* Return a palette index to the above palette given three 8-bit sRGB values. */ 20563965825b97a5809454f5810f7e603cbd02daa036scroggo#define PNG_RGB_INDEX(r,g,b) \ 20573965825b97a5809454f5810f7e603cbd02daa036scroggo ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b))) 20583965825b97a5809454f5810f7e603cbd02daa036scroggo 20593965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 20603965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_read_colormap(png_voidp argument) 20613965825b97a5809454f5810f7e603cbd02daa036scroggo{ 20623965825b97a5809454f5810f7e603cbd02daa036scroggo png_image_read_control *display = 20633965825b97a5809454f5810f7e603cbd02daa036scroggo png_voidcast(png_image_read_control*, argument); 20643965825b97a5809454f5810f7e603cbd02daa036scroggo const png_imagep image = display->image; 20653965825b97a5809454f5810f7e603cbd02daa036scroggo 20663965825b97a5809454f5810f7e603cbd02daa036scroggo const png_structrp png_ptr = image->opaque->png_ptr; 20673965825b97a5809454f5810f7e603cbd02daa036scroggo const png_uint_32 output_format = image->format; 20683965825b97a5809454f5810f7e603cbd02daa036scroggo const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ? 20693965825b97a5809454f5810f7e603cbd02daa036scroggo P_LINEAR : P_sRGB; 20703965825b97a5809454f5810f7e603cbd02daa036scroggo 20713965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int cmap_entries; 20723965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int output_processing; /* Output processing option */ 20733965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */ 20743965825b97a5809454f5810f7e603cbd02daa036scroggo 20753965825b97a5809454f5810f7e603cbd02daa036scroggo /* Background information; the background color and the index of this color 20763965825b97a5809454f5810f7e603cbd02daa036scroggo * in the color-map if it exists (else 256). 20773965825b97a5809454f5810f7e603cbd02daa036scroggo */ 20783965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int background_index = 256; 20793965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 back_r, back_g, back_b; 20803965825b97a5809454f5810f7e603cbd02daa036scroggo 20813965825b97a5809454f5810f7e603cbd02daa036scroggo /* Flags to accumulate things that need to be done to the input. */ 20823965825b97a5809454f5810f7e603cbd02daa036scroggo int expand_tRNS = 0; 20833965825b97a5809454f5810f7e603cbd02daa036scroggo 20843965825b97a5809454f5810f7e603cbd02daa036scroggo /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is 20853965825b97a5809454f5810f7e603cbd02daa036scroggo * very difficult to do, the results look awful, and it is difficult to see 20863965825b97a5809454f5810f7e603cbd02daa036scroggo * what possible use it is because the application can't control the 20873965825b97a5809454f5810f7e603cbd02daa036scroggo * color-map. 20883965825b97a5809454f5810f7e603cbd02daa036scroggo */ 20893965825b97a5809454f5810f7e603cbd02daa036scroggo if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 || 20903965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->num_trans > 0) /* alpha in input */ && 20913965825b97a5809454f5810f7e603cbd02daa036scroggo ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */) 20923965825b97a5809454f5810f7e603cbd02daa036scroggo { 20933965825b97a5809454f5810f7e603cbd02daa036scroggo if (output_encoding == P_LINEAR) /* compose on black */ 20943965825b97a5809454f5810f7e603cbd02daa036scroggo back_b = back_g = back_r = 0; 20953965825b97a5809454f5810f7e603cbd02daa036scroggo 20963965825b97a5809454f5810f7e603cbd02daa036scroggo else if (display->background == NULL /* no way to remove it */) 20973965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, 20983965825b97a5809454f5810f7e603cbd02daa036scroggo "a background color must be supplied to remove alpha/transparency"); 20993965825b97a5809454f5810f7e603cbd02daa036scroggo 21003965825b97a5809454f5810f7e603cbd02daa036scroggo /* Get a copy of the background color (this avoids repeating the checks 21013965825b97a5809454f5810f7e603cbd02daa036scroggo * below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the 21023965825b97a5809454f5810f7e603cbd02daa036scroggo * output format. 21033965825b97a5809454f5810f7e603cbd02daa036scroggo */ 21043965825b97a5809454f5810f7e603cbd02daa036scroggo else 21053965825b97a5809454f5810f7e603cbd02daa036scroggo { 21063965825b97a5809454f5810f7e603cbd02daa036scroggo back_g = display->background->green; 21073965825b97a5809454f5810f7e603cbd02daa036scroggo if ((output_format & PNG_FORMAT_FLAG_COLOR) != 0) 21083965825b97a5809454f5810f7e603cbd02daa036scroggo { 21093965825b97a5809454f5810f7e603cbd02daa036scroggo back_r = display->background->red; 21103965825b97a5809454f5810f7e603cbd02daa036scroggo back_b = display->background->blue; 21113965825b97a5809454f5810f7e603cbd02daa036scroggo } 21123965825b97a5809454f5810f7e603cbd02daa036scroggo else 21133965825b97a5809454f5810f7e603cbd02daa036scroggo back_b = back_r = back_g; 21143965825b97a5809454f5810f7e603cbd02daa036scroggo } 21153965825b97a5809454f5810f7e603cbd02daa036scroggo } 21163965825b97a5809454f5810f7e603cbd02daa036scroggo 21173965825b97a5809454f5810f7e603cbd02daa036scroggo else if (output_encoding == P_LINEAR) 21183965825b97a5809454f5810f7e603cbd02daa036scroggo back_b = back_r = back_g = 65535; 21193965825b97a5809454f5810f7e603cbd02daa036scroggo 21203965825b97a5809454f5810f7e603cbd02daa036scroggo else 21213965825b97a5809454f5810f7e603cbd02daa036scroggo back_b = back_r = back_g = 255; 21223965825b97a5809454f5810f7e603cbd02daa036scroggo 21233965825b97a5809454f5810f7e603cbd02daa036scroggo /* Default the input file gamma if required - this is necessary because 21243965825b97a5809454f5810f7e603cbd02daa036scroggo * libpng assumes that if no gamma information is present the data is in the 21253965825b97a5809454f5810f7e603cbd02daa036scroggo * output format, but the simplified API deduces the gamma from the input 21263965825b97a5809454f5810f7e603cbd02daa036scroggo * format. 21273965825b97a5809454f5810f7e603cbd02daa036scroggo */ 21283965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0) 21293965825b97a5809454f5810f7e603cbd02daa036scroggo { 21303965825b97a5809454f5810f7e603cbd02daa036scroggo /* Do this directly, not using the png_colorspace functions, to ensure 21313965825b97a5809454f5810f7e603cbd02daa036scroggo * that it happens even if the colorspace is invalid (though probably if 21323965825b97a5809454f5810f7e603cbd02daa036scroggo * it is the setting will be ignored) Note that the same thing can be 21333965825b97a5809454f5810f7e603cbd02daa036scroggo * achieved at the application interface with png_set_gAMA. 21343965825b97a5809454f5810f7e603cbd02daa036scroggo */ 21353965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->bit_depth == 16 && 21363965825b97a5809454f5810f7e603cbd02daa036scroggo (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) 21373965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR; 21383965825b97a5809454f5810f7e603cbd02daa036scroggo 21393965825b97a5809454f5810f7e603cbd02daa036scroggo else 21403965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE; 21413965825b97a5809454f5810f7e603cbd02daa036scroggo 21423965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; 21433965825b97a5809454f5810f7e603cbd02daa036scroggo } 21443965825b97a5809454f5810f7e603cbd02daa036scroggo 21453965825b97a5809454f5810f7e603cbd02daa036scroggo /* Decide what to do based on the PNG color type of the input data. The 21463965825b97a5809454f5810f7e603cbd02daa036scroggo * utility function png_create_colormap_entry deals with most aspects of the 21473965825b97a5809454f5810f7e603cbd02daa036scroggo * output transformations; this code works out how to produce bytes of 21483965825b97a5809454f5810f7e603cbd02daa036scroggo * color-map entries from the original format. 21493965825b97a5809454f5810f7e603cbd02daa036scroggo */ 21503965825b97a5809454f5810f7e603cbd02daa036scroggo switch (png_ptr->color_type) 21513965825b97a5809454f5810f7e603cbd02daa036scroggo { 21523965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_COLOR_TYPE_GRAY: 21533965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->bit_depth <= 8) 21543965825b97a5809454f5810f7e603cbd02daa036scroggo { 21553965825b97a5809454f5810f7e603cbd02daa036scroggo /* There at most 256 colors in the output, regardless of 21563965825b97a5809454f5810f7e603cbd02daa036scroggo * transparency. 21573965825b97a5809454f5810f7e603cbd02daa036scroggo */ 21583965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0; 21593965825b97a5809454f5810f7e603cbd02daa036scroggo 21603965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = 1U << png_ptr->bit_depth; 21613965825b97a5809454f5810f7e603cbd02daa036scroggo if (cmap_entries > image->colormap_entries) 21623965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "gray[8] color-map: too few entries"); 21633965825b97a5809454f5810f7e603cbd02daa036scroggo 21643965825b97a5809454f5810f7e603cbd02daa036scroggo step = 255 / (cmap_entries - 1); 21653965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_NONE; 21663965825b97a5809454f5810f7e603cbd02daa036scroggo 21673965825b97a5809454f5810f7e603cbd02daa036scroggo /* If there is a tRNS chunk then this either selects a transparent 21683965825b97a5809454f5810f7e603cbd02daa036scroggo * value or, if the output has no alpha, the background color. 21693965825b97a5809454f5810f7e603cbd02daa036scroggo */ 21703965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->num_trans > 0) 21713965825b97a5809454f5810f7e603cbd02daa036scroggo { 21723965825b97a5809454f5810f7e603cbd02daa036scroggo trans = png_ptr->trans_color.gray; 21733965825b97a5809454f5810f7e603cbd02daa036scroggo 21743965825b97a5809454f5810f7e603cbd02daa036scroggo if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) 21753965825b97a5809454f5810f7e603cbd02daa036scroggo back_alpha = output_encoding == P_LINEAR ? 65535 : 255; 21763965825b97a5809454f5810f7e603cbd02daa036scroggo } 21773965825b97a5809454f5810f7e603cbd02daa036scroggo 21783965825b97a5809454f5810f7e603cbd02daa036scroggo /* png_create_colormap_entry just takes an RGBA and writes the 21793965825b97a5809454f5810f7e603cbd02daa036scroggo * corresponding color-map entry using the format from 'image', 21803965825b97a5809454f5810f7e603cbd02daa036scroggo * including the required conversion to sRGB or linear as 21813965825b97a5809454f5810f7e603cbd02daa036scroggo * appropriate. The input values are always either sRGB (if the 21823965825b97a5809454f5810f7e603cbd02daa036scroggo * gamma correction flag is 0) or 0..255 scaled file encoded values 21833965825b97a5809454f5810f7e603cbd02daa036scroggo * (if the function must gamma correct them). 21843965825b97a5809454f5810f7e603cbd02daa036scroggo */ 21853965825b97a5809454f5810f7e603cbd02daa036scroggo for (i=val=0; i<cmap_entries; ++i, val += step) 21863965825b97a5809454f5810f7e603cbd02daa036scroggo { 21873965825b97a5809454f5810f7e603cbd02daa036scroggo /* 'i' is a file value. While this will result in duplicated 21883965825b97a5809454f5810f7e603cbd02daa036scroggo * entries for 8-bit non-sRGB encoded files it is necessary to 21893965825b97a5809454f5810f7e603cbd02daa036scroggo * have non-gamma corrected values to do tRNS handling. 21903965825b97a5809454f5810f7e603cbd02daa036scroggo */ 21913965825b97a5809454f5810f7e603cbd02daa036scroggo if (i != trans) 21923965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i, val, val, val, 255, 21933965825b97a5809454f5810f7e603cbd02daa036scroggo P_FILE/*8-bit with file gamma*/); 21943965825b97a5809454f5810f7e603cbd02daa036scroggo 21953965825b97a5809454f5810f7e603cbd02daa036scroggo /* Else this entry is transparent. The colors don't matter if 21963965825b97a5809454f5810f7e603cbd02daa036scroggo * there is an alpha channel (back_alpha == 0), but it does no 21973965825b97a5809454f5810f7e603cbd02daa036scroggo * harm to pass them in; the values are not set above so this 21983965825b97a5809454f5810f7e603cbd02daa036scroggo * passes in white. 21993965825b97a5809454f5810f7e603cbd02daa036scroggo * 22003965825b97a5809454f5810f7e603cbd02daa036scroggo * NOTE: this preserves the full precision of the application 22013965825b97a5809454f5810f7e603cbd02daa036scroggo * supplied background color when it is used. 22023965825b97a5809454f5810f7e603cbd02daa036scroggo */ 22033965825b97a5809454f5810f7e603cbd02daa036scroggo else 22043965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i, back_r, back_g, back_b, 22053965825b97a5809454f5810f7e603cbd02daa036scroggo back_alpha, output_encoding); 22063965825b97a5809454f5810f7e603cbd02daa036scroggo } 22073965825b97a5809454f5810f7e603cbd02daa036scroggo 22083965825b97a5809454f5810f7e603cbd02daa036scroggo /* We need libpng to preserve the original encoding. */ 22093965825b97a5809454f5810f7e603cbd02daa036scroggo data_encoding = P_FILE; 22103965825b97a5809454f5810f7e603cbd02daa036scroggo 22113965825b97a5809454f5810f7e603cbd02daa036scroggo /* The rows from libpng, while technically gray values, are now also 22123965825b97a5809454f5810f7e603cbd02daa036scroggo * color-map indices; however, they may need to be expanded to 1 22133965825b97a5809454f5810f7e603cbd02daa036scroggo * byte per pixel. This is what png_set_packing does (i.e., it 22143965825b97a5809454f5810f7e603cbd02daa036scroggo * unpacks the bit values into bytes.) 22153965825b97a5809454f5810f7e603cbd02daa036scroggo */ 22163965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->bit_depth < 8) 22173965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_packing(png_ptr); 22183965825b97a5809454f5810f7e603cbd02daa036scroggo } 22193965825b97a5809454f5810f7e603cbd02daa036scroggo 22203965825b97a5809454f5810f7e603cbd02daa036scroggo else /* bit depth is 16 */ 22213965825b97a5809454f5810f7e603cbd02daa036scroggo { 22223965825b97a5809454f5810f7e603cbd02daa036scroggo /* The 16-bit input values can be converted directly to 8-bit gamma 22233965825b97a5809454f5810f7e603cbd02daa036scroggo * encoded values; however, if a tRNS chunk is present 257 color-map 22243965825b97a5809454f5810f7e603cbd02daa036scroggo * entries are required. This means that the extra entry requires 22253965825b97a5809454f5810f7e603cbd02daa036scroggo * special processing; add an alpha channel, sacrifice gray level 22263965825b97a5809454f5810f7e603cbd02daa036scroggo * 254 and convert transparent (alpha==0) entries to that. 22273965825b97a5809454f5810f7e603cbd02daa036scroggo * 22283965825b97a5809454f5810f7e603cbd02daa036scroggo * Use libpng to chop the data to 8 bits. Convert it to sRGB at the 22293965825b97a5809454f5810f7e603cbd02daa036scroggo * same time to minimize quality loss. If a tRNS chunk is present 22303965825b97a5809454f5810f7e603cbd02daa036scroggo * this means libpng must handle it too; otherwise it is impossible 22313965825b97a5809454f5810f7e603cbd02daa036scroggo * to do the exact match on the 16-bit value. 22323965825b97a5809454f5810f7e603cbd02daa036scroggo * 22333965825b97a5809454f5810f7e603cbd02daa036scroggo * If the output has no alpha channel *and* the background color is 22343965825b97a5809454f5810f7e603cbd02daa036scroggo * gray then it is possible to let libpng handle the substitution by 22353965825b97a5809454f5810f7e603cbd02daa036scroggo * ensuring that the corresponding gray level matches the background 22363965825b97a5809454f5810f7e603cbd02daa036scroggo * color exactly. 22373965825b97a5809454f5810f7e603cbd02daa036scroggo */ 22383965825b97a5809454f5810f7e603cbd02daa036scroggo data_encoding = P_sRGB; 22393965825b97a5809454f5810f7e603cbd02daa036scroggo 22403965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) 22413965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "gray[16] color-map: too few entries"); 22423965825b97a5809454f5810f7e603cbd02daa036scroggo 22433965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = make_gray_colormap(display); 22443965825b97a5809454f5810f7e603cbd02daa036scroggo 22453965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->num_trans > 0) 22463965825b97a5809454f5810f7e603cbd02daa036scroggo { 22473965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int back_alpha; 22483965825b97a5809454f5810f7e603cbd02daa036scroggo 22493965825b97a5809454f5810f7e603cbd02daa036scroggo if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0) 22503965825b97a5809454f5810f7e603cbd02daa036scroggo back_alpha = 0; 22513965825b97a5809454f5810f7e603cbd02daa036scroggo 22523965825b97a5809454f5810f7e603cbd02daa036scroggo else 22533965825b97a5809454f5810f7e603cbd02daa036scroggo { 22543965825b97a5809454f5810f7e603cbd02daa036scroggo if (back_r == back_g && back_g == back_b) 22553965825b97a5809454f5810f7e603cbd02daa036scroggo { 22563965825b97a5809454f5810f7e603cbd02daa036scroggo /* Background is gray; no special processing will be 22573965825b97a5809454f5810f7e603cbd02daa036scroggo * required. 22583965825b97a5809454f5810f7e603cbd02daa036scroggo */ 22593965825b97a5809454f5810f7e603cbd02daa036scroggo png_color_16 c; 22603965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 gray = back_g; 22613965825b97a5809454f5810f7e603cbd02daa036scroggo 22623965825b97a5809454f5810f7e603cbd02daa036scroggo if (output_encoding == P_LINEAR) 22633965825b97a5809454f5810f7e603cbd02daa036scroggo { 22643965825b97a5809454f5810f7e603cbd02daa036scroggo gray = PNG_sRGB_FROM_LINEAR(gray * 255); 22653965825b97a5809454f5810f7e603cbd02daa036scroggo 22663965825b97a5809454f5810f7e603cbd02daa036scroggo /* And make sure the corresponding palette entry 22673965825b97a5809454f5810f7e603cbd02daa036scroggo * matches. 22683965825b97a5809454f5810f7e603cbd02daa036scroggo */ 22693965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, gray, back_g, back_g, 22703965825b97a5809454f5810f7e603cbd02daa036scroggo back_g, 65535, P_LINEAR); 22713965825b97a5809454f5810f7e603cbd02daa036scroggo } 22723965825b97a5809454f5810f7e603cbd02daa036scroggo 22733965825b97a5809454f5810f7e603cbd02daa036scroggo /* The background passed to libpng, however, must be the 22743965825b97a5809454f5810f7e603cbd02daa036scroggo * sRGB value. 22753965825b97a5809454f5810f7e603cbd02daa036scroggo */ 22763965825b97a5809454f5810f7e603cbd02daa036scroggo c.index = 0; /*unused*/ 22773965825b97a5809454f5810f7e603cbd02daa036scroggo c.gray = c.red = c.green = c.blue = (png_uint_16)gray; 22783965825b97a5809454f5810f7e603cbd02daa036scroggo 22793965825b97a5809454f5810f7e603cbd02daa036scroggo /* NOTE: does this work without expanding tRNS to alpha? 22803965825b97a5809454f5810f7e603cbd02daa036scroggo * It should be the color->gray case below apparently 22813965825b97a5809454f5810f7e603cbd02daa036scroggo * doesn't. 22823965825b97a5809454f5810f7e603cbd02daa036scroggo */ 22833965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_background_fixed(png_ptr, &c, 22843965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, 22853965825b97a5809454f5810f7e603cbd02daa036scroggo 0/*gamma: not used*/); 22863965825b97a5809454f5810f7e603cbd02daa036scroggo 22873965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_NONE; 22883965825b97a5809454f5810f7e603cbd02daa036scroggo break; 22893965825b97a5809454f5810f7e603cbd02daa036scroggo } 22903965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef __COVERITY__ 22913965825b97a5809454f5810f7e603cbd02daa036scroggo /* Coverity claims that output_encoding cannot be 2 (P_LINEAR) 22923965825b97a5809454f5810f7e603cbd02daa036scroggo * here. 22933965825b97a5809454f5810f7e603cbd02daa036scroggo */ 22943965825b97a5809454f5810f7e603cbd02daa036scroggo back_alpha = 255; 22953965825b97a5809454f5810f7e603cbd02daa036scroggo#else 22963965825b97a5809454f5810f7e603cbd02daa036scroggo back_alpha = output_encoding == P_LINEAR ? 65535 : 255; 22973965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 22983965825b97a5809454f5810f7e603cbd02daa036scroggo } 22993965825b97a5809454f5810f7e603cbd02daa036scroggo 23003965825b97a5809454f5810f7e603cbd02daa036scroggo /* output_processing means that the libpng-processed row will be 23013965825b97a5809454f5810f7e603cbd02daa036scroggo * 8-bit GA and it has to be processing to single byte color-map 23023965825b97a5809454f5810f7e603cbd02daa036scroggo * values. Entry 254 is replaced by either a completely 23033965825b97a5809454f5810f7e603cbd02daa036scroggo * transparent entry or by the background color at full 23043965825b97a5809454f5810f7e603cbd02daa036scroggo * precision (and the background color is not a simple gray 23053965825b97a5809454f5810f7e603cbd02daa036scroggo * level in this case.) 23063965825b97a5809454f5810f7e603cbd02daa036scroggo */ 23073965825b97a5809454f5810f7e603cbd02daa036scroggo expand_tRNS = 1; 23083965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_TRANS; 23093965825b97a5809454f5810f7e603cbd02daa036scroggo background_index = 254; 23103965825b97a5809454f5810f7e603cbd02daa036scroggo 23113965825b97a5809454f5810f7e603cbd02daa036scroggo /* And set (overwrite) color-map entry 254 to the actual 23123965825b97a5809454f5810f7e603cbd02daa036scroggo * background color at full precision. 23133965825b97a5809454f5810f7e603cbd02daa036scroggo */ 23143965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, 254, back_r, back_g, back_b, 23153965825b97a5809454f5810f7e603cbd02daa036scroggo back_alpha, output_encoding); 23163965825b97a5809454f5810f7e603cbd02daa036scroggo } 23173965825b97a5809454f5810f7e603cbd02daa036scroggo 23183965825b97a5809454f5810f7e603cbd02daa036scroggo else 23193965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_NONE; 23203965825b97a5809454f5810f7e603cbd02daa036scroggo } 23213965825b97a5809454f5810f7e603cbd02daa036scroggo break; 23223965825b97a5809454f5810f7e603cbd02daa036scroggo 23233965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_COLOR_TYPE_GRAY_ALPHA: 23243965825b97a5809454f5810f7e603cbd02daa036scroggo /* 8-bit or 16-bit PNG with two channels - gray and alpha. A minimum 23253965825b97a5809454f5810f7e603cbd02daa036scroggo * of 65536 combinations. If, however, the alpha channel is to be 23263965825b97a5809454f5810f7e603cbd02daa036scroggo * removed there are only 256 possibilities if the background is gray. 23273965825b97a5809454f5810f7e603cbd02daa036scroggo * (Otherwise there is a subset of the 65536 possibilities defined by 23283965825b97a5809454f5810f7e603cbd02daa036scroggo * the triangle between black, white and the background color.) 23293965825b97a5809454f5810f7e603cbd02daa036scroggo * 23303965825b97a5809454f5810f7e603cbd02daa036scroggo * Reduce 16-bit files to 8-bit and sRGB encode the result. No need to 23313965825b97a5809454f5810f7e603cbd02daa036scroggo * worry about tRNS matching - tRNS is ignored if there is an alpha 23323965825b97a5809454f5810f7e603cbd02daa036scroggo * channel. 23333965825b97a5809454f5810f7e603cbd02daa036scroggo */ 23343965825b97a5809454f5810f7e603cbd02daa036scroggo data_encoding = P_sRGB; 23353965825b97a5809454f5810f7e603cbd02daa036scroggo 23363965825b97a5809454f5810f7e603cbd02daa036scroggo if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0) 23373965825b97a5809454f5810f7e603cbd02daa036scroggo { 23383965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) 23393965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "gray+alpha color-map: too few entries"); 23403965825b97a5809454f5810f7e603cbd02daa036scroggo 23413965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = make_ga_colormap(display); 23423965825b97a5809454f5810f7e603cbd02daa036scroggo 23433965825b97a5809454f5810f7e603cbd02daa036scroggo background_index = PNG_CMAP_GA_BACKGROUND; 23443965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_GA; 23453965825b97a5809454f5810f7e603cbd02daa036scroggo } 23463965825b97a5809454f5810f7e603cbd02daa036scroggo 23473965825b97a5809454f5810f7e603cbd02daa036scroggo else /* alpha is removed */ 23483965825b97a5809454f5810f7e603cbd02daa036scroggo { 23493965825b97a5809454f5810f7e603cbd02daa036scroggo /* Alpha must be removed as the PNG data is processed when the 23503965825b97a5809454f5810f7e603cbd02daa036scroggo * background is a color because the G and A channels are 23513965825b97a5809454f5810f7e603cbd02daa036scroggo * independent and the vector addition (non-parallel vectors) is a 23523965825b97a5809454f5810f7e603cbd02daa036scroggo * 2-D problem. 23533965825b97a5809454f5810f7e603cbd02daa036scroggo * 23543965825b97a5809454f5810f7e603cbd02daa036scroggo * This can be reduced to the same algorithm as above by making a 23553965825b97a5809454f5810f7e603cbd02daa036scroggo * colormap containing gray levels (for the opaque grays), a 23563965825b97a5809454f5810f7e603cbd02daa036scroggo * background entry (for a transparent pixel) and a set of four six 23573965825b97a5809454f5810f7e603cbd02daa036scroggo * level color values, one set for each intermediate alpha value. 23583965825b97a5809454f5810f7e603cbd02daa036scroggo * See the comments in make_ga_colormap for how this works in the 23593965825b97a5809454f5810f7e603cbd02daa036scroggo * per-pixel processing. 23603965825b97a5809454f5810f7e603cbd02daa036scroggo * 23613965825b97a5809454f5810f7e603cbd02daa036scroggo * If the background is gray, however, we only need a 256 entry gray 23623965825b97a5809454f5810f7e603cbd02daa036scroggo * level color map. It is sufficient to make the entry generated 23633965825b97a5809454f5810f7e603cbd02daa036scroggo * for the background color be exactly the color specified. 23643965825b97a5809454f5810f7e603cbd02daa036scroggo */ 23653965825b97a5809454f5810f7e603cbd02daa036scroggo if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 || 23663965825b97a5809454f5810f7e603cbd02daa036scroggo (back_r == back_g && back_g == back_b)) 23673965825b97a5809454f5810f7e603cbd02daa036scroggo { 23683965825b97a5809454f5810f7e603cbd02daa036scroggo /* Background is gray; no special processing will be required. */ 23693965825b97a5809454f5810f7e603cbd02daa036scroggo png_color_16 c; 23703965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 gray = back_g; 23713965825b97a5809454f5810f7e603cbd02daa036scroggo 23723965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) 23733965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "gray-alpha color-map: too few entries"); 23743965825b97a5809454f5810f7e603cbd02daa036scroggo 23753965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = make_gray_colormap(display); 23763965825b97a5809454f5810f7e603cbd02daa036scroggo 23773965825b97a5809454f5810f7e603cbd02daa036scroggo if (output_encoding == P_LINEAR) 23783965825b97a5809454f5810f7e603cbd02daa036scroggo { 23793965825b97a5809454f5810f7e603cbd02daa036scroggo gray = PNG_sRGB_FROM_LINEAR(gray * 255); 23803965825b97a5809454f5810f7e603cbd02daa036scroggo 23813965825b97a5809454f5810f7e603cbd02daa036scroggo /* And make sure the corresponding palette entry matches. */ 23823965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, gray, back_g, back_g, 23833965825b97a5809454f5810f7e603cbd02daa036scroggo back_g, 65535, P_LINEAR); 23843965825b97a5809454f5810f7e603cbd02daa036scroggo } 23853965825b97a5809454f5810f7e603cbd02daa036scroggo 23863965825b97a5809454f5810f7e603cbd02daa036scroggo /* The background passed to libpng, however, must be the sRGB 23873965825b97a5809454f5810f7e603cbd02daa036scroggo * value. 23883965825b97a5809454f5810f7e603cbd02daa036scroggo */ 23893965825b97a5809454f5810f7e603cbd02daa036scroggo c.index = 0; /*unused*/ 23903965825b97a5809454f5810f7e603cbd02daa036scroggo c.gray = c.red = c.green = c.blue = (png_uint_16)gray; 23913965825b97a5809454f5810f7e603cbd02daa036scroggo 23923965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_background_fixed(png_ptr, &c, 23933965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, 23943965825b97a5809454f5810f7e603cbd02daa036scroggo 0/*gamma: not used*/); 23953965825b97a5809454f5810f7e603cbd02daa036scroggo 23963965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_NONE; 23973965825b97a5809454f5810f7e603cbd02daa036scroggo } 23983965825b97a5809454f5810f7e603cbd02daa036scroggo 23993965825b97a5809454f5810f7e603cbd02daa036scroggo else 24003965825b97a5809454f5810f7e603cbd02daa036scroggo { 24013965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 i, a; 24023965825b97a5809454f5810f7e603cbd02daa036scroggo 24033965825b97a5809454f5810f7e603cbd02daa036scroggo /* This is the same as png_make_ga_colormap, above, except that 24043965825b97a5809454f5810f7e603cbd02daa036scroggo * the entries are all opaque. 24053965825b97a5809454f5810f7e603cbd02daa036scroggo */ 24063965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) 24073965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "ga-alpha color-map: too few entries"); 24083965825b97a5809454f5810f7e603cbd02daa036scroggo 24093965825b97a5809454f5810f7e603cbd02daa036scroggo i = 0; 24103965825b97a5809454f5810f7e603cbd02daa036scroggo while (i < 231) 24113965825b97a5809454f5810f7e603cbd02daa036scroggo { 24123965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 gray = (i * 256 + 115) / 231; 24133965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i++, gray, gray, gray, 24143965825b97a5809454f5810f7e603cbd02daa036scroggo 255, P_sRGB); 24153965825b97a5809454f5810f7e603cbd02daa036scroggo } 24163965825b97a5809454f5810f7e603cbd02daa036scroggo 24173965825b97a5809454f5810f7e603cbd02daa036scroggo /* NOTE: this preserves the full precision of the application 24183965825b97a5809454f5810f7e603cbd02daa036scroggo * background color. 24193965825b97a5809454f5810f7e603cbd02daa036scroggo */ 24203965825b97a5809454f5810f7e603cbd02daa036scroggo background_index = i; 24213965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i++, back_r, back_g, back_b, 24223965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef __COVERITY__ 24233965825b97a5809454f5810f7e603cbd02daa036scroggo /* Coverity claims that output_encoding cannot be 2 (P_LINEAR) 24243965825b97a5809454f5810f7e603cbd02daa036scroggo * here. 24253965825b97a5809454f5810f7e603cbd02daa036scroggo */ 255U, 24263965825b97a5809454f5810f7e603cbd02daa036scroggo#else 24273965825b97a5809454f5810f7e603cbd02daa036scroggo output_encoding == P_LINEAR ? 65535U : 255U, 24283965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 24293965825b97a5809454f5810f7e603cbd02daa036scroggo output_encoding); 24303965825b97a5809454f5810f7e603cbd02daa036scroggo 24313965825b97a5809454f5810f7e603cbd02daa036scroggo /* For non-opaque input composite on the sRGB background - this 24323965825b97a5809454f5810f7e603cbd02daa036scroggo * requires inverting the encoding for each component. The input 24333965825b97a5809454f5810f7e603cbd02daa036scroggo * is still converted to the sRGB encoding because this is a 24343965825b97a5809454f5810f7e603cbd02daa036scroggo * reasonable approximate to the logarithmic curve of human 24353965825b97a5809454f5810f7e603cbd02daa036scroggo * visual sensitivity, at least over the narrow range which PNG 24363965825b97a5809454f5810f7e603cbd02daa036scroggo * represents. Consequently 'G' is always sRGB encoded, while 24373965825b97a5809454f5810f7e603cbd02daa036scroggo * 'A' is linear. We need the linear background colors. 24383965825b97a5809454f5810f7e603cbd02daa036scroggo */ 24393965825b97a5809454f5810f7e603cbd02daa036scroggo if (output_encoding == P_sRGB) /* else already linear */ 24403965825b97a5809454f5810f7e603cbd02daa036scroggo { 24413965825b97a5809454f5810f7e603cbd02daa036scroggo /* This may produce a value not exactly matching the 24423965825b97a5809454f5810f7e603cbd02daa036scroggo * background, but that's ok because these numbers are only 24433965825b97a5809454f5810f7e603cbd02daa036scroggo * used when alpha != 0 24443965825b97a5809454f5810f7e603cbd02daa036scroggo */ 24453965825b97a5809454f5810f7e603cbd02daa036scroggo back_r = png_sRGB_table[back_r]; 24463965825b97a5809454f5810f7e603cbd02daa036scroggo back_g = png_sRGB_table[back_g]; 24473965825b97a5809454f5810f7e603cbd02daa036scroggo back_b = png_sRGB_table[back_b]; 24483965825b97a5809454f5810f7e603cbd02daa036scroggo } 24493965825b97a5809454f5810f7e603cbd02daa036scroggo 24503965825b97a5809454f5810f7e603cbd02daa036scroggo for (a=1; a<5; ++a) 24513965825b97a5809454f5810f7e603cbd02daa036scroggo { 24523965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int g; 24533965825b97a5809454f5810f7e603cbd02daa036scroggo 24543965825b97a5809454f5810f7e603cbd02daa036scroggo /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled 24553965825b97a5809454f5810f7e603cbd02daa036scroggo * by an 8-bit alpha value (0..255). 24563965825b97a5809454f5810f7e603cbd02daa036scroggo */ 24573965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 alpha = 51 * a; 24583965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 back_rx = (255-alpha) * back_r; 24593965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 back_gx = (255-alpha) * back_g; 24603965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 back_bx = (255-alpha) * back_b; 24613965825b97a5809454f5810f7e603cbd02daa036scroggo 24623965825b97a5809454f5810f7e603cbd02daa036scroggo for (g=0; g<6; ++g) 24633965825b97a5809454f5810f7e603cbd02daa036scroggo { 24643965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 gray = png_sRGB_table[g*51] * alpha; 24653965825b97a5809454f5810f7e603cbd02daa036scroggo 24663965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i++, 24673965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_sRGB_FROM_LINEAR(gray + back_rx), 24683965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_sRGB_FROM_LINEAR(gray + back_gx), 24693965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB); 24703965825b97a5809454f5810f7e603cbd02daa036scroggo } 24713965825b97a5809454f5810f7e603cbd02daa036scroggo } 24723965825b97a5809454f5810f7e603cbd02daa036scroggo 24733965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = i; 24743965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_GA; 24753965825b97a5809454f5810f7e603cbd02daa036scroggo } 24763965825b97a5809454f5810f7e603cbd02daa036scroggo } 24773965825b97a5809454f5810f7e603cbd02daa036scroggo break; 24783965825b97a5809454f5810f7e603cbd02daa036scroggo 24793965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_COLOR_TYPE_RGB: 24803965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_COLOR_TYPE_RGB_ALPHA: 24813965825b97a5809454f5810f7e603cbd02daa036scroggo /* Exclude the case where the output is gray; we can always handle this 24823965825b97a5809454f5810f7e603cbd02daa036scroggo * with the cases above. 24833965825b97a5809454f5810f7e603cbd02daa036scroggo */ 24843965825b97a5809454f5810f7e603cbd02daa036scroggo if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0) 24853965825b97a5809454f5810f7e603cbd02daa036scroggo { 24863965825b97a5809454f5810f7e603cbd02daa036scroggo /* The color-map will be grayscale, so we may as well convert the 24873965825b97a5809454f5810f7e603cbd02daa036scroggo * input RGB values to a simple grayscale and use the grayscale 24883965825b97a5809454f5810f7e603cbd02daa036scroggo * code above. 24893965825b97a5809454f5810f7e603cbd02daa036scroggo * 24903965825b97a5809454f5810f7e603cbd02daa036scroggo * NOTE: calling this apparently damages the recognition of the 24913965825b97a5809454f5810f7e603cbd02daa036scroggo * transparent color in background color handling; call 24923965825b97a5809454f5810f7e603cbd02daa036scroggo * png_set_tRNS_to_alpha before png_set_background_fixed. 24933965825b97a5809454f5810f7e603cbd02daa036scroggo */ 24943965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1, 24953965825b97a5809454f5810f7e603cbd02daa036scroggo -1); 24963965825b97a5809454f5810f7e603cbd02daa036scroggo data_encoding = P_sRGB; 24973965825b97a5809454f5810f7e603cbd02daa036scroggo 24983965825b97a5809454f5810f7e603cbd02daa036scroggo /* The output will now be one or two 8-bit gray or gray+alpha 24993965825b97a5809454f5810f7e603cbd02daa036scroggo * channels. The more complex case arises when the input has alpha. 25003965825b97a5809454f5810f7e603cbd02daa036scroggo */ 25013965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 25023965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->num_trans > 0) && 25033965825b97a5809454f5810f7e603cbd02daa036scroggo (output_format & PNG_FORMAT_FLAG_ALPHA) != 0) 25043965825b97a5809454f5810f7e603cbd02daa036scroggo { 25053965825b97a5809454f5810f7e603cbd02daa036scroggo /* Both input and output have an alpha channel, so no background 25063965825b97a5809454f5810f7e603cbd02daa036scroggo * processing is required; just map the GA bytes to the right 25073965825b97a5809454f5810f7e603cbd02daa036scroggo * color-map entry. 25083965825b97a5809454f5810f7e603cbd02daa036scroggo */ 25093965825b97a5809454f5810f7e603cbd02daa036scroggo expand_tRNS = 1; 25103965825b97a5809454f5810f7e603cbd02daa036scroggo 25113965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) 25123965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "rgb[ga] color-map: too few entries"); 25133965825b97a5809454f5810f7e603cbd02daa036scroggo 25143965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = make_ga_colormap(display); 25153965825b97a5809454f5810f7e603cbd02daa036scroggo background_index = PNG_CMAP_GA_BACKGROUND; 25163965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_GA; 25173965825b97a5809454f5810f7e603cbd02daa036scroggo } 25183965825b97a5809454f5810f7e603cbd02daa036scroggo 25193965825b97a5809454f5810f7e603cbd02daa036scroggo else 25203965825b97a5809454f5810f7e603cbd02daa036scroggo { 25213965825b97a5809454f5810f7e603cbd02daa036scroggo /* Either the input or the output has no alpha channel, so there 25223965825b97a5809454f5810f7e603cbd02daa036scroggo * will be no non-opaque pixels in the color-map; it will just be 25233965825b97a5809454f5810f7e603cbd02daa036scroggo * grayscale. 25243965825b97a5809454f5810f7e603cbd02daa036scroggo */ 25253965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) 25263965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "rgb[gray] color-map: too few entries"); 25273965825b97a5809454f5810f7e603cbd02daa036scroggo 25283965825b97a5809454f5810f7e603cbd02daa036scroggo /* Ideally this code would use libpng to do the gamma correction, 25293965825b97a5809454f5810f7e603cbd02daa036scroggo * but if an input alpha channel is to be removed we will hit the 25303965825b97a5809454f5810f7e603cbd02daa036scroggo * libpng bug in gamma+compose+rgb-to-gray (the double gamma 25313965825b97a5809454f5810f7e603cbd02daa036scroggo * correction bug). Fix this by dropping the gamma correction in 25323965825b97a5809454f5810f7e603cbd02daa036scroggo * this case and doing it in the palette; this will result in 25333965825b97a5809454f5810f7e603cbd02daa036scroggo * duplicate palette entries, but that's better than the 25343965825b97a5809454f5810f7e603cbd02daa036scroggo * alternative of double gamma correction. 25353965825b97a5809454f5810f7e603cbd02daa036scroggo */ 25363965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 25373965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->num_trans > 0) && 25383965825b97a5809454f5810f7e603cbd02daa036scroggo png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0) 25393965825b97a5809454f5810f7e603cbd02daa036scroggo { 25403965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = make_gray_file_colormap(display); 25413965825b97a5809454f5810f7e603cbd02daa036scroggo data_encoding = P_FILE; 25423965825b97a5809454f5810f7e603cbd02daa036scroggo } 25433965825b97a5809454f5810f7e603cbd02daa036scroggo 25443965825b97a5809454f5810f7e603cbd02daa036scroggo else 25453965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = make_gray_colormap(display); 25463965825b97a5809454f5810f7e603cbd02daa036scroggo 25473965825b97a5809454f5810f7e603cbd02daa036scroggo /* But if the input has alpha or transparency it must be removed 25483965825b97a5809454f5810f7e603cbd02daa036scroggo */ 25493965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 25503965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->num_trans > 0) 25513965825b97a5809454f5810f7e603cbd02daa036scroggo { 25523965825b97a5809454f5810f7e603cbd02daa036scroggo png_color_16 c; 25533965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 gray = back_g; 25543965825b97a5809454f5810f7e603cbd02daa036scroggo 25553965825b97a5809454f5810f7e603cbd02daa036scroggo /* We need to ensure that the application background exists in 25563965825b97a5809454f5810f7e603cbd02daa036scroggo * the colormap and that completely transparent pixels map to 25573965825b97a5809454f5810f7e603cbd02daa036scroggo * it. Achieve this simply by ensuring that the entry 25583965825b97a5809454f5810f7e603cbd02daa036scroggo * selected for the background really is the background color. 25593965825b97a5809454f5810f7e603cbd02daa036scroggo */ 25603965825b97a5809454f5810f7e603cbd02daa036scroggo if (data_encoding == P_FILE) /* from the fixup above */ 25613965825b97a5809454f5810f7e603cbd02daa036scroggo { 25623965825b97a5809454f5810f7e603cbd02daa036scroggo /* The app supplied a gray which is in output_encoding, we 25633965825b97a5809454f5810f7e603cbd02daa036scroggo * need to convert it to a value of the input (P_FILE) 25643965825b97a5809454f5810f7e603cbd02daa036scroggo * encoding then set this palette entry to the required 25653965825b97a5809454f5810f7e603cbd02daa036scroggo * output encoding. 25663965825b97a5809454f5810f7e603cbd02daa036scroggo */ 25673965825b97a5809454f5810f7e603cbd02daa036scroggo if (output_encoding == P_sRGB) 25683965825b97a5809454f5810f7e603cbd02daa036scroggo gray = png_sRGB_table[gray]; /* now P_LINEAR */ 25693965825b97a5809454f5810f7e603cbd02daa036scroggo 25703965825b97a5809454f5810f7e603cbd02daa036scroggo gray = PNG_DIV257(png_gamma_16bit_correct(gray, 25713965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->colorspace.gamma)); /* now P_FILE */ 25723965825b97a5809454f5810f7e603cbd02daa036scroggo 25733965825b97a5809454f5810f7e603cbd02daa036scroggo /* And make sure the corresponding palette entry contains 25743965825b97a5809454f5810f7e603cbd02daa036scroggo * exactly the required sRGB value. 25753965825b97a5809454f5810f7e603cbd02daa036scroggo */ 25763965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, gray, back_g, back_g, 25773965825b97a5809454f5810f7e603cbd02daa036scroggo back_g, 0/*unused*/, output_encoding); 25783965825b97a5809454f5810f7e603cbd02daa036scroggo } 25793965825b97a5809454f5810f7e603cbd02daa036scroggo 25803965825b97a5809454f5810f7e603cbd02daa036scroggo else if (output_encoding == P_LINEAR) 25813965825b97a5809454f5810f7e603cbd02daa036scroggo { 25823965825b97a5809454f5810f7e603cbd02daa036scroggo gray = PNG_sRGB_FROM_LINEAR(gray * 255); 25833965825b97a5809454f5810f7e603cbd02daa036scroggo 25843965825b97a5809454f5810f7e603cbd02daa036scroggo /* And make sure the corresponding palette entry matches. 25853965825b97a5809454f5810f7e603cbd02daa036scroggo */ 25863965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, gray, back_g, back_g, 25873965825b97a5809454f5810f7e603cbd02daa036scroggo back_g, 0/*unused*/, P_LINEAR); 25883965825b97a5809454f5810f7e603cbd02daa036scroggo } 25893965825b97a5809454f5810f7e603cbd02daa036scroggo 25903965825b97a5809454f5810f7e603cbd02daa036scroggo /* The background passed to libpng, however, must be the 25913965825b97a5809454f5810f7e603cbd02daa036scroggo * output (normally sRGB) value. 25923965825b97a5809454f5810f7e603cbd02daa036scroggo */ 25933965825b97a5809454f5810f7e603cbd02daa036scroggo c.index = 0; /*unused*/ 25943965825b97a5809454f5810f7e603cbd02daa036scroggo c.gray = c.red = c.green = c.blue = (png_uint_16)gray; 25953965825b97a5809454f5810f7e603cbd02daa036scroggo 25963965825b97a5809454f5810f7e603cbd02daa036scroggo /* NOTE: the following is apparently a bug in libpng. Without 25973965825b97a5809454f5810f7e603cbd02daa036scroggo * it the transparent color recognition in 25983965825b97a5809454f5810f7e603cbd02daa036scroggo * png_set_background_fixed seems to go wrong. 25993965825b97a5809454f5810f7e603cbd02daa036scroggo */ 26003965825b97a5809454f5810f7e603cbd02daa036scroggo expand_tRNS = 1; 26013965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_background_fixed(png_ptr, &c, 26023965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, 26033965825b97a5809454f5810f7e603cbd02daa036scroggo 0/*gamma: not used*/); 26043965825b97a5809454f5810f7e603cbd02daa036scroggo } 26053965825b97a5809454f5810f7e603cbd02daa036scroggo 26063965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_NONE; 26073965825b97a5809454f5810f7e603cbd02daa036scroggo } 26083965825b97a5809454f5810f7e603cbd02daa036scroggo } 26093965825b97a5809454f5810f7e603cbd02daa036scroggo 26103965825b97a5809454f5810f7e603cbd02daa036scroggo else /* output is color */ 26113965825b97a5809454f5810f7e603cbd02daa036scroggo { 26123965825b97a5809454f5810f7e603cbd02daa036scroggo /* We could use png_quantize here so long as there is no transparent 26133965825b97a5809454f5810f7e603cbd02daa036scroggo * color or alpha; png_quantize ignores alpha. Easier overall just 26143965825b97a5809454f5810f7e603cbd02daa036scroggo * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube. 26153965825b97a5809454f5810f7e603cbd02daa036scroggo * Consequently we always want libpng to produce sRGB data. 26163965825b97a5809454f5810f7e603cbd02daa036scroggo */ 26173965825b97a5809454f5810f7e603cbd02daa036scroggo data_encoding = P_sRGB; 26183965825b97a5809454f5810f7e603cbd02daa036scroggo 26193965825b97a5809454f5810f7e603cbd02daa036scroggo /* Is there any transparency or alpha? */ 26203965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 26213965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->num_trans > 0) 26223965825b97a5809454f5810f7e603cbd02daa036scroggo { 26233965825b97a5809454f5810f7e603cbd02daa036scroggo /* Is there alpha in the output too? If so all four channels are 26243965825b97a5809454f5810f7e603cbd02daa036scroggo * processed into a special RGB cube with alpha support. 26253965825b97a5809454f5810f7e603cbd02daa036scroggo */ 26263965825b97a5809454f5810f7e603cbd02daa036scroggo if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0) 26273965825b97a5809454f5810f7e603cbd02daa036scroggo { 26283965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 r; 26293965825b97a5809454f5810f7e603cbd02daa036scroggo 26303965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) 26313965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "rgb+alpha color-map: too few entries"); 26323965825b97a5809454f5810f7e603cbd02daa036scroggo 26333965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = make_rgb_colormap(display); 26343965825b97a5809454f5810f7e603cbd02daa036scroggo 26353965825b97a5809454f5810f7e603cbd02daa036scroggo /* Add a transparent entry. */ 26363965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, cmap_entries, 255, 255, 26373965825b97a5809454f5810f7e603cbd02daa036scroggo 255, 0, P_sRGB); 26383965825b97a5809454f5810f7e603cbd02daa036scroggo 26393965825b97a5809454f5810f7e603cbd02daa036scroggo /* This is stored as the background index for the processing 26403965825b97a5809454f5810f7e603cbd02daa036scroggo * algorithm. 26413965825b97a5809454f5810f7e603cbd02daa036scroggo */ 26423965825b97a5809454f5810f7e603cbd02daa036scroggo background_index = cmap_entries++; 26433965825b97a5809454f5810f7e603cbd02daa036scroggo 26443965825b97a5809454f5810f7e603cbd02daa036scroggo /* Add 27 r,g,b entries each with alpha 0.5. */ 26453965825b97a5809454f5810f7e603cbd02daa036scroggo for (r=0; r<256; r = (r << 1) | 0x7f) 26463965825b97a5809454f5810f7e603cbd02daa036scroggo { 26473965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 g; 26483965825b97a5809454f5810f7e603cbd02daa036scroggo 26493965825b97a5809454f5810f7e603cbd02daa036scroggo for (g=0; g<256; g = (g << 1) | 0x7f) 26503965825b97a5809454f5810f7e603cbd02daa036scroggo { 26513965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 b; 26523965825b97a5809454f5810f7e603cbd02daa036scroggo 26533965825b97a5809454f5810f7e603cbd02daa036scroggo /* This generates components with the values 0, 127 and 26543965825b97a5809454f5810f7e603cbd02daa036scroggo * 255 26553965825b97a5809454f5810f7e603cbd02daa036scroggo */ 26563965825b97a5809454f5810f7e603cbd02daa036scroggo for (b=0; b<256; b = (b << 1) | 0x7f) 26573965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, cmap_entries++, 26583965825b97a5809454f5810f7e603cbd02daa036scroggo r, g, b, 128, P_sRGB); 26593965825b97a5809454f5810f7e603cbd02daa036scroggo } 26603965825b97a5809454f5810f7e603cbd02daa036scroggo } 26613965825b97a5809454f5810f7e603cbd02daa036scroggo 26623965825b97a5809454f5810f7e603cbd02daa036scroggo expand_tRNS = 1; 26633965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_RGB_ALPHA; 26643965825b97a5809454f5810f7e603cbd02daa036scroggo } 26653965825b97a5809454f5810f7e603cbd02daa036scroggo 26663965825b97a5809454f5810f7e603cbd02daa036scroggo else 26673965825b97a5809454f5810f7e603cbd02daa036scroggo { 26683965825b97a5809454f5810f7e603cbd02daa036scroggo /* Alpha/transparency must be removed. The background must 26693965825b97a5809454f5810f7e603cbd02daa036scroggo * exist in the color map (achieved by setting adding it after 26703965825b97a5809454f5810f7e603cbd02daa036scroggo * the 666 color-map). If the standard processing code will 26713965825b97a5809454f5810f7e603cbd02daa036scroggo * pick up this entry automatically that's all that is 26723965825b97a5809454f5810f7e603cbd02daa036scroggo * required; libpng can be called to do the background 26733965825b97a5809454f5810f7e603cbd02daa036scroggo * processing. 26743965825b97a5809454f5810f7e603cbd02daa036scroggo */ 26753965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int sample_size = 26763965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_IMAGE_SAMPLE_SIZE(output_format); 26773965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 r, g, b; /* sRGB background */ 26783965825b97a5809454f5810f7e603cbd02daa036scroggo 26793965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) 26803965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "rgb-alpha color-map: too few entries"); 26813965825b97a5809454f5810f7e603cbd02daa036scroggo 26823965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = make_rgb_colormap(display); 26833965825b97a5809454f5810f7e603cbd02daa036scroggo 26843965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, cmap_entries, back_r, 26853965825b97a5809454f5810f7e603cbd02daa036scroggo back_g, back_b, 0/*unused*/, output_encoding); 26863965825b97a5809454f5810f7e603cbd02daa036scroggo 26873965825b97a5809454f5810f7e603cbd02daa036scroggo if (output_encoding == P_LINEAR) 26883965825b97a5809454f5810f7e603cbd02daa036scroggo { 26893965825b97a5809454f5810f7e603cbd02daa036scroggo r = PNG_sRGB_FROM_LINEAR(back_r * 255); 26903965825b97a5809454f5810f7e603cbd02daa036scroggo g = PNG_sRGB_FROM_LINEAR(back_g * 255); 26913965825b97a5809454f5810f7e603cbd02daa036scroggo b = PNG_sRGB_FROM_LINEAR(back_b * 255); 26923965825b97a5809454f5810f7e603cbd02daa036scroggo } 26933965825b97a5809454f5810f7e603cbd02daa036scroggo 26943965825b97a5809454f5810f7e603cbd02daa036scroggo else 26953965825b97a5809454f5810f7e603cbd02daa036scroggo { 26963965825b97a5809454f5810f7e603cbd02daa036scroggo r = back_r; 26973965825b97a5809454f5810f7e603cbd02daa036scroggo g = back_g; 26983965825b97a5809454f5810f7e603cbd02daa036scroggo b = back_g; 26993965825b97a5809454f5810f7e603cbd02daa036scroggo } 27003965825b97a5809454f5810f7e603cbd02daa036scroggo 27013965825b97a5809454f5810f7e603cbd02daa036scroggo /* Compare the newly-created color-map entry with the one the 27023965825b97a5809454f5810f7e603cbd02daa036scroggo * PNG_CMAP_RGB algorithm will use. If the two entries don't 27033965825b97a5809454f5810f7e603cbd02daa036scroggo * match, add the new one and set this as the background 27043965825b97a5809454f5810f7e603cbd02daa036scroggo * index. 27053965825b97a5809454f5810f7e603cbd02daa036scroggo */ 27063965825b97a5809454f5810f7e603cbd02daa036scroggo if (memcmp((png_const_bytep)display->colormap + 27073965825b97a5809454f5810f7e603cbd02daa036scroggo sample_size * cmap_entries, 27083965825b97a5809454f5810f7e603cbd02daa036scroggo (png_const_bytep)display->colormap + 27093965825b97a5809454f5810f7e603cbd02daa036scroggo sample_size * PNG_RGB_INDEX(r,g,b), 27103965825b97a5809454f5810f7e603cbd02daa036scroggo sample_size) != 0) 27113965825b97a5809454f5810f7e603cbd02daa036scroggo { 27123965825b97a5809454f5810f7e603cbd02daa036scroggo /* The background color must be added. */ 27133965825b97a5809454f5810f7e603cbd02daa036scroggo background_index = cmap_entries++; 27143965825b97a5809454f5810f7e603cbd02daa036scroggo 27153965825b97a5809454f5810f7e603cbd02daa036scroggo /* Add 27 r,g,b entries each with created by composing with 27163965825b97a5809454f5810f7e603cbd02daa036scroggo * the background at alpha 0.5. 27173965825b97a5809454f5810f7e603cbd02daa036scroggo */ 27183965825b97a5809454f5810f7e603cbd02daa036scroggo for (r=0; r<256; r = (r << 1) | 0x7f) 27193965825b97a5809454f5810f7e603cbd02daa036scroggo { 27203965825b97a5809454f5810f7e603cbd02daa036scroggo for (g=0; g<256; g = (g << 1) | 0x7f) 27213965825b97a5809454f5810f7e603cbd02daa036scroggo { 27223965825b97a5809454f5810f7e603cbd02daa036scroggo /* This generates components with the values 0, 127 27233965825b97a5809454f5810f7e603cbd02daa036scroggo * and 255 27243965825b97a5809454f5810f7e603cbd02daa036scroggo */ 27253965825b97a5809454f5810f7e603cbd02daa036scroggo for (b=0; b<256; b = (b << 1) | 0x7f) 27263965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, cmap_entries++, 27273965825b97a5809454f5810f7e603cbd02daa036scroggo png_colormap_compose(display, r, P_sRGB, 128, 27283965825b97a5809454f5810f7e603cbd02daa036scroggo back_r, output_encoding), 27293965825b97a5809454f5810f7e603cbd02daa036scroggo png_colormap_compose(display, g, P_sRGB, 128, 27303965825b97a5809454f5810f7e603cbd02daa036scroggo back_g, output_encoding), 27313965825b97a5809454f5810f7e603cbd02daa036scroggo png_colormap_compose(display, b, P_sRGB, 128, 27323965825b97a5809454f5810f7e603cbd02daa036scroggo back_b, output_encoding), 27333965825b97a5809454f5810f7e603cbd02daa036scroggo 0/*unused*/, output_encoding); 27343965825b97a5809454f5810f7e603cbd02daa036scroggo } 27353965825b97a5809454f5810f7e603cbd02daa036scroggo } 27363965825b97a5809454f5810f7e603cbd02daa036scroggo 27373965825b97a5809454f5810f7e603cbd02daa036scroggo expand_tRNS = 1; 27383965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_RGB_ALPHA; 27393965825b97a5809454f5810f7e603cbd02daa036scroggo } 27403965825b97a5809454f5810f7e603cbd02daa036scroggo 27413965825b97a5809454f5810f7e603cbd02daa036scroggo else /* background color is in the standard color-map */ 27423965825b97a5809454f5810f7e603cbd02daa036scroggo { 27433965825b97a5809454f5810f7e603cbd02daa036scroggo png_color_16 c; 27443965825b97a5809454f5810f7e603cbd02daa036scroggo 27453965825b97a5809454f5810f7e603cbd02daa036scroggo c.index = 0; /*unused*/ 27463965825b97a5809454f5810f7e603cbd02daa036scroggo c.red = (png_uint_16)back_r; 27473965825b97a5809454f5810f7e603cbd02daa036scroggo c.gray = c.green = (png_uint_16)back_g; 27483965825b97a5809454f5810f7e603cbd02daa036scroggo c.blue = (png_uint_16)back_b; 27493965825b97a5809454f5810f7e603cbd02daa036scroggo 27503965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_background_fixed(png_ptr, &c, 27513965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, 27523965825b97a5809454f5810f7e603cbd02daa036scroggo 0/*gamma: not used*/); 27533965825b97a5809454f5810f7e603cbd02daa036scroggo 27543965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_RGB; 27553965825b97a5809454f5810f7e603cbd02daa036scroggo } 27563965825b97a5809454f5810f7e603cbd02daa036scroggo } 27573965825b97a5809454f5810f7e603cbd02daa036scroggo } 27583965825b97a5809454f5810f7e603cbd02daa036scroggo 27593965825b97a5809454f5810f7e603cbd02daa036scroggo else /* no alpha or transparency in the input */ 27603965825b97a5809454f5810f7e603cbd02daa036scroggo { 27613965825b97a5809454f5810f7e603cbd02daa036scroggo /* Alpha in the output is irrelevant, simply map the opaque input 27623965825b97a5809454f5810f7e603cbd02daa036scroggo * pixels to the 6x6x6 color-map. 27633965825b97a5809454f5810f7e603cbd02daa036scroggo */ 27643965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries) 27653965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "rgb color-map: too few entries"); 27663965825b97a5809454f5810f7e603cbd02daa036scroggo 27673965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = make_rgb_colormap(display); 27683965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_RGB; 27693965825b97a5809454f5810f7e603cbd02daa036scroggo } 27703965825b97a5809454f5810f7e603cbd02daa036scroggo } 27713965825b97a5809454f5810f7e603cbd02daa036scroggo break; 27723965825b97a5809454f5810f7e603cbd02daa036scroggo 27733965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_COLOR_TYPE_PALETTE: 27743965825b97a5809454f5810f7e603cbd02daa036scroggo /* It's already got a color-map. It may be necessary to eliminate the 27753965825b97a5809454f5810f7e603cbd02daa036scroggo * tRNS entries though. 27763965825b97a5809454f5810f7e603cbd02daa036scroggo */ 27773965825b97a5809454f5810f7e603cbd02daa036scroggo { 27783965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int num_trans = png_ptr->num_trans; 27793965825b97a5809454f5810f7e603cbd02daa036scroggo png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL; 27803965825b97a5809454f5810f7e603cbd02daa036scroggo png_const_colorp colormap = png_ptr->palette; 27813965825b97a5809454f5810f7e603cbd02daa036scroggo const int do_background = trans != NULL && 27823965825b97a5809454f5810f7e603cbd02daa036scroggo (output_format & PNG_FORMAT_FLAG_ALPHA) == 0; 27833965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int i; 27843965825b97a5809454f5810f7e603cbd02daa036scroggo 27853965825b97a5809454f5810f7e603cbd02daa036scroggo /* Just in case: */ 27863965825b97a5809454f5810f7e603cbd02daa036scroggo if (trans == NULL) 27873965825b97a5809454f5810f7e603cbd02daa036scroggo num_trans = 0; 27883965825b97a5809454f5810f7e603cbd02daa036scroggo 27893965825b97a5809454f5810f7e603cbd02daa036scroggo output_processing = PNG_CMAP_NONE; 27903965825b97a5809454f5810f7e603cbd02daa036scroggo data_encoding = P_FILE; /* Don't change from color-map indices */ 27913965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = png_ptr->num_palette; 27923965825b97a5809454f5810f7e603cbd02daa036scroggo if (cmap_entries > 256) 27933965825b97a5809454f5810f7e603cbd02daa036scroggo cmap_entries = 256; 27943965825b97a5809454f5810f7e603cbd02daa036scroggo 27953965825b97a5809454f5810f7e603cbd02daa036scroggo if (cmap_entries > image->colormap_entries) 27963965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "palette color-map: too few entries"); 27973965825b97a5809454f5810f7e603cbd02daa036scroggo 27983965825b97a5809454f5810f7e603cbd02daa036scroggo for (i=0; i < cmap_entries; ++i) 27993965825b97a5809454f5810f7e603cbd02daa036scroggo { 28003965825b97a5809454f5810f7e603cbd02daa036scroggo if (do_background != 0 && i < num_trans && trans[i] < 255) 28013965825b97a5809454f5810f7e603cbd02daa036scroggo { 28023965825b97a5809454f5810f7e603cbd02daa036scroggo if (trans[i] == 0) 28033965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i, back_r, back_g, 28043965825b97a5809454f5810f7e603cbd02daa036scroggo back_b, 0, output_encoding); 28053965825b97a5809454f5810f7e603cbd02daa036scroggo 28063965825b97a5809454f5810f7e603cbd02daa036scroggo else 28073965825b97a5809454f5810f7e603cbd02daa036scroggo { 28083965825b97a5809454f5810f7e603cbd02daa036scroggo /* Must compose the PNG file color in the color-map entry 28093965825b97a5809454f5810f7e603cbd02daa036scroggo * on the sRGB color in 'back'. 28103965825b97a5809454f5810f7e603cbd02daa036scroggo */ 28113965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i, 28123965825b97a5809454f5810f7e603cbd02daa036scroggo png_colormap_compose(display, colormap[i].red, P_FILE, 28133965825b97a5809454f5810f7e603cbd02daa036scroggo trans[i], back_r, output_encoding), 28143965825b97a5809454f5810f7e603cbd02daa036scroggo png_colormap_compose(display, colormap[i].green, P_FILE, 28153965825b97a5809454f5810f7e603cbd02daa036scroggo trans[i], back_g, output_encoding), 28163965825b97a5809454f5810f7e603cbd02daa036scroggo png_colormap_compose(display, colormap[i].blue, P_FILE, 28173965825b97a5809454f5810f7e603cbd02daa036scroggo trans[i], back_b, output_encoding), 28183965825b97a5809454f5810f7e603cbd02daa036scroggo output_encoding == P_LINEAR ? trans[i] * 257U : 28193965825b97a5809454f5810f7e603cbd02daa036scroggo trans[i], 28203965825b97a5809454f5810f7e603cbd02daa036scroggo output_encoding); 28213965825b97a5809454f5810f7e603cbd02daa036scroggo } 28223965825b97a5809454f5810f7e603cbd02daa036scroggo } 28233965825b97a5809454f5810f7e603cbd02daa036scroggo 28243965825b97a5809454f5810f7e603cbd02daa036scroggo else 28253965825b97a5809454f5810f7e603cbd02daa036scroggo png_create_colormap_entry(display, i, colormap[i].red, 28263965825b97a5809454f5810f7e603cbd02daa036scroggo colormap[i].green, colormap[i].blue, 28273965825b97a5809454f5810f7e603cbd02daa036scroggo i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/); 28283965825b97a5809454f5810f7e603cbd02daa036scroggo } 28293965825b97a5809454f5810f7e603cbd02daa036scroggo 28303965825b97a5809454f5810f7e603cbd02daa036scroggo /* The PNG data may have indices packed in fewer than 8 bits, it 28313965825b97a5809454f5810f7e603cbd02daa036scroggo * must be expanded if so. 28323965825b97a5809454f5810f7e603cbd02daa036scroggo */ 28333965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->bit_depth < 8) 28343965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_packing(png_ptr); 28353965825b97a5809454f5810f7e603cbd02daa036scroggo } 28363965825b97a5809454f5810f7e603cbd02daa036scroggo break; 28373965825b97a5809454f5810f7e603cbd02daa036scroggo 28383965825b97a5809454f5810f7e603cbd02daa036scroggo default: 28393965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "invalid PNG color type"); 28403965825b97a5809454f5810f7e603cbd02daa036scroggo /*NOT REACHED*/ 28413965825b97a5809454f5810f7e603cbd02daa036scroggo } 28423965825b97a5809454f5810f7e603cbd02daa036scroggo 28433965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now deal with the output processing */ 28443965825b97a5809454f5810f7e603cbd02daa036scroggo if (expand_tRNS != 0 && png_ptr->num_trans > 0 && 28453965825b97a5809454f5810f7e603cbd02daa036scroggo (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0) 28463965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_tRNS_to_alpha(png_ptr); 28473965825b97a5809454f5810f7e603cbd02daa036scroggo 28483965825b97a5809454f5810f7e603cbd02daa036scroggo switch (data_encoding) 28493965825b97a5809454f5810f7e603cbd02daa036scroggo { 28503965825b97a5809454f5810f7e603cbd02daa036scroggo case P_sRGB: 28513965825b97a5809454f5810f7e603cbd02daa036scroggo /* Change to 8-bit sRGB */ 28523965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); 28533965825b97a5809454f5810f7e603cbd02daa036scroggo /* FALL THROUGH */ 28543965825b97a5809454f5810f7e603cbd02daa036scroggo 28553965825b97a5809454f5810f7e603cbd02daa036scroggo case P_FILE: 28563965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->bit_depth > 8) 28573965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_scale_16(png_ptr); 28583965825b97a5809454f5810f7e603cbd02daa036scroggo break; 28593965825b97a5809454f5810f7e603cbd02daa036scroggo 28603965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef __GNUC__ 28613965825b97a5809454f5810f7e603cbd02daa036scroggo default: 28623965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "bad data option (internal error)"); 28633965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 28643965825b97a5809454f5810f7e603cbd02daa036scroggo } 28653965825b97a5809454f5810f7e603cbd02daa036scroggo 28663965825b97a5809454f5810f7e603cbd02daa036scroggo if (cmap_entries > 256 || cmap_entries > image->colormap_entries) 28673965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "color map overflow (BAD internal error)"); 28683965825b97a5809454f5810f7e603cbd02daa036scroggo 28693965825b97a5809454f5810f7e603cbd02daa036scroggo image->colormap_entries = cmap_entries; 28703965825b97a5809454f5810f7e603cbd02daa036scroggo 28713965825b97a5809454f5810f7e603cbd02daa036scroggo /* Double check using the recorded background index */ 28723965825b97a5809454f5810f7e603cbd02daa036scroggo switch (output_processing) 28733965825b97a5809454f5810f7e603cbd02daa036scroggo { 28743965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_NONE: 28753965825b97a5809454f5810f7e603cbd02daa036scroggo if (background_index != PNG_CMAP_NONE_BACKGROUND) 28763965825b97a5809454f5810f7e603cbd02daa036scroggo goto bad_background; 28773965825b97a5809454f5810f7e603cbd02daa036scroggo break; 28783965825b97a5809454f5810f7e603cbd02daa036scroggo 28793965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_GA: 28803965825b97a5809454f5810f7e603cbd02daa036scroggo if (background_index != PNG_CMAP_GA_BACKGROUND) 28813965825b97a5809454f5810f7e603cbd02daa036scroggo goto bad_background; 28823965825b97a5809454f5810f7e603cbd02daa036scroggo break; 28833965825b97a5809454f5810f7e603cbd02daa036scroggo 28843965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_TRANS: 28853965825b97a5809454f5810f7e603cbd02daa036scroggo if (background_index >= cmap_entries || 28863965825b97a5809454f5810f7e603cbd02daa036scroggo background_index != PNG_CMAP_TRANS_BACKGROUND) 28873965825b97a5809454f5810f7e603cbd02daa036scroggo goto bad_background; 28883965825b97a5809454f5810f7e603cbd02daa036scroggo break; 28893965825b97a5809454f5810f7e603cbd02daa036scroggo 28903965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_RGB: 28913965825b97a5809454f5810f7e603cbd02daa036scroggo if (background_index != PNG_CMAP_RGB_BACKGROUND) 28923965825b97a5809454f5810f7e603cbd02daa036scroggo goto bad_background; 28933965825b97a5809454f5810f7e603cbd02daa036scroggo break; 28943965825b97a5809454f5810f7e603cbd02daa036scroggo 28953965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_RGB_ALPHA: 28963965825b97a5809454f5810f7e603cbd02daa036scroggo if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND) 28973965825b97a5809454f5810f7e603cbd02daa036scroggo goto bad_background; 28983965825b97a5809454f5810f7e603cbd02daa036scroggo break; 28993965825b97a5809454f5810f7e603cbd02daa036scroggo 29003965825b97a5809454f5810f7e603cbd02daa036scroggo default: 29013965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "bad processing option (internal error)"); 29023965825b97a5809454f5810f7e603cbd02daa036scroggo 29033965825b97a5809454f5810f7e603cbd02daa036scroggo bad_background: 29043965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "bad background index (internal error)"); 29053965825b97a5809454f5810f7e603cbd02daa036scroggo } 29063965825b97a5809454f5810f7e603cbd02daa036scroggo 29073965825b97a5809454f5810f7e603cbd02daa036scroggo display->colormap_processing = output_processing; 29083965825b97a5809454f5810f7e603cbd02daa036scroggo 29093965825b97a5809454f5810f7e603cbd02daa036scroggo return 1/*ok*/; 29103965825b97a5809454f5810f7e603cbd02daa036scroggo} 29113965825b97a5809454f5810f7e603cbd02daa036scroggo 29123965825b97a5809454f5810f7e603cbd02daa036scroggo/* The final part of the color-map read called from png_image_finish_read. */ 29133965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 29143965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_read_and_map(png_voidp argument) 29153965825b97a5809454f5810f7e603cbd02daa036scroggo{ 29163965825b97a5809454f5810f7e603cbd02daa036scroggo png_image_read_control *display = png_voidcast(png_image_read_control*, 29173965825b97a5809454f5810f7e603cbd02daa036scroggo argument); 29183965825b97a5809454f5810f7e603cbd02daa036scroggo png_imagep image = display->image; 29193965825b97a5809454f5810f7e603cbd02daa036scroggo png_structrp png_ptr = image->opaque->png_ptr; 29203965825b97a5809454f5810f7e603cbd02daa036scroggo int passes; 29213965825b97a5809454f5810f7e603cbd02daa036scroggo 29223965825b97a5809454f5810f7e603cbd02daa036scroggo /* Called when the libpng data must be transformed into the color-mapped 29233965825b97a5809454f5810f7e603cbd02daa036scroggo * form. There is a local row buffer in display->local and this routine must 29243965825b97a5809454f5810f7e603cbd02daa036scroggo * do the interlace handling. 29253965825b97a5809454f5810f7e603cbd02daa036scroggo */ 29263965825b97a5809454f5810f7e603cbd02daa036scroggo switch (png_ptr->interlaced) 29273965825b97a5809454f5810f7e603cbd02daa036scroggo { 29283965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_INTERLACE_NONE: 29293965825b97a5809454f5810f7e603cbd02daa036scroggo passes = 1; 29303965825b97a5809454f5810f7e603cbd02daa036scroggo break; 29313965825b97a5809454f5810f7e603cbd02daa036scroggo 29323965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_INTERLACE_ADAM7: 29333965825b97a5809454f5810f7e603cbd02daa036scroggo passes = PNG_INTERLACE_ADAM7_PASSES; 29343965825b97a5809454f5810f7e603cbd02daa036scroggo break; 29353965825b97a5809454f5810f7e603cbd02daa036scroggo 29363965825b97a5809454f5810f7e603cbd02daa036scroggo default: 29373965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "unknown interlace type"); 29383965825b97a5809454f5810f7e603cbd02daa036scroggo } 29393965825b97a5809454f5810f7e603cbd02daa036scroggo 29403965825b97a5809454f5810f7e603cbd02daa036scroggo { 29413965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 height = image->height; 29423965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 width = image->width; 29433965825b97a5809454f5810f7e603cbd02daa036scroggo int proc = display->colormap_processing; 29443965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep first_row = png_voidcast(png_bytep, display->first_row); 29453965825b97a5809454f5810f7e603cbd02daa036scroggo ptrdiff_t step_row = display->row_bytes; 29463965825b97a5809454f5810f7e603cbd02daa036scroggo int pass; 29473965825b97a5809454f5810f7e603cbd02daa036scroggo 29483965825b97a5809454f5810f7e603cbd02daa036scroggo for (pass = 0; pass < passes; ++pass) 29493965825b97a5809454f5810f7e603cbd02daa036scroggo { 29503965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int startx, stepx, stepy; 29513965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 y; 29523965825b97a5809454f5810f7e603cbd02daa036scroggo 29533965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) 29543965825b97a5809454f5810f7e603cbd02daa036scroggo { 29553965825b97a5809454f5810f7e603cbd02daa036scroggo /* The row may be empty for a short image: */ 29563965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_PASS_COLS(width, pass) == 0) 29573965825b97a5809454f5810f7e603cbd02daa036scroggo continue; 29583965825b97a5809454f5810f7e603cbd02daa036scroggo 29593965825b97a5809454f5810f7e603cbd02daa036scroggo startx = PNG_PASS_START_COL(pass); 29603965825b97a5809454f5810f7e603cbd02daa036scroggo stepx = PNG_PASS_COL_OFFSET(pass); 29613965825b97a5809454f5810f7e603cbd02daa036scroggo y = PNG_PASS_START_ROW(pass); 29623965825b97a5809454f5810f7e603cbd02daa036scroggo stepy = PNG_PASS_ROW_OFFSET(pass); 29633965825b97a5809454f5810f7e603cbd02daa036scroggo } 29643965825b97a5809454f5810f7e603cbd02daa036scroggo 29653965825b97a5809454f5810f7e603cbd02daa036scroggo else 29663965825b97a5809454f5810f7e603cbd02daa036scroggo { 29673965825b97a5809454f5810f7e603cbd02daa036scroggo y = 0; 29683965825b97a5809454f5810f7e603cbd02daa036scroggo startx = 0; 29693965825b97a5809454f5810f7e603cbd02daa036scroggo stepx = stepy = 1; 29703965825b97a5809454f5810f7e603cbd02daa036scroggo } 29713965825b97a5809454f5810f7e603cbd02daa036scroggo 29723965825b97a5809454f5810f7e603cbd02daa036scroggo for (; y<height; y += stepy) 29733965825b97a5809454f5810f7e603cbd02daa036scroggo { 29743965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep inrow = png_voidcast(png_bytep, display->local_row); 29753965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep outrow = first_row + y * step_row; 29763965825b97a5809454f5810f7e603cbd02daa036scroggo png_const_bytep end_row = outrow + width; 29773965825b97a5809454f5810f7e603cbd02daa036scroggo 29783965825b97a5809454f5810f7e603cbd02daa036scroggo /* Read read the libpng data into the temporary buffer. */ 29793965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_row(png_ptr, inrow, NULL); 29803965825b97a5809454f5810f7e603cbd02daa036scroggo 29813965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now process the row according to the processing option, note 29823965825b97a5809454f5810f7e603cbd02daa036scroggo * that the caller verifies that the format of the libpng output 29833965825b97a5809454f5810f7e603cbd02daa036scroggo * data is as required. 29843965825b97a5809454f5810f7e603cbd02daa036scroggo */ 29853965825b97a5809454f5810f7e603cbd02daa036scroggo outrow += startx; 29863965825b97a5809454f5810f7e603cbd02daa036scroggo switch (proc) 29873965825b97a5809454f5810f7e603cbd02daa036scroggo { 29883965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_GA: 29893965825b97a5809454f5810f7e603cbd02daa036scroggo for (; outrow < end_row; outrow += stepx) 29903965825b97a5809454f5810f7e603cbd02daa036scroggo { 29913965825b97a5809454f5810f7e603cbd02daa036scroggo /* The data is always in the PNG order */ 29923965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int gray = *inrow++; 29933965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int alpha = *inrow++; 29943965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int entry; 29953965825b97a5809454f5810f7e603cbd02daa036scroggo 29963965825b97a5809454f5810f7e603cbd02daa036scroggo /* NOTE: this code is copied as a comment in 29973965825b97a5809454f5810f7e603cbd02daa036scroggo * make_ga_colormap above. Please update the 29983965825b97a5809454f5810f7e603cbd02daa036scroggo * comment if you change this code! 29993965825b97a5809454f5810f7e603cbd02daa036scroggo */ 30003965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha > 229) /* opaque */ 30013965825b97a5809454f5810f7e603cbd02daa036scroggo { 30023965825b97a5809454f5810f7e603cbd02daa036scroggo entry = (231 * gray + 128) >> 8; 30033965825b97a5809454f5810f7e603cbd02daa036scroggo } 30043965825b97a5809454f5810f7e603cbd02daa036scroggo else if (alpha < 26) /* transparent */ 30053965825b97a5809454f5810f7e603cbd02daa036scroggo { 30063965825b97a5809454f5810f7e603cbd02daa036scroggo entry = 231; 30073965825b97a5809454f5810f7e603cbd02daa036scroggo } 30083965825b97a5809454f5810f7e603cbd02daa036scroggo else /* partially opaque */ 30093965825b97a5809454f5810f7e603cbd02daa036scroggo { 30103965825b97a5809454f5810f7e603cbd02daa036scroggo entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray); 30113965825b97a5809454f5810f7e603cbd02daa036scroggo } 30123965825b97a5809454f5810f7e603cbd02daa036scroggo 30133965825b97a5809454f5810f7e603cbd02daa036scroggo *outrow = (png_byte)entry; 30143965825b97a5809454f5810f7e603cbd02daa036scroggo } 30153965825b97a5809454f5810f7e603cbd02daa036scroggo break; 30163965825b97a5809454f5810f7e603cbd02daa036scroggo 30173965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_TRANS: 30183965825b97a5809454f5810f7e603cbd02daa036scroggo for (; outrow < end_row; outrow += stepx) 30193965825b97a5809454f5810f7e603cbd02daa036scroggo { 30203965825b97a5809454f5810f7e603cbd02daa036scroggo png_byte gray = *inrow++; 30213965825b97a5809454f5810f7e603cbd02daa036scroggo png_byte alpha = *inrow++; 30223965825b97a5809454f5810f7e603cbd02daa036scroggo 30233965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha == 0) 30243965825b97a5809454f5810f7e603cbd02daa036scroggo *outrow = PNG_CMAP_TRANS_BACKGROUND; 30253965825b97a5809454f5810f7e603cbd02daa036scroggo 30263965825b97a5809454f5810f7e603cbd02daa036scroggo else if (gray != PNG_CMAP_TRANS_BACKGROUND) 30273965825b97a5809454f5810f7e603cbd02daa036scroggo *outrow = gray; 30283965825b97a5809454f5810f7e603cbd02daa036scroggo 30293965825b97a5809454f5810f7e603cbd02daa036scroggo else 30303965825b97a5809454f5810f7e603cbd02daa036scroggo *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1); 30313965825b97a5809454f5810f7e603cbd02daa036scroggo } 30323965825b97a5809454f5810f7e603cbd02daa036scroggo break; 30333965825b97a5809454f5810f7e603cbd02daa036scroggo 30343965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_RGB: 30353965825b97a5809454f5810f7e603cbd02daa036scroggo for (; outrow < end_row; outrow += stepx) 30363965825b97a5809454f5810f7e603cbd02daa036scroggo { 30373965825b97a5809454f5810f7e603cbd02daa036scroggo *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]); 30383965825b97a5809454f5810f7e603cbd02daa036scroggo inrow += 3; 30393965825b97a5809454f5810f7e603cbd02daa036scroggo } 30403965825b97a5809454f5810f7e603cbd02daa036scroggo break; 30413965825b97a5809454f5810f7e603cbd02daa036scroggo 30423965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_RGB_ALPHA: 30433965825b97a5809454f5810f7e603cbd02daa036scroggo for (; outrow < end_row; outrow += stepx) 30443965825b97a5809454f5810f7e603cbd02daa036scroggo { 30453965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int alpha = inrow[3]; 30463965825b97a5809454f5810f7e603cbd02daa036scroggo 30473965825b97a5809454f5810f7e603cbd02daa036scroggo /* Because the alpha entries only hold alpha==0.5 values 30483965825b97a5809454f5810f7e603cbd02daa036scroggo * split the processing at alpha==0.25 (64) and 0.75 30493965825b97a5809454f5810f7e603cbd02daa036scroggo * (196). 30503965825b97a5809454f5810f7e603cbd02daa036scroggo */ 30513965825b97a5809454f5810f7e603cbd02daa036scroggo 30523965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha >= 196) 30533965825b97a5809454f5810f7e603cbd02daa036scroggo *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], 30543965825b97a5809454f5810f7e603cbd02daa036scroggo inrow[2]); 30553965825b97a5809454f5810f7e603cbd02daa036scroggo 30563965825b97a5809454f5810f7e603cbd02daa036scroggo else if (alpha < 64) 30573965825b97a5809454f5810f7e603cbd02daa036scroggo *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND; 30583965825b97a5809454f5810f7e603cbd02daa036scroggo 30593965825b97a5809454f5810f7e603cbd02daa036scroggo else 30603965825b97a5809454f5810f7e603cbd02daa036scroggo { 30613965825b97a5809454f5810f7e603cbd02daa036scroggo /* Likewise there are three entries for each of r, g 30623965825b97a5809454f5810f7e603cbd02daa036scroggo * and b. We could select the entry by popcount on 30633965825b97a5809454f5810f7e603cbd02daa036scroggo * the top two bits on those architectures that 30643965825b97a5809454f5810f7e603cbd02daa036scroggo * support it, this is what the code below does, 30653965825b97a5809454f5810f7e603cbd02daa036scroggo * crudely. 30663965825b97a5809454f5810f7e603cbd02daa036scroggo */ 30673965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1; 30683965825b97a5809454f5810f7e603cbd02daa036scroggo 30693965825b97a5809454f5810f7e603cbd02daa036scroggo /* Here are how the values map: 30703965825b97a5809454f5810f7e603cbd02daa036scroggo * 30713965825b97a5809454f5810f7e603cbd02daa036scroggo * 0x00 .. 0x3f -> 0 30723965825b97a5809454f5810f7e603cbd02daa036scroggo * 0x40 .. 0xbf -> 1 30733965825b97a5809454f5810f7e603cbd02daa036scroggo * 0xc0 .. 0xff -> 2 30743965825b97a5809454f5810f7e603cbd02daa036scroggo * 30753965825b97a5809454f5810f7e603cbd02daa036scroggo * So, as above with the explicit alpha checks, the 30763965825b97a5809454f5810f7e603cbd02daa036scroggo * breakpoints are at 64 and 196. 30773965825b97a5809454f5810f7e603cbd02daa036scroggo */ 30783965825b97a5809454f5810f7e603cbd02daa036scroggo if (inrow[0] & 0x80) back_i += 9; /* red */ 30793965825b97a5809454f5810f7e603cbd02daa036scroggo if (inrow[0] & 0x40) back_i += 9; 30803965825b97a5809454f5810f7e603cbd02daa036scroggo if (inrow[0] & 0x80) back_i += 3; /* green */ 30813965825b97a5809454f5810f7e603cbd02daa036scroggo if (inrow[0] & 0x40) back_i += 3; 30823965825b97a5809454f5810f7e603cbd02daa036scroggo if (inrow[0] & 0x80) back_i += 1; /* blue */ 30833965825b97a5809454f5810f7e603cbd02daa036scroggo if (inrow[0] & 0x40) back_i += 1; 30843965825b97a5809454f5810f7e603cbd02daa036scroggo 30853965825b97a5809454f5810f7e603cbd02daa036scroggo *outrow = (png_byte)back_i; 30863965825b97a5809454f5810f7e603cbd02daa036scroggo } 30873965825b97a5809454f5810f7e603cbd02daa036scroggo 30883965825b97a5809454f5810f7e603cbd02daa036scroggo inrow += 4; 30893965825b97a5809454f5810f7e603cbd02daa036scroggo } 30903965825b97a5809454f5810f7e603cbd02daa036scroggo break; 30913965825b97a5809454f5810f7e603cbd02daa036scroggo 30923965825b97a5809454f5810f7e603cbd02daa036scroggo default: 30933965825b97a5809454f5810f7e603cbd02daa036scroggo break; 30943965825b97a5809454f5810f7e603cbd02daa036scroggo } 30953965825b97a5809454f5810f7e603cbd02daa036scroggo } 30963965825b97a5809454f5810f7e603cbd02daa036scroggo } 30973965825b97a5809454f5810f7e603cbd02daa036scroggo } 30983965825b97a5809454f5810f7e603cbd02daa036scroggo 30993965825b97a5809454f5810f7e603cbd02daa036scroggo return 1; 31003965825b97a5809454f5810f7e603cbd02daa036scroggo} 31013965825b97a5809454f5810f7e603cbd02daa036scroggo 31023965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 31033965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_read_colormapped(png_voidp argument) 31043965825b97a5809454f5810f7e603cbd02daa036scroggo{ 31053965825b97a5809454f5810f7e603cbd02daa036scroggo png_image_read_control *display = png_voidcast(png_image_read_control*, 31063965825b97a5809454f5810f7e603cbd02daa036scroggo argument); 31073965825b97a5809454f5810f7e603cbd02daa036scroggo png_imagep image = display->image; 31083965825b97a5809454f5810f7e603cbd02daa036scroggo png_controlp control = image->opaque; 31093965825b97a5809454f5810f7e603cbd02daa036scroggo png_structrp png_ptr = control->png_ptr; 31103965825b97a5809454f5810f7e603cbd02daa036scroggo png_inforp info_ptr = control->info_ptr; 31113965825b97a5809454f5810f7e603cbd02daa036scroggo 31123965825b97a5809454f5810f7e603cbd02daa036scroggo int passes = 0; /* As a flag */ 31133965825b97a5809454f5810f7e603cbd02daa036scroggo 31143965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_SKIP_CHUNKS(png_ptr); 31153965825b97a5809454f5810f7e603cbd02daa036scroggo 31163965825b97a5809454f5810f7e603cbd02daa036scroggo /* Update the 'info' structure and make sure the result is as required; first 31173965825b97a5809454f5810f7e603cbd02daa036scroggo * make sure to turn on the interlace handling if it will be required 31183965825b97a5809454f5810f7e603cbd02daa036scroggo * (because it can't be turned on *after* the call to png_read_update_info!) 31193965825b97a5809454f5810f7e603cbd02daa036scroggo */ 31203965825b97a5809454f5810f7e603cbd02daa036scroggo if (display->colormap_processing == PNG_CMAP_NONE) 31213965825b97a5809454f5810f7e603cbd02daa036scroggo passes = png_set_interlace_handling(png_ptr); 31223965825b97a5809454f5810f7e603cbd02daa036scroggo 31233965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_update_info(png_ptr, info_ptr); 31243965825b97a5809454f5810f7e603cbd02daa036scroggo 31253965825b97a5809454f5810f7e603cbd02daa036scroggo /* The expected output can be deduced from the colormap_processing option. */ 31263965825b97a5809454f5810f7e603cbd02daa036scroggo switch (display->colormap_processing) 31273965825b97a5809454f5810f7e603cbd02daa036scroggo { 31283965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_NONE: 31293965825b97a5809454f5810f7e603cbd02daa036scroggo /* Output must be one channel and one byte per pixel, the output 31303965825b97a5809454f5810f7e603cbd02daa036scroggo * encoding can be anything. 31313965825b97a5809454f5810f7e603cbd02daa036scroggo */ 31323965825b97a5809454f5810f7e603cbd02daa036scroggo if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE || 31333965825b97a5809454f5810f7e603cbd02daa036scroggo info_ptr->color_type == PNG_COLOR_TYPE_GRAY) && 31343965825b97a5809454f5810f7e603cbd02daa036scroggo info_ptr->bit_depth == 8) 31353965825b97a5809454f5810f7e603cbd02daa036scroggo break; 31363965825b97a5809454f5810f7e603cbd02daa036scroggo 31373965825b97a5809454f5810f7e603cbd02daa036scroggo goto bad_output; 31383965825b97a5809454f5810f7e603cbd02daa036scroggo 31393965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_TRANS: 31403965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_GA: 31413965825b97a5809454f5810f7e603cbd02daa036scroggo /* Output must be two channels and the 'G' one must be sRGB, the latter 31423965825b97a5809454f5810f7e603cbd02daa036scroggo * can be checked with an exact number because it should have been set 31433965825b97a5809454f5810f7e603cbd02daa036scroggo * to this number above! 31443965825b97a5809454f5810f7e603cbd02daa036scroggo */ 31453965825b97a5809454f5810f7e603cbd02daa036scroggo if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && 31463965825b97a5809454f5810f7e603cbd02daa036scroggo info_ptr->bit_depth == 8 && 31473965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->screen_gamma == PNG_GAMMA_sRGB && 31483965825b97a5809454f5810f7e603cbd02daa036scroggo image->colormap_entries == 256) 31493965825b97a5809454f5810f7e603cbd02daa036scroggo break; 31503965825b97a5809454f5810f7e603cbd02daa036scroggo 31513965825b97a5809454f5810f7e603cbd02daa036scroggo goto bad_output; 31523965825b97a5809454f5810f7e603cbd02daa036scroggo 31533965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_RGB: 31543965825b97a5809454f5810f7e603cbd02daa036scroggo /* Output must be 8-bit sRGB encoded RGB */ 31553965825b97a5809454f5810f7e603cbd02daa036scroggo if (info_ptr->color_type == PNG_COLOR_TYPE_RGB && 31563965825b97a5809454f5810f7e603cbd02daa036scroggo info_ptr->bit_depth == 8 && 31573965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->screen_gamma == PNG_GAMMA_sRGB && 31583965825b97a5809454f5810f7e603cbd02daa036scroggo image->colormap_entries == 216) 31593965825b97a5809454f5810f7e603cbd02daa036scroggo break; 31603965825b97a5809454f5810f7e603cbd02daa036scroggo 31613965825b97a5809454f5810f7e603cbd02daa036scroggo goto bad_output; 31623965825b97a5809454f5810f7e603cbd02daa036scroggo 31633965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_CMAP_RGB_ALPHA: 31643965825b97a5809454f5810f7e603cbd02daa036scroggo /* Output must be 8-bit sRGB encoded RGBA */ 31653965825b97a5809454f5810f7e603cbd02daa036scroggo if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA && 31663965825b97a5809454f5810f7e603cbd02daa036scroggo info_ptr->bit_depth == 8 && 31673965825b97a5809454f5810f7e603cbd02daa036scroggo png_ptr->screen_gamma == PNG_GAMMA_sRGB && 31683965825b97a5809454f5810f7e603cbd02daa036scroggo image->colormap_entries == 244 /* 216 + 1 + 27 */) 31693965825b97a5809454f5810f7e603cbd02daa036scroggo break; 31703965825b97a5809454f5810f7e603cbd02daa036scroggo 31713965825b97a5809454f5810f7e603cbd02daa036scroggo /* goto bad_output; */ 31723965825b97a5809454f5810f7e603cbd02daa036scroggo /* FALL THROUGH */ 31733965825b97a5809454f5810f7e603cbd02daa036scroggo 31743965825b97a5809454f5810f7e603cbd02daa036scroggo default: 31753965825b97a5809454f5810f7e603cbd02daa036scroggo bad_output: 31763965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "bad color-map processing (internal error)"); 31773965825b97a5809454f5810f7e603cbd02daa036scroggo } 31783965825b97a5809454f5810f7e603cbd02daa036scroggo 31793965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now read the rows. Do this here if it is possible to read directly into 31803965825b97a5809454f5810f7e603cbd02daa036scroggo * the output buffer, otherwise allocate a local row buffer of the maximum 31813965825b97a5809454f5810f7e603cbd02daa036scroggo * size libpng requires and call the relevant processing routine safely. 31823965825b97a5809454f5810f7e603cbd02daa036scroggo */ 31833965825b97a5809454f5810f7e603cbd02daa036scroggo { 31843965825b97a5809454f5810f7e603cbd02daa036scroggo png_voidp first_row = display->buffer; 31853965825b97a5809454f5810f7e603cbd02daa036scroggo ptrdiff_t row_bytes = display->row_stride; 31863965825b97a5809454f5810f7e603cbd02daa036scroggo 31873965825b97a5809454f5810f7e603cbd02daa036scroggo /* The following expression is designed to work correctly whether it gives 31883965825b97a5809454f5810f7e603cbd02daa036scroggo * a signed or an unsigned result. 31893965825b97a5809454f5810f7e603cbd02daa036scroggo */ 31903965825b97a5809454f5810f7e603cbd02daa036scroggo if (row_bytes < 0) 31913965825b97a5809454f5810f7e603cbd02daa036scroggo { 31923965825b97a5809454f5810f7e603cbd02daa036scroggo char *ptr = png_voidcast(char*, first_row); 31933965825b97a5809454f5810f7e603cbd02daa036scroggo ptr += (image->height-1) * (-row_bytes); 31943965825b97a5809454f5810f7e603cbd02daa036scroggo first_row = png_voidcast(png_voidp, ptr); 31953965825b97a5809454f5810f7e603cbd02daa036scroggo } 31963965825b97a5809454f5810f7e603cbd02daa036scroggo 31973965825b97a5809454f5810f7e603cbd02daa036scroggo display->first_row = first_row; 31983965825b97a5809454f5810f7e603cbd02daa036scroggo display->row_bytes = row_bytes; 31993965825b97a5809454f5810f7e603cbd02daa036scroggo } 32003965825b97a5809454f5810f7e603cbd02daa036scroggo 32013965825b97a5809454f5810f7e603cbd02daa036scroggo if (passes == 0) 32023965825b97a5809454f5810f7e603cbd02daa036scroggo { 32033965825b97a5809454f5810f7e603cbd02daa036scroggo int result; 32043965825b97a5809454f5810f7e603cbd02daa036scroggo png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); 32053965825b97a5809454f5810f7e603cbd02daa036scroggo 32063965825b97a5809454f5810f7e603cbd02daa036scroggo display->local_row = row; 32073965825b97a5809454f5810f7e603cbd02daa036scroggo result = png_safe_execute(image, png_image_read_and_map, display); 32083965825b97a5809454f5810f7e603cbd02daa036scroggo display->local_row = NULL; 32093965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, row); 32103965825b97a5809454f5810f7e603cbd02daa036scroggo 32113965825b97a5809454f5810f7e603cbd02daa036scroggo return result; 32123965825b97a5809454f5810f7e603cbd02daa036scroggo } 32133965825b97a5809454f5810f7e603cbd02daa036scroggo 32143965825b97a5809454f5810f7e603cbd02daa036scroggo else 32153965825b97a5809454f5810f7e603cbd02daa036scroggo { 32163965825b97a5809454f5810f7e603cbd02daa036scroggo png_alloc_size_t row_bytes = display->row_bytes; 32173965825b97a5809454f5810f7e603cbd02daa036scroggo 32183965825b97a5809454f5810f7e603cbd02daa036scroggo while (--passes >= 0) 32193965825b97a5809454f5810f7e603cbd02daa036scroggo { 32203965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 y = image->height; 32213965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep row = png_voidcast(png_bytep, display->first_row); 32223965825b97a5809454f5810f7e603cbd02daa036scroggo 32233965825b97a5809454f5810f7e603cbd02daa036scroggo while (y-- > 0) 32243965825b97a5809454f5810f7e603cbd02daa036scroggo { 32253965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_row(png_ptr, row, NULL); 32263965825b97a5809454f5810f7e603cbd02daa036scroggo row += row_bytes; 32273965825b97a5809454f5810f7e603cbd02daa036scroggo } 32283965825b97a5809454f5810f7e603cbd02daa036scroggo } 32293965825b97a5809454f5810f7e603cbd02daa036scroggo 32303965825b97a5809454f5810f7e603cbd02daa036scroggo return 1; 32313965825b97a5809454f5810f7e603cbd02daa036scroggo } 32323965825b97a5809454f5810f7e603cbd02daa036scroggo} 32333965825b97a5809454f5810f7e603cbd02daa036scroggo 32343965825b97a5809454f5810f7e603cbd02daa036scroggo/* Just the row reading part of png_image_read. */ 32353965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 32363965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_read_composite(png_voidp argument) 32373965825b97a5809454f5810f7e603cbd02daa036scroggo{ 32383965825b97a5809454f5810f7e603cbd02daa036scroggo png_image_read_control *display = png_voidcast(png_image_read_control*, 32393965825b97a5809454f5810f7e603cbd02daa036scroggo argument); 32403965825b97a5809454f5810f7e603cbd02daa036scroggo png_imagep image = display->image; 32413965825b97a5809454f5810f7e603cbd02daa036scroggo png_structrp png_ptr = image->opaque->png_ptr; 32423965825b97a5809454f5810f7e603cbd02daa036scroggo int passes; 32433965825b97a5809454f5810f7e603cbd02daa036scroggo 32443965825b97a5809454f5810f7e603cbd02daa036scroggo switch (png_ptr->interlaced) 32453965825b97a5809454f5810f7e603cbd02daa036scroggo { 32463965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_INTERLACE_NONE: 32473965825b97a5809454f5810f7e603cbd02daa036scroggo passes = 1; 32483965825b97a5809454f5810f7e603cbd02daa036scroggo break; 32493965825b97a5809454f5810f7e603cbd02daa036scroggo 32503965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_INTERLACE_ADAM7: 32513965825b97a5809454f5810f7e603cbd02daa036scroggo passes = PNG_INTERLACE_ADAM7_PASSES; 32523965825b97a5809454f5810f7e603cbd02daa036scroggo break; 32533965825b97a5809454f5810f7e603cbd02daa036scroggo 32543965825b97a5809454f5810f7e603cbd02daa036scroggo default: 32553965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "unknown interlace type"); 32563965825b97a5809454f5810f7e603cbd02daa036scroggo } 32573965825b97a5809454f5810f7e603cbd02daa036scroggo 32583965825b97a5809454f5810f7e603cbd02daa036scroggo { 32593965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 height = image->height; 32603965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 width = image->width; 32613965825b97a5809454f5810f7e603cbd02daa036scroggo ptrdiff_t step_row = display->row_bytes; 32623965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int channels = 32633965825b97a5809454f5810f7e603cbd02daa036scroggo (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; 32643965825b97a5809454f5810f7e603cbd02daa036scroggo int pass; 32653965825b97a5809454f5810f7e603cbd02daa036scroggo 32663965825b97a5809454f5810f7e603cbd02daa036scroggo for (pass = 0; pass < passes; ++pass) 32673965825b97a5809454f5810f7e603cbd02daa036scroggo { 32683965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int startx, stepx, stepy; 32693965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 y; 32703965825b97a5809454f5810f7e603cbd02daa036scroggo 32713965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) 32723965825b97a5809454f5810f7e603cbd02daa036scroggo { 32733965825b97a5809454f5810f7e603cbd02daa036scroggo /* The row may be empty for a short image: */ 32743965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_PASS_COLS(width, pass) == 0) 32753965825b97a5809454f5810f7e603cbd02daa036scroggo continue; 32763965825b97a5809454f5810f7e603cbd02daa036scroggo 32773965825b97a5809454f5810f7e603cbd02daa036scroggo startx = PNG_PASS_START_COL(pass) * channels; 32783965825b97a5809454f5810f7e603cbd02daa036scroggo stepx = PNG_PASS_COL_OFFSET(pass) * channels; 32793965825b97a5809454f5810f7e603cbd02daa036scroggo y = PNG_PASS_START_ROW(pass); 32803965825b97a5809454f5810f7e603cbd02daa036scroggo stepy = PNG_PASS_ROW_OFFSET(pass); 32813965825b97a5809454f5810f7e603cbd02daa036scroggo } 32823965825b97a5809454f5810f7e603cbd02daa036scroggo 32833965825b97a5809454f5810f7e603cbd02daa036scroggo else 32843965825b97a5809454f5810f7e603cbd02daa036scroggo { 32853965825b97a5809454f5810f7e603cbd02daa036scroggo y = 0; 32863965825b97a5809454f5810f7e603cbd02daa036scroggo startx = 0; 32873965825b97a5809454f5810f7e603cbd02daa036scroggo stepx = channels; 32883965825b97a5809454f5810f7e603cbd02daa036scroggo stepy = 1; 32893965825b97a5809454f5810f7e603cbd02daa036scroggo } 32903965825b97a5809454f5810f7e603cbd02daa036scroggo 32913965825b97a5809454f5810f7e603cbd02daa036scroggo for (; y<height; y += stepy) 32923965825b97a5809454f5810f7e603cbd02daa036scroggo { 32933965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep inrow = png_voidcast(png_bytep, display->local_row); 32943965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep outrow; 32953965825b97a5809454f5810f7e603cbd02daa036scroggo png_const_bytep end_row; 32963965825b97a5809454f5810f7e603cbd02daa036scroggo 32973965825b97a5809454f5810f7e603cbd02daa036scroggo /* Read the row, which is packed: */ 32983965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_row(png_ptr, inrow, NULL); 32993965825b97a5809454f5810f7e603cbd02daa036scroggo 33003965825b97a5809454f5810f7e603cbd02daa036scroggo outrow = png_voidcast(png_bytep, display->first_row); 33013965825b97a5809454f5810f7e603cbd02daa036scroggo outrow += y * step_row; 33023965825b97a5809454f5810f7e603cbd02daa036scroggo end_row = outrow + width * channels; 33033965825b97a5809454f5810f7e603cbd02daa036scroggo 33043965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now do the composition on each pixel in this row. */ 33053965825b97a5809454f5810f7e603cbd02daa036scroggo outrow += startx; 33063965825b97a5809454f5810f7e603cbd02daa036scroggo for (; outrow < end_row; outrow += stepx) 33073965825b97a5809454f5810f7e603cbd02daa036scroggo { 33083965825b97a5809454f5810f7e603cbd02daa036scroggo png_byte alpha = inrow[channels]; 33093965825b97a5809454f5810f7e603cbd02daa036scroggo 33103965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha > 0) /* else no change to the output */ 33113965825b97a5809454f5810f7e603cbd02daa036scroggo { 33123965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int c; 33133965825b97a5809454f5810f7e603cbd02daa036scroggo 33143965825b97a5809454f5810f7e603cbd02daa036scroggo for (c=0; c<channels; ++c) 33153965825b97a5809454f5810f7e603cbd02daa036scroggo { 33163965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 component = inrow[c]; 33173965825b97a5809454f5810f7e603cbd02daa036scroggo 33183965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha < 255) /* else just use component */ 33193965825b97a5809454f5810f7e603cbd02daa036scroggo { 33203965825b97a5809454f5810f7e603cbd02daa036scroggo /* This is PNG_OPTIMIZED_ALPHA, the component value 33213965825b97a5809454f5810f7e603cbd02daa036scroggo * is a linear 8-bit value. Combine this with the 33223965825b97a5809454f5810f7e603cbd02daa036scroggo * current outrow[c] value which is sRGB encoded. 33233965825b97a5809454f5810f7e603cbd02daa036scroggo * Arithmetic here is 16-bits to preserve the output 33243965825b97a5809454f5810f7e603cbd02daa036scroggo * values correctly. 33253965825b97a5809454f5810f7e603cbd02daa036scroggo */ 33263965825b97a5809454f5810f7e603cbd02daa036scroggo component *= 257*255; /* =65535 */ 33273965825b97a5809454f5810f7e603cbd02daa036scroggo component += (255-alpha)*png_sRGB_table[outrow[c]]; 33283965825b97a5809454f5810f7e603cbd02daa036scroggo 33293965825b97a5809454f5810f7e603cbd02daa036scroggo /* So 'component' is scaled by 255*65535 and is 33303965825b97a5809454f5810f7e603cbd02daa036scroggo * therefore appropriate for the sRGB to linear 33313965825b97a5809454f5810f7e603cbd02daa036scroggo * conversion table. 33323965825b97a5809454f5810f7e603cbd02daa036scroggo */ 33333965825b97a5809454f5810f7e603cbd02daa036scroggo component = PNG_sRGB_FROM_LINEAR(component); 33343965825b97a5809454f5810f7e603cbd02daa036scroggo } 33353965825b97a5809454f5810f7e603cbd02daa036scroggo 33363965825b97a5809454f5810f7e603cbd02daa036scroggo outrow[c] = (png_byte)component; 33373965825b97a5809454f5810f7e603cbd02daa036scroggo } 33383965825b97a5809454f5810f7e603cbd02daa036scroggo } 33393965825b97a5809454f5810f7e603cbd02daa036scroggo 33403965825b97a5809454f5810f7e603cbd02daa036scroggo inrow += channels+1; /* components and alpha channel */ 33413965825b97a5809454f5810f7e603cbd02daa036scroggo } 33423965825b97a5809454f5810f7e603cbd02daa036scroggo } 33433965825b97a5809454f5810f7e603cbd02daa036scroggo } 33443965825b97a5809454f5810f7e603cbd02daa036scroggo } 33453965825b97a5809454f5810f7e603cbd02daa036scroggo 33463965825b97a5809454f5810f7e603cbd02daa036scroggo return 1; 33473965825b97a5809454f5810f7e603cbd02daa036scroggo} 33483965825b97a5809454f5810f7e603cbd02daa036scroggo 33493965825b97a5809454f5810f7e603cbd02daa036scroggo/* The do_local_background case; called when all the following transforms are to 33503965825b97a5809454f5810f7e603cbd02daa036scroggo * be done: 33513965825b97a5809454f5810f7e603cbd02daa036scroggo * 33523965825b97a5809454f5810f7e603cbd02daa036scroggo * PNG_RGB_TO_GRAY 33533965825b97a5809454f5810f7e603cbd02daa036scroggo * PNG_COMPOSITE 33543965825b97a5809454f5810f7e603cbd02daa036scroggo * PNG_GAMMA 33553965825b97a5809454f5810f7e603cbd02daa036scroggo * 33563965825b97a5809454f5810f7e603cbd02daa036scroggo * This is a work-around for the fact that both the PNG_RGB_TO_GRAY and 33573965825b97a5809454f5810f7e603cbd02daa036scroggo * PNG_COMPOSITE code performs gamma correction, so we get double gamma 33583965825b97a5809454f5810f7e603cbd02daa036scroggo * correction. The fix-up is to prevent the PNG_COMPOSITE operation from 33593965825b97a5809454f5810f7e603cbd02daa036scroggo * happening inside libpng, so this routine sees an 8 or 16-bit gray+alpha 33603965825b97a5809454f5810f7e603cbd02daa036scroggo * row and handles the removal or pre-multiplication of the alpha channel. 33613965825b97a5809454f5810f7e603cbd02daa036scroggo */ 33623965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 33633965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_read_background(png_voidp argument) 33643965825b97a5809454f5810f7e603cbd02daa036scroggo{ 33653965825b97a5809454f5810f7e603cbd02daa036scroggo png_image_read_control *display = png_voidcast(png_image_read_control*, 33663965825b97a5809454f5810f7e603cbd02daa036scroggo argument); 33673965825b97a5809454f5810f7e603cbd02daa036scroggo png_imagep image = display->image; 33683965825b97a5809454f5810f7e603cbd02daa036scroggo png_structrp png_ptr = image->opaque->png_ptr; 33693965825b97a5809454f5810f7e603cbd02daa036scroggo png_inforp info_ptr = image->opaque->info_ptr; 33703965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 height = image->height; 33713965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 width = image->width; 33723965825b97a5809454f5810f7e603cbd02daa036scroggo int pass, passes; 33733965825b97a5809454f5810f7e603cbd02daa036scroggo 33743965825b97a5809454f5810f7e603cbd02daa036scroggo /* Double check the convoluted logic below. We expect to get here with 33753965825b97a5809454f5810f7e603cbd02daa036scroggo * libpng doing rgb to gray and gamma correction but background processing 33763965825b97a5809454f5810f7e603cbd02daa036scroggo * left to the png_image_read_background function. The rows libpng produce 33773965825b97a5809454f5810f7e603cbd02daa036scroggo * might be 8 or 16-bit but should always have two channels; gray plus alpha. 33783965825b97a5809454f5810f7e603cbd02daa036scroggo */ 33793965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) 33803965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "lost rgb to gray"); 33813965825b97a5809454f5810f7e603cbd02daa036scroggo 33823965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->transformations & PNG_COMPOSE) != 0) 33833965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "unexpected compose"); 33843965825b97a5809454f5810f7e603cbd02daa036scroggo 33853965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_get_channels(png_ptr, info_ptr) != 2) 33863965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "lost/gained channels"); 33873965825b97a5809454f5810f7e603cbd02daa036scroggo 33883965825b97a5809454f5810f7e603cbd02daa036scroggo /* Expect the 8-bit case to always remove the alpha channel */ 33893965825b97a5809454f5810f7e603cbd02daa036scroggo if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 && 33903965825b97a5809454f5810f7e603cbd02daa036scroggo (image->format & PNG_FORMAT_FLAG_ALPHA) != 0) 33913965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "unexpected 8-bit transformation"); 33923965825b97a5809454f5810f7e603cbd02daa036scroggo 33933965825b97a5809454f5810f7e603cbd02daa036scroggo switch (png_ptr->interlaced) 33943965825b97a5809454f5810f7e603cbd02daa036scroggo { 33953965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_INTERLACE_NONE: 33963965825b97a5809454f5810f7e603cbd02daa036scroggo passes = 1; 33973965825b97a5809454f5810f7e603cbd02daa036scroggo break; 33983965825b97a5809454f5810f7e603cbd02daa036scroggo 33993965825b97a5809454f5810f7e603cbd02daa036scroggo case PNG_INTERLACE_ADAM7: 34003965825b97a5809454f5810f7e603cbd02daa036scroggo passes = PNG_INTERLACE_ADAM7_PASSES; 34013965825b97a5809454f5810f7e603cbd02daa036scroggo break; 34023965825b97a5809454f5810f7e603cbd02daa036scroggo 34033965825b97a5809454f5810f7e603cbd02daa036scroggo default: 34043965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "unknown interlace type"); 34053965825b97a5809454f5810f7e603cbd02daa036scroggo } 34063965825b97a5809454f5810f7e603cbd02daa036scroggo 34073965825b97a5809454f5810f7e603cbd02daa036scroggo /* Use direct access to info_ptr here because otherwise the simplified API 34083965825b97a5809454f5810f7e603cbd02daa036scroggo * would require PNG_EASY_ACCESS_SUPPORTED (just for this.) Note this is 34093965825b97a5809454f5810f7e603cbd02daa036scroggo * checking the value after libpng expansions, not the original value in the 34103965825b97a5809454f5810f7e603cbd02daa036scroggo * PNG. 34113965825b97a5809454f5810f7e603cbd02daa036scroggo */ 34123965825b97a5809454f5810f7e603cbd02daa036scroggo switch (info_ptr->bit_depth) 34133965825b97a5809454f5810f7e603cbd02daa036scroggo { 34143965825b97a5809454f5810f7e603cbd02daa036scroggo case 8: 34153965825b97a5809454f5810f7e603cbd02daa036scroggo /* 8-bit sRGB gray values with an alpha channel; the alpha channel is 34163965825b97a5809454f5810f7e603cbd02daa036scroggo * to be removed by composing on a background: either the row if 34173965825b97a5809454f5810f7e603cbd02daa036scroggo * display->background is NULL or display->background->green if not. 34183965825b97a5809454f5810f7e603cbd02daa036scroggo * Unlike the code above ALPHA_OPTIMIZED has *not* been done. 34193965825b97a5809454f5810f7e603cbd02daa036scroggo */ 34203965825b97a5809454f5810f7e603cbd02daa036scroggo { 34213965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep first_row = png_voidcast(png_bytep, display->first_row); 34223965825b97a5809454f5810f7e603cbd02daa036scroggo ptrdiff_t step_row = display->row_bytes; 34233965825b97a5809454f5810f7e603cbd02daa036scroggo 34243965825b97a5809454f5810f7e603cbd02daa036scroggo for (pass = 0; pass < passes; ++pass) 34253965825b97a5809454f5810f7e603cbd02daa036scroggo { 34263965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep row = png_voidcast(png_bytep, 34273965825b97a5809454f5810f7e603cbd02daa036scroggo display->first_row); 34283965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int startx, stepx, stepy; 34293965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 y; 34303965825b97a5809454f5810f7e603cbd02daa036scroggo 34313965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) 34323965825b97a5809454f5810f7e603cbd02daa036scroggo { 34333965825b97a5809454f5810f7e603cbd02daa036scroggo /* The row may be empty for a short image: */ 34343965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_PASS_COLS(width, pass) == 0) 34353965825b97a5809454f5810f7e603cbd02daa036scroggo continue; 34363965825b97a5809454f5810f7e603cbd02daa036scroggo 34373965825b97a5809454f5810f7e603cbd02daa036scroggo startx = PNG_PASS_START_COL(pass); 34383965825b97a5809454f5810f7e603cbd02daa036scroggo stepx = PNG_PASS_COL_OFFSET(pass); 34393965825b97a5809454f5810f7e603cbd02daa036scroggo y = PNG_PASS_START_ROW(pass); 34403965825b97a5809454f5810f7e603cbd02daa036scroggo stepy = PNG_PASS_ROW_OFFSET(pass); 34413965825b97a5809454f5810f7e603cbd02daa036scroggo } 34423965825b97a5809454f5810f7e603cbd02daa036scroggo 34433965825b97a5809454f5810f7e603cbd02daa036scroggo else 34443965825b97a5809454f5810f7e603cbd02daa036scroggo { 34453965825b97a5809454f5810f7e603cbd02daa036scroggo y = 0; 34463965825b97a5809454f5810f7e603cbd02daa036scroggo startx = 0; 34473965825b97a5809454f5810f7e603cbd02daa036scroggo stepx = stepy = 1; 34483965825b97a5809454f5810f7e603cbd02daa036scroggo } 34493965825b97a5809454f5810f7e603cbd02daa036scroggo 34503965825b97a5809454f5810f7e603cbd02daa036scroggo if (display->background == NULL) 34513965825b97a5809454f5810f7e603cbd02daa036scroggo { 34523965825b97a5809454f5810f7e603cbd02daa036scroggo for (; y<height; y += stepy) 34533965825b97a5809454f5810f7e603cbd02daa036scroggo { 34543965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep inrow = png_voidcast(png_bytep, 34553965825b97a5809454f5810f7e603cbd02daa036scroggo display->local_row); 34563965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep outrow = first_row + y * step_row; 34573965825b97a5809454f5810f7e603cbd02daa036scroggo png_const_bytep end_row = outrow + width; 34583965825b97a5809454f5810f7e603cbd02daa036scroggo 34593965825b97a5809454f5810f7e603cbd02daa036scroggo /* Read the row, which is packed: */ 34603965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_row(png_ptr, inrow, NULL); 34613965825b97a5809454f5810f7e603cbd02daa036scroggo 34623965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now do the composition on each pixel in this row. */ 34633965825b97a5809454f5810f7e603cbd02daa036scroggo outrow += startx; 34643965825b97a5809454f5810f7e603cbd02daa036scroggo for (; outrow < end_row; outrow += stepx) 34653965825b97a5809454f5810f7e603cbd02daa036scroggo { 34663965825b97a5809454f5810f7e603cbd02daa036scroggo png_byte alpha = inrow[1]; 34673965825b97a5809454f5810f7e603cbd02daa036scroggo 34683965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha > 0) /* else no change to the output */ 34693965825b97a5809454f5810f7e603cbd02daa036scroggo { 34703965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 component = inrow[0]; 34713965825b97a5809454f5810f7e603cbd02daa036scroggo 34723965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha < 255) /* else just use component */ 34733965825b97a5809454f5810f7e603cbd02daa036scroggo { 34743965825b97a5809454f5810f7e603cbd02daa036scroggo /* Since PNG_OPTIMIZED_ALPHA was not set it is 34753965825b97a5809454f5810f7e603cbd02daa036scroggo * necessary to invert the sRGB transfer 34763965825b97a5809454f5810f7e603cbd02daa036scroggo * function and multiply the alpha out. 34773965825b97a5809454f5810f7e603cbd02daa036scroggo */ 34783965825b97a5809454f5810f7e603cbd02daa036scroggo component = png_sRGB_table[component] * alpha; 34793965825b97a5809454f5810f7e603cbd02daa036scroggo component += png_sRGB_table[outrow[0]] * 34803965825b97a5809454f5810f7e603cbd02daa036scroggo (255-alpha); 34813965825b97a5809454f5810f7e603cbd02daa036scroggo component = PNG_sRGB_FROM_LINEAR(component); 34823965825b97a5809454f5810f7e603cbd02daa036scroggo } 34833965825b97a5809454f5810f7e603cbd02daa036scroggo 34843965825b97a5809454f5810f7e603cbd02daa036scroggo outrow[0] = (png_byte)component; 34853965825b97a5809454f5810f7e603cbd02daa036scroggo } 34863965825b97a5809454f5810f7e603cbd02daa036scroggo 34873965825b97a5809454f5810f7e603cbd02daa036scroggo inrow += 2; /* gray and alpha channel */ 34883965825b97a5809454f5810f7e603cbd02daa036scroggo } 34893965825b97a5809454f5810f7e603cbd02daa036scroggo } 34903965825b97a5809454f5810f7e603cbd02daa036scroggo } 34913965825b97a5809454f5810f7e603cbd02daa036scroggo 34923965825b97a5809454f5810f7e603cbd02daa036scroggo else /* constant background value */ 34933965825b97a5809454f5810f7e603cbd02daa036scroggo { 34943965825b97a5809454f5810f7e603cbd02daa036scroggo png_byte background8 = display->background->green; 34953965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_16 background = png_sRGB_table[background8]; 34963965825b97a5809454f5810f7e603cbd02daa036scroggo 34973965825b97a5809454f5810f7e603cbd02daa036scroggo for (; y<height; y += stepy) 34983965825b97a5809454f5810f7e603cbd02daa036scroggo { 34993965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep inrow = png_voidcast(png_bytep, 35003965825b97a5809454f5810f7e603cbd02daa036scroggo display->local_row); 35013965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep outrow = first_row + y * step_row; 35023965825b97a5809454f5810f7e603cbd02daa036scroggo png_const_bytep end_row = outrow + width; 35033965825b97a5809454f5810f7e603cbd02daa036scroggo 35043965825b97a5809454f5810f7e603cbd02daa036scroggo /* Read the row, which is packed: */ 35053965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_row(png_ptr, inrow, NULL); 35063965825b97a5809454f5810f7e603cbd02daa036scroggo 35073965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now do the composition on each pixel in this row. */ 35083965825b97a5809454f5810f7e603cbd02daa036scroggo outrow += startx; 35093965825b97a5809454f5810f7e603cbd02daa036scroggo for (; outrow < end_row; outrow += stepx) 35103965825b97a5809454f5810f7e603cbd02daa036scroggo { 35113965825b97a5809454f5810f7e603cbd02daa036scroggo png_byte alpha = inrow[1]; 35123965825b97a5809454f5810f7e603cbd02daa036scroggo 35133965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha > 0) /* else use background */ 35143965825b97a5809454f5810f7e603cbd02daa036scroggo { 35153965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 component = inrow[0]; 35163965825b97a5809454f5810f7e603cbd02daa036scroggo 35173965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha < 255) /* else just use component */ 35183965825b97a5809454f5810f7e603cbd02daa036scroggo { 35193965825b97a5809454f5810f7e603cbd02daa036scroggo component = png_sRGB_table[component] * alpha; 35203965825b97a5809454f5810f7e603cbd02daa036scroggo component += background * (255-alpha); 35213965825b97a5809454f5810f7e603cbd02daa036scroggo component = PNG_sRGB_FROM_LINEAR(component); 35223965825b97a5809454f5810f7e603cbd02daa036scroggo } 35233965825b97a5809454f5810f7e603cbd02daa036scroggo 35243965825b97a5809454f5810f7e603cbd02daa036scroggo outrow[0] = (png_byte)component; 35253965825b97a5809454f5810f7e603cbd02daa036scroggo } 35263965825b97a5809454f5810f7e603cbd02daa036scroggo 35273965825b97a5809454f5810f7e603cbd02daa036scroggo else 35283965825b97a5809454f5810f7e603cbd02daa036scroggo outrow[0] = background8; 35293965825b97a5809454f5810f7e603cbd02daa036scroggo 35303965825b97a5809454f5810f7e603cbd02daa036scroggo inrow += 2; /* gray and alpha channel */ 35313965825b97a5809454f5810f7e603cbd02daa036scroggo } 35323965825b97a5809454f5810f7e603cbd02daa036scroggo 35333965825b97a5809454f5810f7e603cbd02daa036scroggo row += display->row_bytes; 35343965825b97a5809454f5810f7e603cbd02daa036scroggo } 35353965825b97a5809454f5810f7e603cbd02daa036scroggo } 35363965825b97a5809454f5810f7e603cbd02daa036scroggo } 35373965825b97a5809454f5810f7e603cbd02daa036scroggo } 35383965825b97a5809454f5810f7e603cbd02daa036scroggo break; 35393965825b97a5809454f5810f7e603cbd02daa036scroggo 35403965825b97a5809454f5810f7e603cbd02daa036scroggo case 16: 35413965825b97a5809454f5810f7e603cbd02daa036scroggo /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must 35423965825b97a5809454f5810f7e603cbd02daa036scroggo * still be done and, maybe, the alpha channel removed. This code also 35433965825b97a5809454f5810f7e603cbd02daa036scroggo * handles the alpha-first option. 35443965825b97a5809454f5810f7e603cbd02daa036scroggo */ 35453965825b97a5809454f5810f7e603cbd02daa036scroggo { 35463965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_16p first_row = png_voidcast(png_uint_16p, 35473965825b97a5809454f5810f7e603cbd02daa036scroggo display->first_row); 35483965825b97a5809454f5810f7e603cbd02daa036scroggo /* The division by two is safe because the caller passed in a 35493965825b97a5809454f5810f7e603cbd02daa036scroggo * stride which was multiplied by 2 (below) to get row_bytes. 35503965825b97a5809454f5810f7e603cbd02daa036scroggo */ 35513965825b97a5809454f5810f7e603cbd02daa036scroggo ptrdiff_t step_row = display->row_bytes / 2; 35523965825b97a5809454f5810f7e603cbd02daa036scroggo int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; 35533965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int outchannels = 1+preserve_alpha; 35543965825b97a5809454f5810f7e603cbd02daa036scroggo int swap_alpha = 0; 35553965825b97a5809454f5810f7e603cbd02daa036scroggo 35563965825b97a5809454f5810f7e603cbd02daa036scroggo# ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED 35573965825b97a5809454f5810f7e603cbd02daa036scroggo if (preserve_alpha != 0 && 35583965825b97a5809454f5810f7e603cbd02daa036scroggo (image->format & PNG_FORMAT_FLAG_AFIRST) != 0) 35593965825b97a5809454f5810f7e603cbd02daa036scroggo swap_alpha = 1; 35603965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 35613965825b97a5809454f5810f7e603cbd02daa036scroggo 35623965825b97a5809454f5810f7e603cbd02daa036scroggo for (pass = 0; pass < passes; ++pass) 35633965825b97a5809454f5810f7e603cbd02daa036scroggo { 35643965825b97a5809454f5810f7e603cbd02daa036scroggo unsigned int startx, stepx, stepy; 35653965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 y; 35663965825b97a5809454f5810f7e603cbd02daa036scroggo 35673965825b97a5809454f5810f7e603cbd02daa036scroggo /* The 'x' start and step are adjusted to output components here. 35683965825b97a5809454f5810f7e603cbd02daa036scroggo */ 35693965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) 35703965825b97a5809454f5810f7e603cbd02daa036scroggo { 35713965825b97a5809454f5810f7e603cbd02daa036scroggo /* The row may be empty for a short image: */ 35723965825b97a5809454f5810f7e603cbd02daa036scroggo if (PNG_PASS_COLS(width, pass) == 0) 35733965825b97a5809454f5810f7e603cbd02daa036scroggo continue; 35743965825b97a5809454f5810f7e603cbd02daa036scroggo 35753965825b97a5809454f5810f7e603cbd02daa036scroggo startx = PNG_PASS_START_COL(pass) * outchannels; 35763965825b97a5809454f5810f7e603cbd02daa036scroggo stepx = PNG_PASS_COL_OFFSET(pass) * outchannels; 35773965825b97a5809454f5810f7e603cbd02daa036scroggo y = PNG_PASS_START_ROW(pass); 35783965825b97a5809454f5810f7e603cbd02daa036scroggo stepy = PNG_PASS_ROW_OFFSET(pass); 35793965825b97a5809454f5810f7e603cbd02daa036scroggo } 35803965825b97a5809454f5810f7e603cbd02daa036scroggo 35813965825b97a5809454f5810f7e603cbd02daa036scroggo else 35823965825b97a5809454f5810f7e603cbd02daa036scroggo { 35833965825b97a5809454f5810f7e603cbd02daa036scroggo y = 0; 35843965825b97a5809454f5810f7e603cbd02daa036scroggo startx = 0; 35853965825b97a5809454f5810f7e603cbd02daa036scroggo stepx = outchannels; 35863965825b97a5809454f5810f7e603cbd02daa036scroggo stepy = 1; 35873965825b97a5809454f5810f7e603cbd02daa036scroggo } 35883965825b97a5809454f5810f7e603cbd02daa036scroggo 35893965825b97a5809454f5810f7e603cbd02daa036scroggo for (; y<height; y += stepy) 35903965825b97a5809454f5810f7e603cbd02daa036scroggo { 35913965825b97a5809454f5810f7e603cbd02daa036scroggo png_const_uint_16p inrow; 35923965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_16p outrow = first_row + y*step_row; 35933965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_16p end_row = outrow + width * outchannels; 35943965825b97a5809454f5810f7e603cbd02daa036scroggo 35953965825b97a5809454f5810f7e603cbd02daa036scroggo /* Read the row, which is packed: */ 35963965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_row(png_ptr, png_voidcast(png_bytep, 35973965825b97a5809454f5810f7e603cbd02daa036scroggo display->local_row), NULL); 35983965825b97a5809454f5810f7e603cbd02daa036scroggo inrow = png_voidcast(png_const_uint_16p, display->local_row); 35993965825b97a5809454f5810f7e603cbd02daa036scroggo 36003965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now do the pre-multiplication on each pixel in this row. 36013965825b97a5809454f5810f7e603cbd02daa036scroggo */ 36023965825b97a5809454f5810f7e603cbd02daa036scroggo outrow += startx; 36033965825b97a5809454f5810f7e603cbd02daa036scroggo for (; outrow < end_row; outrow += stepx) 36043965825b97a5809454f5810f7e603cbd02daa036scroggo { 36053965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 component = inrow[0]; 36063965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_16 alpha = inrow[1]; 36073965825b97a5809454f5810f7e603cbd02daa036scroggo 36083965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha > 0) /* else 0 */ 36093965825b97a5809454f5810f7e603cbd02daa036scroggo { 36103965825b97a5809454f5810f7e603cbd02daa036scroggo if (alpha < 65535) /* else just use component */ 36113965825b97a5809454f5810f7e603cbd02daa036scroggo { 36123965825b97a5809454f5810f7e603cbd02daa036scroggo component *= alpha; 36133965825b97a5809454f5810f7e603cbd02daa036scroggo component += 32767; 36143965825b97a5809454f5810f7e603cbd02daa036scroggo component /= 65535; 36153965825b97a5809454f5810f7e603cbd02daa036scroggo } 36163965825b97a5809454f5810f7e603cbd02daa036scroggo } 36173965825b97a5809454f5810f7e603cbd02daa036scroggo 36183965825b97a5809454f5810f7e603cbd02daa036scroggo else 36193965825b97a5809454f5810f7e603cbd02daa036scroggo component = 0; 36203965825b97a5809454f5810f7e603cbd02daa036scroggo 36213965825b97a5809454f5810f7e603cbd02daa036scroggo outrow[swap_alpha] = (png_uint_16)component; 36223965825b97a5809454f5810f7e603cbd02daa036scroggo if (preserve_alpha != 0) 36233965825b97a5809454f5810f7e603cbd02daa036scroggo outrow[1 ^ swap_alpha] = alpha; 36243965825b97a5809454f5810f7e603cbd02daa036scroggo 36253965825b97a5809454f5810f7e603cbd02daa036scroggo inrow += 2; /* components and alpha channel */ 36263965825b97a5809454f5810f7e603cbd02daa036scroggo } 36273965825b97a5809454f5810f7e603cbd02daa036scroggo } 36283965825b97a5809454f5810f7e603cbd02daa036scroggo } 36293965825b97a5809454f5810f7e603cbd02daa036scroggo } 36303965825b97a5809454f5810f7e603cbd02daa036scroggo break; 36313965825b97a5809454f5810f7e603cbd02daa036scroggo 36323965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef __GNUC__ 36333965825b97a5809454f5810f7e603cbd02daa036scroggo default: 36343965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "unexpected bit depth"); 36353965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 36363965825b97a5809454f5810f7e603cbd02daa036scroggo } 36373965825b97a5809454f5810f7e603cbd02daa036scroggo 36383965825b97a5809454f5810f7e603cbd02daa036scroggo return 1; 36393965825b97a5809454f5810f7e603cbd02daa036scroggo} 36403965825b97a5809454f5810f7e603cbd02daa036scroggo 36413965825b97a5809454f5810f7e603cbd02daa036scroggo/* The guts of png_image_finish_read as a png_safe_execute callback. */ 36423965825b97a5809454f5810f7e603cbd02daa036scroggostatic int 36433965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_read_direct(png_voidp argument) 36443965825b97a5809454f5810f7e603cbd02daa036scroggo{ 36453965825b97a5809454f5810f7e603cbd02daa036scroggo png_image_read_control *display = png_voidcast(png_image_read_control*, 36463965825b97a5809454f5810f7e603cbd02daa036scroggo argument); 36473965825b97a5809454f5810f7e603cbd02daa036scroggo png_imagep image = display->image; 36483965825b97a5809454f5810f7e603cbd02daa036scroggo png_structrp png_ptr = image->opaque->png_ptr; 36493965825b97a5809454f5810f7e603cbd02daa036scroggo png_inforp info_ptr = image->opaque->info_ptr; 36503965825b97a5809454f5810f7e603cbd02daa036scroggo 36513965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 format = image->format; 36523965825b97a5809454f5810f7e603cbd02daa036scroggo int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; 36533965825b97a5809454f5810f7e603cbd02daa036scroggo int do_local_compose = 0; 36543965825b97a5809454f5810f7e603cbd02daa036scroggo int do_local_background = 0; /* to avoid double gamma correction bug */ 36553965825b97a5809454f5810f7e603cbd02daa036scroggo int passes = 0; 36563965825b97a5809454f5810f7e603cbd02daa036scroggo 36573965825b97a5809454f5810f7e603cbd02daa036scroggo /* Add transforms to ensure the correct output format is produced then check 36583965825b97a5809454f5810f7e603cbd02daa036scroggo * that the required implementation support is there. Always expand; always 36593965825b97a5809454f5810f7e603cbd02daa036scroggo * need 8 bits minimum, no palette and expanded tRNS. 36603965825b97a5809454f5810f7e603cbd02daa036scroggo */ 36613965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_expand(png_ptr); 36623965825b97a5809454f5810f7e603cbd02daa036scroggo 36633965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now check the format to see if it was modified. */ 36643965825b97a5809454f5810f7e603cbd02daa036scroggo { 36653965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 base_format = png_image_format(png_ptr) & 36663965825b97a5809454f5810f7e603cbd02daa036scroggo ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */; 36673965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 change = format ^ base_format; 36683965825b97a5809454f5810f7e603cbd02daa036scroggo png_fixed_point output_gamma; 36693965825b97a5809454f5810f7e603cbd02daa036scroggo int mode; /* alpha mode */ 36703965825b97a5809454f5810f7e603cbd02daa036scroggo 36713965825b97a5809454f5810f7e603cbd02daa036scroggo /* Do this first so that we have a record if rgb to gray is happening. */ 36723965825b97a5809454f5810f7e603cbd02daa036scroggo if ((change & PNG_FORMAT_FLAG_COLOR) != 0) 36733965825b97a5809454f5810f7e603cbd02daa036scroggo { 36743965825b97a5809454f5810f7e603cbd02daa036scroggo /* gray<->color transformation required. */ 36753965825b97a5809454f5810f7e603cbd02daa036scroggo if ((format & PNG_FORMAT_FLAG_COLOR) != 0) 36763965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_gray_to_rgb(png_ptr); 36773965825b97a5809454f5810f7e603cbd02daa036scroggo 36783965825b97a5809454f5810f7e603cbd02daa036scroggo else 36793965825b97a5809454f5810f7e603cbd02daa036scroggo { 36803965825b97a5809454f5810f7e603cbd02daa036scroggo /* libpng can't do both rgb to gray and 36813965825b97a5809454f5810f7e603cbd02daa036scroggo * background/pre-multiplication if there is also significant gamma 36823965825b97a5809454f5810f7e603cbd02daa036scroggo * correction, because both operations require linear colors and 36833965825b97a5809454f5810f7e603cbd02daa036scroggo * the code only supports one transform doing the gamma correction. 36843965825b97a5809454f5810f7e603cbd02daa036scroggo * Handle this by doing the pre-multiplication or background 36853965825b97a5809454f5810f7e603cbd02daa036scroggo * operation in this code, if necessary. 36863965825b97a5809454f5810f7e603cbd02daa036scroggo * 36873965825b97a5809454f5810f7e603cbd02daa036scroggo * TODO: fix this by rewriting pngrtran.c (!) 36883965825b97a5809454f5810f7e603cbd02daa036scroggo * 36893965825b97a5809454f5810f7e603cbd02daa036scroggo * For the moment (given that fixing this in pngrtran.c is an 36903965825b97a5809454f5810f7e603cbd02daa036scroggo * enormous change) 'do_local_background' is used to indicate that 36913965825b97a5809454f5810f7e603cbd02daa036scroggo * the problem exists. 36923965825b97a5809454f5810f7e603cbd02daa036scroggo */ 36933965825b97a5809454f5810f7e603cbd02daa036scroggo if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0) 36943965825b97a5809454f5810f7e603cbd02daa036scroggo do_local_background = 1/*maybe*/; 36953965825b97a5809454f5810f7e603cbd02daa036scroggo 36963965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, 36973965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); 36983965825b97a5809454f5810f7e603cbd02daa036scroggo } 36993965825b97a5809454f5810f7e603cbd02daa036scroggo 37003965825b97a5809454f5810f7e603cbd02daa036scroggo change &= ~PNG_FORMAT_FLAG_COLOR; 37013965825b97a5809454f5810f7e603cbd02daa036scroggo } 37023965825b97a5809454f5810f7e603cbd02daa036scroggo 37033965825b97a5809454f5810f7e603cbd02daa036scroggo /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise. 37043965825b97a5809454f5810f7e603cbd02daa036scroggo */ 37053965825b97a5809454f5810f7e603cbd02daa036scroggo { 37063965825b97a5809454f5810f7e603cbd02daa036scroggo png_fixed_point input_gamma_default; 37073965825b97a5809454f5810f7e603cbd02daa036scroggo 37083965825b97a5809454f5810f7e603cbd02daa036scroggo if ((base_format & PNG_FORMAT_FLAG_LINEAR) != 0 && 37093965825b97a5809454f5810f7e603cbd02daa036scroggo (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) 37103965825b97a5809454f5810f7e603cbd02daa036scroggo input_gamma_default = PNG_GAMMA_LINEAR; 37113965825b97a5809454f5810f7e603cbd02daa036scroggo else 37123965825b97a5809454f5810f7e603cbd02daa036scroggo input_gamma_default = PNG_DEFAULT_sRGB; 37133965825b97a5809454f5810f7e603cbd02daa036scroggo 37143965825b97a5809454f5810f7e603cbd02daa036scroggo /* Call png_set_alpha_mode to set the default for the input gamma; the 37153965825b97a5809454f5810f7e603cbd02daa036scroggo * output gamma is set by a second call below. 37163965825b97a5809454f5810f7e603cbd02daa036scroggo */ 37173965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default); 37183965825b97a5809454f5810f7e603cbd02daa036scroggo } 37193965825b97a5809454f5810f7e603cbd02daa036scroggo 37203965825b97a5809454f5810f7e603cbd02daa036scroggo if (linear != 0) 37213965825b97a5809454f5810f7e603cbd02daa036scroggo { 37223965825b97a5809454f5810f7e603cbd02daa036scroggo /* If there *is* an alpha channel in the input it must be multiplied 37233965825b97a5809454f5810f7e603cbd02daa036scroggo * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG. 37243965825b97a5809454f5810f7e603cbd02daa036scroggo */ 37253965825b97a5809454f5810f7e603cbd02daa036scroggo if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0) 37263965825b97a5809454f5810f7e603cbd02daa036scroggo mode = PNG_ALPHA_STANDARD; /* associated alpha */ 37273965825b97a5809454f5810f7e603cbd02daa036scroggo 37283965825b97a5809454f5810f7e603cbd02daa036scroggo else 37293965825b97a5809454f5810f7e603cbd02daa036scroggo mode = PNG_ALPHA_PNG; 37303965825b97a5809454f5810f7e603cbd02daa036scroggo 37313965825b97a5809454f5810f7e603cbd02daa036scroggo output_gamma = PNG_GAMMA_LINEAR; 37323965825b97a5809454f5810f7e603cbd02daa036scroggo } 37333965825b97a5809454f5810f7e603cbd02daa036scroggo 37343965825b97a5809454f5810f7e603cbd02daa036scroggo else 37353965825b97a5809454f5810f7e603cbd02daa036scroggo { 37363965825b97a5809454f5810f7e603cbd02daa036scroggo mode = PNG_ALPHA_PNG; 37373965825b97a5809454f5810f7e603cbd02daa036scroggo output_gamma = PNG_DEFAULT_sRGB; 37383965825b97a5809454f5810f7e603cbd02daa036scroggo } 37393965825b97a5809454f5810f7e603cbd02daa036scroggo 37403965825b97a5809454f5810f7e603cbd02daa036scroggo /* If 'do_local_background' is set check for the presence of gamma 37413965825b97a5809454f5810f7e603cbd02daa036scroggo * correction; this is part of the work-round for the libpng bug 37423965825b97a5809454f5810f7e603cbd02daa036scroggo * described above. 37433965825b97a5809454f5810f7e603cbd02daa036scroggo * 37443965825b97a5809454f5810f7e603cbd02daa036scroggo * TODO: fix libpng and remove this. 37453965825b97a5809454f5810f7e603cbd02daa036scroggo */ 37463965825b97a5809454f5810f7e603cbd02daa036scroggo if (do_local_background != 0) 37473965825b97a5809454f5810f7e603cbd02daa036scroggo { 37483965825b97a5809454f5810f7e603cbd02daa036scroggo png_fixed_point gtest; 37493965825b97a5809454f5810f7e603cbd02daa036scroggo 37503965825b97a5809454f5810f7e603cbd02daa036scroggo /* This is 'png_gamma_threshold' from pngrtran.c; the test used for 37513965825b97a5809454f5810f7e603cbd02daa036scroggo * gamma correction, the screen gamma hasn't been set on png_struct 37523965825b97a5809454f5810f7e603cbd02daa036scroggo * yet; it's set below. png_struct::gamma, however, is set to the 37533965825b97a5809454f5810f7e603cbd02daa036scroggo * final value. 37543965825b97a5809454f5810f7e603cbd02daa036scroggo */ 37553965825b97a5809454f5810f7e603cbd02daa036scroggo if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma, 37563965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0) 37573965825b97a5809454f5810f7e603cbd02daa036scroggo do_local_background = 0; 37583965825b97a5809454f5810f7e603cbd02daa036scroggo 37593965825b97a5809454f5810f7e603cbd02daa036scroggo else if (mode == PNG_ALPHA_STANDARD) 37603965825b97a5809454f5810f7e603cbd02daa036scroggo { 37613965825b97a5809454f5810f7e603cbd02daa036scroggo do_local_background = 2/*required*/; 37623965825b97a5809454f5810f7e603cbd02daa036scroggo mode = PNG_ALPHA_PNG; /* prevent libpng doing it */ 37633965825b97a5809454f5810f7e603cbd02daa036scroggo } 37643965825b97a5809454f5810f7e603cbd02daa036scroggo 37653965825b97a5809454f5810f7e603cbd02daa036scroggo /* else leave as 1 for the checks below */ 37663965825b97a5809454f5810f7e603cbd02daa036scroggo } 37673965825b97a5809454f5810f7e603cbd02daa036scroggo 37683965825b97a5809454f5810f7e603cbd02daa036scroggo /* If the bit-depth changes then handle that here. */ 37693965825b97a5809454f5810f7e603cbd02daa036scroggo if ((change & PNG_FORMAT_FLAG_LINEAR) != 0) 37703965825b97a5809454f5810f7e603cbd02daa036scroggo { 37713965825b97a5809454f5810f7e603cbd02daa036scroggo if (linear != 0 /*16-bit output*/) 37723965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_expand_16(png_ptr); 37733965825b97a5809454f5810f7e603cbd02daa036scroggo 37743965825b97a5809454f5810f7e603cbd02daa036scroggo else /* 8-bit output */ 37753965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_scale_16(png_ptr); 37763965825b97a5809454f5810f7e603cbd02daa036scroggo 37773965825b97a5809454f5810f7e603cbd02daa036scroggo change &= ~PNG_FORMAT_FLAG_LINEAR; 37783965825b97a5809454f5810f7e603cbd02daa036scroggo } 37793965825b97a5809454f5810f7e603cbd02daa036scroggo 37803965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now the background/alpha channel changes. */ 37813965825b97a5809454f5810f7e603cbd02daa036scroggo if ((change & PNG_FORMAT_FLAG_ALPHA) != 0) 37823965825b97a5809454f5810f7e603cbd02daa036scroggo { 37833965825b97a5809454f5810f7e603cbd02daa036scroggo /* Removing an alpha channel requires composition for the 8-bit 37843965825b97a5809454f5810f7e603cbd02daa036scroggo * formats; for the 16-bit it is already done, above, by the 37853965825b97a5809454f5810f7e603cbd02daa036scroggo * pre-multiplication and the channel just needs to be stripped. 37863965825b97a5809454f5810f7e603cbd02daa036scroggo */ 37873965825b97a5809454f5810f7e603cbd02daa036scroggo if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0) 37883965825b97a5809454f5810f7e603cbd02daa036scroggo { 37893965825b97a5809454f5810f7e603cbd02daa036scroggo /* If RGB->gray is happening the alpha channel must be left and the 37903965825b97a5809454f5810f7e603cbd02daa036scroggo * operation completed locally. 37913965825b97a5809454f5810f7e603cbd02daa036scroggo * 37923965825b97a5809454f5810f7e603cbd02daa036scroggo * TODO: fix libpng and remove this. 37933965825b97a5809454f5810f7e603cbd02daa036scroggo */ 37943965825b97a5809454f5810f7e603cbd02daa036scroggo if (do_local_background != 0) 37953965825b97a5809454f5810f7e603cbd02daa036scroggo do_local_background = 2/*required*/; 37963965825b97a5809454f5810f7e603cbd02daa036scroggo 37973965825b97a5809454f5810f7e603cbd02daa036scroggo /* 16-bit output: just remove the channel */ 37983965825b97a5809454f5810f7e603cbd02daa036scroggo else if (linear != 0) /* compose on black (well, pre-multiply) */ 37993965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_strip_alpha(png_ptr); 38003965825b97a5809454f5810f7e603cbd02daa036scroggo 38013965825b97a5809454f5810f7e603cbd02daa036scroggo /* 8-bit output: do an appropriate compose */ 38023965825b97a5809454f5810f7e603cbd02daa036scroggo else if (display->background != NULL) 38033965825b97a5809454f5810f7e603cbd02daa036scroggo { 38043965825b97a5809454f5810f7e603cbd02daa036scroggo png_color_16 c; 38053965825b97a5809454f5810f7e603cbd02daa036scroggo 38063965825b97a5809454f5810f7e603cbd02daa036scroggo c.index = 0; /*unused*/ 38073965825b97a5809454f5810f7e603cbd02daa036scroggo c.red = display->background->red; 38083965825b97a5809454f5810f7e603cbd02daa036scroggo c.green = display->background->green; 38093965825b97a5809454f5810f7e603cbd02daa036scroggo c.blue = display->background->blue; 38103965825b97a5809454f5810f7e603cbd02daa036scroggo c.gray = display->background->green; 38113965825b97a5809454f5810f7e603cbd02daa036scroggo 38123965825b97a5809454f5810f7e603cbd02daa036scroggo /* This is always an 8-bit sRGB value, using the 'green' channel 38133965825b97a5809454f5810f7e603cbd02daa036scroggo * for gray is much better than calculating the luminance here; 38143965825b97a5809454f5810f7e603cbd02daa036scroggo * we can get off-by-one errors in that calculation relative to 38153965825b97a5809454f5810f7e603cbd02daa036scroggo * the app expectations and that will show up in transparent 38163965825b97a5809454f5810f7e603cbd02daa036scroggo * pixels. 38173965825b97a5809454f5810f7e603cbd02daa036scroggo */ 38183965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_background_fixed(png_ptr, &c, 38193965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, 38203965825b97a5809454f5810f7e603cbd02daa036scroggo 0/*gamma: not used*/); 38213965825b97a5809454f5810f7e603cbd02daa036scroggo } 38223965825b97a5809454f5810f7e603cbd02daa036scroggo 38233965825b97a5809454f5810f7e603cbd02daa036scroggo else /* compose on row: implemented below. */ 38243965825b97a5809454f5810f7e603cbd02daa036scroggo { 38253965825b97a5809454f5810f7e603cbd02daa036scroggo do_local_compose = 1; 38263965825b97a5809454f5810f7e603cbd02daa036scroggo /* This leaves the alpha channel in the output, so it has to be 38273965825b97a5809454f5810f7e603cbd02daa036scroggo * removed by the code below. Set the encoding to the 'OPTIMIZE' 38283965825b97a5809454f5810f7e603cbd02daa036scroggo * one so the code only has to hack on the pixels that require 38293965825b97a5809454f5810f7e603cbd02daa036scroggo * composition. 38303965825b97a5809454f5810f7e603cbd02daa036scroggo */ 38313965825b97a5809454f5810f7e603cbd02daa036scroggo mode = PNG_ALPHA_OPTIMIZED; 38323965825b97a5809454f5810f7e603cbd02daa036scroggo } 38333965825b97a5809454f5810f7e603cbd02daa036scroggo } 38343965825b97a5809454f5810f7e603cbd02daa036scroggo 38353965825b97a5809454f5810f7e603cbd02daa036scroggo else /* output needs an alpha channel */ 38363965825b97a5809454f5810f7e603cbd02daa036scroggo { 38373965825b97a5809454f5810f7e603cbd02daa036scroggo /* This is tricky because it happens before the swap operation has 38383965825b97a5809454f5810f7e603cbd02daa036scroggo * been accomplished; however, the swap does *not* swap the added 38393965825b97a5809454f5810f7e603cbd02daa036scroggo * alpha channel (weird API), so it must be added in the correct 38403965825b97a5809454f5810f7e603cbd02daa036scroggo * place. 38413965825b97a5809454f5810f7e603cbd02daa036scroggo */ 38423965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 filler; /* opaque filler */ 38433965825b97a5809454f5810f7e603cbd02daa036scroggo int where; 38443965825b97a5809454f5810f7e603cbd02daa036scroggo 38453965825b97a5809454f5810f7e603cbd02daa036scroggo if (linear != 0) 38463965825b97a5809454f5810f7e603cbd02daa036scroggo filler = 65535; 38473965825b97a5809454f5810f7e603cbd02daa036scroggo 38483965825b97a5809454f5810f7e603cbd02daa036scroggo else 38493965825b97a5809454f5810f7e603cbd02daa036scroggo filler = 255; 38503965825b97a5809454f5810f7e603cbd02daa036scroggo 38513965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_FORMAT_AFIRST_SUPPORTED 38523965825b97a5809454f5810f7e603cbd02daa036scroggo if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) 38533965825b97a5809454f5810f7e603cbd02daa036scroggo { 38543965825b97a5809454f5810f7e603cbd02daa036scroggo where = PNG_FILLER_BEFORE; 38553965825b97a5809454f5810f7e603cbd02daa036scroggo change &= ~PNG_FORMAT_FLAG_AFIRST; 38563965825b97a5809454f5810f7e603cbd02daa036scroggo } 38573965825b97a5809454f5810f7e603cbd02daa036scroggo 38583965825b97a5809454f5810f7e603cbd02daa036scroggo else 38593965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 38603965825b97a5809454f5810f7e603cbd02daa036scroggo where = PNG_FILLER_AFTER; 38613965825b97a5809454f5810f7e603cbd02daa036scroggo 38623965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_add_alpha(png_ptr, filler, where); 38633965825b97a5809454f5810f7e603cbd02daa036scroggo } 38643965825b97a5809454f5810f7e603cbd02daa036scroggo 38653965825b97a5809454f5810f7e603cbd02daa036scroggo /* This stops the (irrelevant) call to swap_alpha below. */ 38663965825b97a5809454f5810f7e603cbd02daa036scroggo change &= ~PNG_FORMAT_FLAG_ALPHA; 38673965825b97a5809454f5810f7e603cbd02daa036scroggo } 38683965825b97a5809454f5810f7e603cbd02daa036scroggo 38693965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now set the alpha mode correctly; this is always done, even if there is 38703965825b97a5809454f5810f7e603cbd02daa036scroggo * no alpha channel in either the input or the output because it correctly 38713965825b97a5809454f5810f7e603cbd02daa036scroggo * sets the output gamma. 38723965825b97a5809454f5810f7e603cbd02daa036scroggo */ 38733965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_alpha_mode_fixed(png_ptr, mode, output_gamma); 38743965825b97a5809454f5810f7e603cbd02daa036scroggo 38753965825b97a5809454f5810f7e603cbd02daa036scroggo# ifdef PNG_FORMAT_BGR_SUPPORTED 38763965825b97a5809454f5810f7e603cbd02daa036scroggo if ((change & PNG_FORMAT_FLAG_BGR) != 0) 38773965825b97a5809454f5810f7e603cbd02daa036scroggo { 38783965825b97a5809454f5810f7e603cbd02daa036scroggo /* Check only the output format; PNG is never BGR; don't do this if 38793965825b97a5809454f5810f7e603cbd02daa036scroggo * the output is gray, but fix up the 'format' value in that case. 38803965825b97a5809454f5810f7e603cbd02daa036scroggo */ 38813965825b97a5809454f5810f7e603cbd02daa036scroggo if ((format & PNG_FORMAT_FLAG_COLOR) != 0) 38823965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_bgr(png_ptr); 38833965825b97a5809454f5810f7e603cbd02daa036scroggo 38843965825b97a5809454f5810f7e603cbd02daa036scroggo else 38853965825b97a5809454f5810f7e603cbd02daa036scroggo format &= ~PNG_FORMAT_FLAG_BGR; 38863965825b97a5809454f5810f7e603cbd02daa036scroggo 38873965825b97a5809454f5810f7e603cbd02daa036scroggo change &= ~PNG_FORMAT_FLAG_BGR; 38883965825b97a5809454f5810f7e603cbd02daa036scroggo } 38893965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 38903965825b97a5809454f5810f7e603cbd02daa036scroggo 38913965825b97a5809454f5810f7e603cbd02daa036scroggo# ifdef PNG_FORMAT_AFIRST_SUPPORTED 38923965825b97a5809454f5810f7e603cbd02daa036scroggo if ((change & PNG_FORMAT_FLAG_AFIRST) != 0) 38933965825b97a5809454f5810f7e603cbd02daa036scroggo { 38943965825b97a5809454f5810f7e603cbd02daa036scroggo /* Only relevant if there is an alpha channel - it's particularly 38953965825b97a5809454f5810f7e603cbd02daa036scroggo * important to handle this correctly because do_local_compose may 38963965825b97a5809454f5810f7e603cbd02daa036scroggo * be set above and then libpng will keep the alpha channel for this 38973965825b97a5809454f5810f7e603cbd02daa036scroggo * code to remove. 38983965825b97a5809454f5810f7e603cbd02daa036scroggo */ 38993965825b97a5809454f5810f7e603cbd02daa036scroggo if ((format & PNG_FORMAT_FLAG_ALPHA) != 0) 39003965825b97a5809454f5810f7e603cbd02daa036scroggo { 39013965825b97a5809454f5810f7e603cbd02daa036scroggo /* Disable this if doing a local background, 39023965825b97a5809454f5810f7e603cbd02daa036scroggo * TODO: remove this when local background is no longer required. 39033965825b97a5809454f5810f7e603cbd02daa036scroggo */ 39043965825b97a5809454f5810f7e603cbd02daa036scroggo if (do_local_background != 2) 39053965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_swap_alpha(png_ptr); 39063965825b97a5809454f5810f7e603cbd02daa036scroggo } 39073965825b97a5809454f5810f7e603cbd02daa036scroggo 39083965825b97a5809454f5810f7e603cbd02daa036scroggo else 39093965825b97a5809454f5810f7e603cbd02daa036scroggo format &= ~PNG_FORMAT_FLAG_AFIRST; 39103965825b97a5809454f5810f7e603cbd02daa036scroggo 39113965825b97a5809454f5810f7e603cbd02daa036scroggo change &= ~PNG_FORMAT_FLAG_AFIRST; 39123965825b97a5809454f5810f7e603cbd02daa036scroggo } 39133965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 39143965825b97a5809454f5810f7e603cbd02daa036scroggo 39153965825b97a5809454f5810f7e603cbd02daa036scroggo /* If the *output* is 16-bit then we need to check for a byte-swap on this 39163965825b97a5809454f5810f7e603cbd02daa036scroggo * architecture. 39173965825b97a5809454f5810f7e603cbd02daa036scroggo */ 39183965825b97a5809454f5810f7e603cbd02daa036scroggo if (linear != 0) 39193965825b97a5809454f5810f7e603cbd02daa036scroggo { 39203965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_CONST png_uint_16 le = 0x0001; 39213965825b97a5809454f5810f7e603cbd02daa036scroggo 39223965825b97a5809454f5810f7e603cbd02daa036scroggo if ((*(png_const_bytep) & le) != 0) 39233965825b97a5809454f5810f7e603cbd02daa036scroggo png_set_swap(png_ptr); 39243965825b97a5809454f5810f7e603cbd02daa036scroggo } 39253965825b97a5809454f5810f7e603cbd02daa036scroggo 39263965825b97a5809454f5810f7e603cbd02daa036scroggo /* If change is not now 0 some transformation is missing - error out. */ 39273965825b97a5809454f5810f7e603cbd02daa036scroggo if (change != 0) 39283965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "png_read_image: unsupported transformation"); 39293965825b97a5809454f5810f7e603cbd02daa036scroggo } 39303965825b97a5809454f5810f7e603cbd02daa036scroggo 39313965825b97a5809454f5810f7e603cbd02daa036scroggo PNG_SKIP_CHUNKS(png_ptr); 39323965825b97a5809454f5810f7e603cbd02daa036scroggo 39333965825b97a5809454f5810f7e603cbd02daa036scroggo /* Update the 'info' structure and make sure the result is as required; first 39343965825b97a5809454f5810f7e603cbd02daa036scroggo * make sure to turn on the interlace handling if it will be required 39353965825b97a5809454f5810f7e603cbd02daa036scroggo * (because it can't be turned on *after* the call to png_read_update_info!) 39363965825b97a5809454f5810f7e603cbd02daa036scroggo * 39373965825b97a5809454f5810f7e603cbd02daa036scroggo * TODO: remove the do_local_background fixup below. 39383965825b97a5809454f5810f7e603cbd02daa036scroggo */ 39393965825b97a5809454f5810f7e603cbd02daa036scroggo if (do_local_compose == 0 && do_local_background != 2) 39403965825b97a5809454f5810f7e603cbd02daa036scroggo passes = png_set_interlace_handling(png_ptr); 39413965825b97a5809454f5810f7e603cbd02daa036scroggo 39423965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_update_info(png_ptr, info_ptr); 39433965825b97a5809454f5810f7e603cbd02daa036scroggo 39443965825b97a5809454f5810f7e603cbd02daa036scroggo { 39453965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 info_format = 0; 39463965825b97a5809454f5810f7e603cbd02daa036scroggo 39473965825b97a5809454f5810f7e603cbd02daa036scroggo if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0) 39483965825b97a5809454f5810f7e603cbd02daa036scroggo info_format |= PNG_FORMAT_FLAG_COLOR; 39493965825b97a5809454f5810f7e603cbd02daa036scroggo 39503965825b97a5809454f5810f7e603cbd02daa036scroggo if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0) 39513965825b97a5809454f5810f7e603cbd02daa036scroggo { 39523965825b97a5809454f5810f7e603cbd02daa036scroggo /* do_local_compose removes this channel below. */ 39533965825b97a5809454f5810f7e603cbd02daa036scroggo if (do_local_compose == 0) 39543965825b97a5809454f5810f7e603cbd02daa036scroggo { 39553965825b97a5809454f5810f7e603cbd02daa036scroggo /* do_local_background does the same if required. */ 39563965825b97a5809454f5810f7e603cbd02daa036scroggo if (do_local_background != 2 || 39573965825b97a5809454f5810f7e603cbd02daa036scroggo (format & PNG_FORMAT_FLAG_ALPHA) != 0) 39583965825b97a5809454f5810f7e603cbd02daa036scroggo info_format |= PNG_FORMAT_FLAG_ALPHA; 39593965825b97a5809454f5810f7e603cbd02daa036scroggo } 39603965825b97a5809454f5810f7e603cbd02daa036scroggo } 39613965825b97a5809454f5810f7e603cbd02daa036scroggo 39623965825b97a5809454f5810f7e603cbd02daa036scroggo else if (do_local_compose != 0) /* internal error */ 39633965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "png_image_read: alpha channel lost"); 39643965825b97a5809454f5810f7e603cbd02daa036scroggo 39653965825b97a5809454f5810f7e603cbd02daa036scroggo if (info_ptr->bit_depth == 16) 39663965825b97a5809454f5810f7e603cbd02daa036scroggo info_format |= PNG_FORMAT_FLAG_LINEAR; 39673965825b97a5809454f5810f7e603cbd02daa036scroggo 39683965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_FORMAT_BGR_SUPPORTED 39693965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->transformations & PNG_BGR) != 0) 39703965825b97a5809454f5810f7e603cbd02daa036scroggo info_format |= PNG_FORMAT_FLAG_BGR; 39713965825b97a5809454f5810f7e603cbd02daa036scroggo#endif 39723965825b97a5809454f5810f7e603cbd02daa036scroggo 39733965825b97a5809454f5810f7e603cbd02daa036scroggo#ifdef PNG_FORMAT_AFIRST_SUPPORTED 39743965825b97a5809454f5810f7e603cbd02daa036scroggo if (do_local_background == 2) 39753965825b97a5809454f5810f7e603cbd02daa036scroggo { 39763965825b97a5809454f5810f7e603cbd02daa036scroggo if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) 39773965825b97a5809454f5810f7e603cbd02daa036scroggo info_format |= PNG_FORMAT_FLAG_AFIRST; 39783965825b97a5809454f5810f7e603cbd02daa036scroggo } 39793965825b97a5809454f5810f7e603cbd02daa036scroggo 39803965825b97a5809454f5810f7e603cbd02daa036scroggo if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 || 39813965825b97a5809454f5810f7e603cbd02daa036scroggo ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 && 39823965825b97a5809454f5810f7e603cbd02daa036scroggo (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0)) 39833965825b97a5809454f5810f7e603cbd02daa036scroggo { 39843965825b97a5809454f5810f7e603cbd02daa036scroggo if (do_local_background == 2) 39853965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "unexpected alpha swap transformation"); 39863965825b97a5809454f5810f7e603cbd02daa036scroggo 39873965825b97a5809454f5810f7e603cbd02daa036scroggo info_format |= PNG_FORMAT_FLAG_AFIRST; 39883965825b97a5809454f5810f7e603cbd02daa036scroggo } 39893965825b97a5809454f5810f7e603cbd02daa036scroggo# endif 39903965825b97a5809454f5810f7e603cbd02daa036scroggo 39913965825b97a5809454f5810f7e603cbd02daa036scroggo /* This is actually an internal error. */ 39923965825b97a5809454f5810f7e603cbd02daa036scroggo if (info_format != format) 39933965825b97a5809454f5810f7e603cbd02daa036scroggo png_error(png_ptr, "png_read_image: invalid transformations"); 39943965825b97a5809454f5810f7e603cbd02daa036scroggo } 39953965825b97a5809454f5810f7e603cbd02daa036scroggo 39963965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now read the rows. If do_local_compose is set then it is necessary to use 39973965825b97a5809454f5810f7e603cbd02daa036scroggo * a local row buffer. The output will be GA, RGBA or BGRA and must be 39983965825b97a5809454f5810f7e603cbd02daa036scroggo * converted to G, RGB or BGR as appropriate. The 'local_row' member of the 39993965825b97a5809454f5810f7e603cbd02daa036scroggo * display acts as a flag. 40003965825b97a5809454f5810f7e603cbd02daa036scroggo */ 40013965825b97a5809454f5810f7e603cbd02daa036scroggo { 40023965825b97a5809454f5810f7e603cbd02daa036scroggo png_voidp first_row = display->buffer; 40033965825b97a5809454f5810f7e603cbd02daa036scroggo ptrdiff_t row_bytes = display->row_stride; 40043965825b97a5809454f5810f7e603cbd02daa036scroggo 40053965825b97a5809454f5810f7e603cbd02daa036scroggo if (linear != 0) 40063965825b97a5809454f5810f7e603cbd02daa036scroggo row_bytes *= 2; 40073965825b97a5809454f5810f7e603cbd02daa036scroggo 40083965825b97a5809454f5810f7e603cbd02daa036scroggo /* The following expression is designed to work correctly whether it gives 40093965825b97a5809454f5810f7e603cbd02daa036scroggo * a signed or an unsigned result. 40103965825b97a5809454f5810f7e603cbd02daa036scroggo */ 40113965825b97a5809454f5810f7e603cbd02daa036scroggo if (row_bytes < 0) 40123965825b97a5809454f5810f7e603cbd02daa036scroggo { 40133965825b97a5809454f5810f7e603cbd02daa036scroggo char *ptr = png_voidcast(char*, first_row); 40143965825b97a5809454f5810f7e603cbd02daa036scroggo ptr += (image->height-1) * (-row_bytes); 40153965825b97a5809454f5810f7e603cbd02daa036scroggo first_row = png_voidcast(png_voidp, ptr); 40163965825b97a5809454f5810f7e603cbd02daa036scroggo } 40173965825b97a5809454f5810f7e603cbd02daa036scroggo 40183965825b97a5809454f5810f7e603cbd02daa036scroggo display->first_row = first_row; 40193965825b97a5809454f5810f7e603cbd02daa036scroggo display->row_bytes = row_bytes; 40203965825b97a5809454f5810f7e603cbd02daa036scroggo } 40213965825b97a5809454f5810f7e603cbd02daa036scroggo 40223965825b97a5809454f5810f7e603cbd02daa036scroggo if (do_local_compose != 0) 40233965825b97a5809454f5810f7e603cbd02daa036scroggo { 40243965825b97a5809454f5810f7e603cbd02daa036scroggo int result; 40253965825b97a5809454f5810f7e603cbd02daa036scroggo png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); 40263965825b97a5809454f5810f7e603cbd02daa036scroggo 40273965825b97a5809454f5810f7e603cbd02daa036scroggo display->local_row = row; 40283965825b97a5809454f5810f7e603cbd02daa036scroggo result = png_safe_execute(image, png_image_read_composite, display); 40293965825b97a5809454f5810f7e603cbd02daa036scroggo display->local_row = NULL; 40303965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, row); 40313965825b97a5809454f5810f7e603cbd02daa036scroggo 40323965825b97a5809454f5810f7e603cbd02daa036scroggo return result; 40333965825b97a5809454f5810f7e603cbd02daa036scroggo } 40343965825b97a5809454f5810f7e603cbd02daa036scroggo 40353965825b97a5809454f5810f7e603cbd02daa036scroggo else if (do_local_background == 2) 40363965825b97a5809454f5810f7e603cbd02daa036scroggo { 40373965825b97a5809454f5810f7e603cbd02daa036scroggo int result; 40383965825b97a5809454f5810f7e603cbd02daa036scroggo png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); 40393965825b97a5809454f5810f7e603cbd02daa036scroggo 40403965825b97a5809454f5810f7e603cbd02daa036scroggo display->local_row = row; 40413965825b97a5809454f5810f7e603cbd02daa036scroggo result = png_safe_execute(image, png_image_read_background, display); 40423965825b97a5809454f5810f7e603cbd02daa036scroggo display->local_row = NULL; 40433965825b97a5809454f5810f7e603cbd02daa036scroggo png_free(png_ptr, row); 40443965825b97a5809454f5810f7e603cbd02daa036scroggo 40453965825b97a5809454f5810f7e603cbd02daa036scroggo return result; 40463965825b97a5809454f5810f7e603cbd02daa036scroggo } 40473965825b97a5809454f5810f7e603cbd02daa036scroggo 40483965825b97a5809454f5810f7e603cbd02daa036scroggo else 40493965825b97a5809454f5810f7e603cbd02daa036scroggo { 40503965825b97a5809454f5810f7e603cbd02daa036scroggo png_alloc_size_t row_bytes = display->row_bytes; 40513965825b97a5809454f5810f7e603cbd02daa036scroggo 40523965825b97a5809454f5810f7e603cbd02daa036scroggo while (--passes >= 0) 40533965825b97a5809454f5810f7e603cbd02daa036scroggo { 40543965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 y = image->height; 40553965825b97a5809454f5810f7e603cbd02daa036scroggo png_bytep row = png_voidcast(png_bytep, display->first_row); 40563965825b97a5809454f5810f7e603cbd02daa036scroggo 40573965825b97a5809454f5810f7e603cbd02daa036scroggo while (y-- > 0) 40583965825b97a5809454f5810f7e603cbd02daa036scroggo { 40593965825b97a5809454f5810f7e603cbd02daa036scroggo png_read_row(png_ptr, row, NULL); 40603965825b97a5809454f5810f7e603cbd02daa036scroggo row += row_bytes; 40613965825b97a5809454f5810f7e603cbd02daa036scroggo } 40623965825b97a5809454f5810f7e603cbd02daa036scroggo } 40633965825b97a5809454f5810f7e603cbd02daa036scroggo 40643965825b97a5809454f5810f7e603cbd02daa036scroggo return 1; 40653965825b97a5809454f5810f7e603cbd02daa036scroggo } 40663965825b97a5809454f5810f7e603cbd02daa036scroggo} 40673965825b97a5809454f5810f7e603cbd02daa036scroggo 40683965825b97a5809454f5810f7e603cbd02daa036scroggoint PNGAPI 40693965825b97a5809454f5810f7e603cbd02daa036scroggopng_image_finish_read(png_imagep image, png_const_colorp background, 40703965825b97a5809454f5810f7e603cbd02daa036scroggo void *buffer, png_int_32 row_stride, void *colormap) 40713965825b97a5809454f5810f7e603cbd02daa036scroggo{ 40723965825b97a5809454f5810f7e603cbd02daa036scroggo if (image != NULL && image->version == PNG_IMAGE_VERSION) 40733965825b97a5809454f5810f7e603cbd02daa036scroggo { 40743965825b97a5809454f5810f7e603cbd02daa036scroggo /* Check for row_stride overflow. This check is not performed on the 40753965825b97a5809454f5810f7e603cbd02daa036scroggo * original PNG format because it may not occur in the output PNG format 40763965825b97a5809454f5810f7e603cbd02daa036scroggo * and libpng deals with the issues of reading the original. 40773965825b97a5809454f5810f7e603cbd02daa036scroggo */ 40783965825b97a5809454f5810f7e603cbd02daa036scroggo const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); 40793965825b97a5809454f5810f7e603cbd02daa036scroggo 40803965825b97a5809454f5810f7e603cbd02daa036scroggo if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */ 40813965825b97a5809454f5810f7e603cbd02daa036scroggo { 40823965825b97a5809454f5810f7e603cbd02daa036scroggo png_uint_32 check; 40833965825b97a5809454f5810f7e603cbd02daa036scroggo const png_uint_32 png_row_stride = image->width * channels; 40843965825b97a5809454f5810f7e603cbd02daa036scroggo 40853965825b97a5809454f5810f7e603cbd02daa036scroggo if (row_stride == 0) 40863965825b97a5809454f5810f7e603cbd02daa036scroggo row_stride = (png_int_32)/*SAFE*/png_row_stride; 40873965825b97a5809454f5810f7e603cbd02daa036scroggo 40883965825b97a5809454f5810f7e603cbd02daa036scroggo if (row_stride < 0) 40893965825b97a5809454f5810f7e603cbd02daa036scroggo check = -row_stride; 40903965825b97a5809454f5810f7e603cbd02daa036scroggo 40913965825b97a5809454f5810f7e603cbd02daa036scroggo else 40923965825b97a5809454f5810f7e603cbd02daa036scroggo check = row_stride; 40933965825b97a5809454f5810f7e603cbd02daa036scroggo 40943965825b97a5809454f5810f7e603cbd02daa036scroggo if (image->opaque != NULL && buffer != NULL && check >= png_row_stride) 40953965825b97a5809454f5810f7e603cbd02daa036scroggo { 40963965825b97a5809454f5810f7e603cbd02daa036scroggo /* Now check for overflow of the image buffer calculation; this 40973965825b97a5809454f5810f7e603cbd02daa036scroggo * limits the whole image size to 32 bits for API compatibility with 40983965825b97a5809454f5810f7e603cbd02daa036scroggo * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro. 40993965825b97a5809454f5810f7e603cbd02daa036scroggo */ 41003965825b97a5809454f5810f7e603cbd02daa036scroggo if (image->height <= 0xFFFFFFFF/png_row_stride) 41013965825b97a5809454f5810f7e603cbd02daa036scroggo { 41023965825b97a5809454f5810f7e603cbd02daa036scroggo if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || 41033965825b97a5809454f5810f7e603cbd02daa036scroggo (image->colormap_entries > 0 && colormap != NULL)) 41043965825b97a5809454f5810f7e603cbd02daa036scroggo { 41053965825b97a5809454f5810f7e603cbd02daa036scroggo int result; 41063965825b97a5809454f5810f7e603cbd02daa036scroggo png_image_read_control display; 41073965825b97a5809454f5810f7e603cbd02daa036scroggo 41083965825b97a5809454f5810f7e603cbd02daa036scroggo memset(&display, 0, (sizeof display)); 41093965825b97a5809454f5810f7e603cbd02daa036scroggo display.image = image; 41103965825b97a5809454f5810f7e603cbd02daa036scroggo display.buffer = buffer; 41113965825b97a5809454f5810f7e603cbd02daa036scroggo display.row_stride = row_stride; 41123965825b97a5809454f5810f7e603cbd02daa036scroggo display.colormap = colormap; 41133965825b97a5809454f5810f7e603cbd02daa036scroggo display.background = background; 41143965825b97a5809454f5810f7e603cbd02daa036scroggo display.local_row = NULL; 41153965825b97a5809454f5810f7e603cbd02daa036scroggo 41163965825b97a5809454f5810f7e603cbd02daa036scroggo /* Choose the correct 'end' routine; for the color-map case 41173965825b97a5809454f5810f7e603cbd02daa036scroggo * all the setup has already been done. 41183965825b97a5809454f5810f7e603cbd02daa036scroggo */ 41193965825b97a5809454f5810f7e603cbd02daa036scroggo if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0) 41203965825b97a5809454f5810f7e603cbd02daa036scroggo result = png_safe_execute(image, 41213965825b97a5809454f5810f7e603cbd02daa036scroggo png_image_read_colormap, &display) && 41223965825b97a5809454f5810f7e603cbd02daa036scroggo png_safe_execute(image, 41233965825b97a5809454f5810f7e603cbd02daa036scroggo png_image_read_colormapped, &display); 41243965825b97a5809454f5810f7e603cbd02daa036scroggo 41253965825b97a5809454f5810f7e603cbd02daa036scroggo else 41263965825b97a5809454f5810f7e603cbd02daa036scroggo result = 41273965825b97a5809454f5810f7e603cbd02daa036scroggo png_safe_execute(image, 41283965825b97a5809454f5810f7e603cbd02daa036scroggo png_image_read_direct, &display); 41293965825b97a5809454f5810f7e603cbd02daa036scroggo 41303965825b97a5809454f5810f7e603cbd02daa036scroggo png_image_free(image); 41313965825b97a5809454f5810f7e603cbd02daa036scroggo return result; 41323965825b97a5809454f5810f7e603cbd02daa036scroggo } 41333965825b97a5809454f5810f7e603cbd02daa036scroggo 41343965825b97a5809454f5810f7e603cbd02daa036scroggo else 41353965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, 41363965825b97a5809454f5810f7e603cbd02daa036scroggo "png_image_finish_read[color-map]: no color-map"); 41373965825b97a5809454f5810f7e603cbd02daa036scroggo } 41383965825b97a5809454f5810f7e603cbd02daa036scroggo 41393965825b97a5809454f5810f7e603cbd02daa036scroggo else 41403965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, 41413965825b97a5809454f5810f7e603cbd02daa036scroggo "png_image_finish_read: image too large"); 41423965825b97a5809454f5810f7e603cbd02daa036scroggo } 41433965825b97a5809454f5810f7e603cbd02daa036scroggo 41443965825b97a5809454f5810f7e603cbd02daa036scroggo else 41453965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, 41463965825b97a5809454f5810f7e603cbd02daa036scroggo "png_image_finish_read: invalid argument"); 41473965825b97a5809454f5810f7e603cbd02daa036scroggo } 41483965825b97a5809454f5810f7e603cbd02daa036scroggo 41493965825b97a5809454f5810f7e603cbd02daa036scroggo else 41503965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, 41513965825b97a5809454f5810f7e603cbd02daa036scroggo "png_image_finish_read: row_stride too large"); 41523965825b97a5809454f5810f7e603cbd02daa036scroggo } 41533965825b97a5809454f5810f7e603cbd02daa036scroggo 41543965825b97a5809454f5810f7e603cbd02daa036scroggo else if (image != NULL) 41553965825b97a5809454f5810f7e603cbd02daa036scroggo return png_image_error(image, 41563965825b97a5809454f5810f7e603cbd02daa036scroggo "png_image_finish_read: damaged PNG_IMAGE_VERSION"); 41573965825b97a5809454f5810f7e603cbd02daa036scroggo 41583965825b97a5809454f5810f7e603cbd02daa036scroggo return 0; 41593965825b97a5809454f5810f7e603cbd02daa036scroggo} 41603965825b97a5809454f5810f7e603cbd02daa036scroggo 41613965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* SIMPLIFIED_READ */ 41623965825b97a5809454f5810f7e603cbd02daa036scroggo#endif /* READ */ 4163