1893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* png.c - location for general purpose libpng functions 3893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 43cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * Last changed in libpng 1.6.33 [September 28, 2017] 53cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson 6893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 7893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 8a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * 9a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * This code is released under the libpng license. 10a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * For conditions of distribution and use, see the disclaimer 11a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * and license in png.h 12893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 13893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 14b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include "pngpriv.h" 15893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 16893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Generate a compiler error if there is an old png.h in the search path. */ 173cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins IIItypedef png_libpng_version_1_6_34 Your_png_h_is_not_version_1_6_34; 183cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III 193cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#ifdef __GNUC__ 203cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III/* The version tests may need to be added to, but the problem warning has 213cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * consistently been fixed in GCC versions which obtain wide-spread release. 223cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * The problem is that many versions of GCC rearrange comparison expressions in 233cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * the optimizer in such a way that the results of the comparison will change 243cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * if signed integer overflow occurs. Such comparisons are not permitted in 253cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * ANSI C90, however GCC isn't clever enough to work out that that do not occur 263cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * below in png_ascii_from_fp and png_muldiv, so it produces a warning with 273cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * -Wextra. Unfortunately this is highly dependent on the optimizer and the 283cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * machine architecture so the warning comes and goes unpredictably and is 293cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * impossible to "fix", even were that a good idea. 303cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III */ 313cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#if __GNUC__ == 7 && __GNUC_MINOR__ == 1 323cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#define GCC_STRICT_OVERFLOW 1 333cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#endif /* GNU 7.1.x */ 343cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#endif /* GNU */ 353cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#ifndef GCC_STRICT_OVERFLOW 363cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#define GCC_STRICT_OVERFLOW 0 373cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#endif 38893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 39893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Tells libpng that we have already handled the first "num_bytes" bytes 40893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * of the PNG file signature. If the PNG data is embedded into another 41893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * stream we can set num_bytes = 8 so that libpng will not attempt to read 42893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * or write any of the magic bytes before it starts on the IHDR. 43893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 44893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 45893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_READ_SUPPORTED 46893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 47b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_sig_bytes(png_structrp png_ptr, int num_bytes) 48893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 499b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett unsigned int nb = (unsigned int)num_bytes; 509b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 515f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_debug(1, "in png_set_sig_bytes"); 525f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 53a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 54a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 555f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (num_bytes < 0) 579b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett nb = 0; 589b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (nb > 8) 60b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "Too many bytes for PNG signature"); 61893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->sig_bytes = (png_byte)nb; 63893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 64893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 65893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Checks whether the supplied bytes match the PNG signature. We allow 66893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * checking less than the full 8-byte signature so that those apps that 67893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * already read the first few bytes of a file to determine the file type 68893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * can simply check the remaining bytes for extra assurance. Returns 69893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * an integer less than, equal to, or greater than zero if sig is found, 70893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * respectively, to be less than, to match, or be greater than the correct 71b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG signature (this is the same behavior as strcmp, memcmp, etc). 72893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 73893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectint PNGAPI 74b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check) 75893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 76893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; 77b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 78893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (num_to_check > 8) 79893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project num_to_check = 8; 80b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 81893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else if (num_to_check < 1) 82893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return (-1); 83893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 84893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (start > 7) 85893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return (-1); 86893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 87893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (start + num_to_check > 8) 88893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project num_to_check = 8 - start; 89893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 90b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check))); 91893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 92893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 939b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ */ 94893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 95893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) 96b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Function to allocate memory for zlib */ 97b50c217251b086440efcdb273c22f86a06c80cbaChris CraikPNG_FUNCTION(voidpf /* PRIVATE */, 98b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED) 99893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_alloc_size_t num_bytes = size; 101893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 102a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return NULL; 104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (items >= (~(png_alloc_size_t)0)/size) 106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning (png_voidcast(png_structrp, png_ptr), 1087a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "Potential overflow in png_zalloc()"); 109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return NULL; 110893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik num_bytes *= items; 113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes); 114893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 115893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 116a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Function to free memory for zlib */ 1175f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scottvoid /* PRIVATE */ 118893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_zfree(voidpf png_ptr, voidpf ptr) 119893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_voidcast(png_const_structrp,png_ptr), ptr); 121893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 122893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 123893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Reset the CRC variable to 32 bits of 1's. Care must be taken 124893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * in case CRC is > 32 bits to leave the top bits 0. 125893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 126893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 127b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_reset_crc(png_structrp png_ptr) 128893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1299b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* The cast is safe because the crc is a 32-bit value. */ 130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0); 131893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 132893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 133893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Calculate the CRC over a section of data. We can only pass as 134893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * much data to this routine as the largest single buffer size. We 135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * also check that this data will actually be used before going to the 136893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * trouble of calculating it. 137893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 138893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 139b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) 140893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 141893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int need_crc = 1; 142893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0) 144893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 145893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) == 146893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project (PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN)) 147893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project need_crc = 0; 148893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* critical */ 151893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0) 153893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project need_crc = 0; 154893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 155893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 'uLong' is defined in zlib.h as unsigned long; this means that on some 1579b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * systems it is a 64-bit value. crc32, however, returns 32 bits so the 158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * following cast is safe. 'uInt' may be no more than 16 bits, so it is 159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * necessary to perform a loop here. 160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (need_crc != 0 && length > 0) 162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik uLong crc = png_ptr->crc; /* Should never issue a warning */ 164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do 166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik uInt safe_length = (uInt)length; 1689b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifndef __COVERITY__ 169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (safe_length == 0) 170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik safe_length = (uInt)-1; /* evil, but safe */ 1719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik crc = crc32(crc, ptr, safe_length); 174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following should never issue compiler warnings; if they do the 176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * target system has characteristics that will probably violate other 177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * assumptions within the libpng code. 178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptr += safe_length; 180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik length -= safe_length; 181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (length > 0); 183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And the following is always safe because the crc is only 32 bits. */ 185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->crc = (png_uint_32)crc; 186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Check a user supplied version number, called from both read and write 190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * functions that create a png_struct. 191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 192b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint 193b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) 194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1957a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* Libpng versions 1.0.0 and later are binary compatible if the version 1967a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * string matches through the second '.'; we must recompile any 1977a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * applications that use any older library version. 1987a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis */ 1999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 2009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (user_png_ver != NULL) 201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int i = -1; 2039b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int found_dots = 0; 204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do 206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett i++; 2089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (user_png_ver[i] != PNG_LIBPNG_VER_STRING[i]) 209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; 2109b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (user_png_ver[i] == '.') 2119b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett found_dots++; 2129b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } while (found_dots < 2 && user_png_ver[i] != 0 && 2139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_LIBPNG_VER_STRING[i] != 0); 214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; 218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) != 0) 220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WARNINGS_SUPPORTED 2229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett size_t pos = 0; 2239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett char m[128]; 224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pos = png_safecat(m, (sizeof m), pos, 2269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett "Application built with libpng-"); 2279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pos = png_safecat(m, (sizeof m), pos, user_png_ver); 2289b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pos = png_safecat(m, (sizeof m), pos, " but running with "); 2299b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pos = png_safecat(m, (sizeof m), pos, PNG_LIBPNG_VER_STRING); 2309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(pos) 231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_warning(png_ptr, m); 233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_ERROR_NUMBERS_SUPPORTED 2369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->flags = 0; 237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 0; 240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Success return. */ 243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 244893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 245893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Generic function to create a png_struct for either read or write - this 247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * contains the common initialization. 248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 249b50c217251b086440efcdb273c22f86a06c80cbaChris CraikPNG_FUNCTION(png_structp /* PRIVATE */, 250b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, 251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, 252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) 253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_struct create_struct; 255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_SETJMP_SUPPORTED 256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik jmp_buf create_jmp_buf; 257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This temporary stack-allocated structure is used to provide a place to 260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * build enough context to allow the user provided memory allocator (if any) 261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to be called. 262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(&create_struct, 0, (sizeof create_struct)); 264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Added at libpng-1.2.6 */ 266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_USER_LIMITS_SUPPORTED 267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik create_struct.user_width_max = PNG_USER_WIDTH_MAX; 268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik create_struct.user_height_max = PNG_USER_HEIGHT_MAX; 269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_USER_CHUNK_CACHE_MAX 2719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Added at libpng-1.2.43 and 1.4.0 */ 2729b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; 273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_USER_CHUNK_MALLOC_MAX 2769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists 2779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * in png_struct regardless. 2789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett */ 2799b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; 280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following two API calls simply set fields in png_struct, so it is safe 284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to do them now even though error handling is not yet set up. 285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_USER_MEM_SUPPORTED 287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn); 288b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# else 289b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari PNG_UNUSED(mem_ptr) 290b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari PNG_UNUSED(malloc_fn) 291b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari PNG_UNUSED(free_fn) 292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* (*error_fn) can return control to the caller after the error_ptr is set, 295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this will result in a memory leak unless the error_fn does something 296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * extremely sophisticated. The design lacks merit but is implicit in the 297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * API. 298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn); 300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_SETJMP_SUPPORTED 302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!setjmp(create_jmp_buf)) 3039b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3059b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef PNG_SETJMP_SUPPORTED 306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Temporarily fake out the longjmp information until we have 307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * successfully completed this function. This only works if we have 308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * setjmp() support compiled in, but it is safe - this stuff should 309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * never happen. 310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik create_struct.jmp_buf_ptr = &create_jmp_buf; 312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik create_struct.jmp_buf_size = 0; /*stack allocation*/ 313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik create_struct.longjmp_fn = longjmp; 314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Call the general version checker (shared with read and write code): 316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3179b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_user_version_check(&create_struct, user_png_ver) != 0) 318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = png_voidcast(png_structrp, 3207a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_malloc_warn(&create_struct, (sizeof *png_ptr))); 321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr != NULL) 323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* png_ptr->zstream holds a back-pointer to the png_struct, so 325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this can only be done now: 326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik create_struct.zstream.zalloc = png_zalloc; 328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik create_struct.zstream.zfree = png_zfree; 329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik create_struct.zstream.opaque = png_ptr; 330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_SETJMP_SUPPORTED 3329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Eliminate the local error handling: */ 3339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett create_struct.jmp_buf_ptr = NULL; 3349b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett create_struct.jmp_buf_size = 0; 3359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett create_struct.longjmp_fn = 0; 336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *png_ptr = create_struct; 339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is the successful return point */ 341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_ptr; 342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* A longjmp because of a bug in the application storage allocator or a 347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * simple failure to allocate the png_struct. 348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return NULL; 350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Allocate the memory for an info_struct for the application. */ 353b50c217251b086440efcdb273c22f86a06c80cbaChris CraikPNG_FUNCTION(png_infop,PNGAPI 354b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED) 355893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_inforp info_ptr; 357893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 3584215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_create_info_struct"); 3595f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 360a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return NULL; 362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Use the internal API that does not (or at least should not) error out, so 364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * that this call always returns ok. The application typically sets up the 365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * error handling *after* creating the info_struct because this is the way it 366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * has always been done in 'example.c'. 367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr, 3697a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis (sizeof *info_ptr))); 3705f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 371893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (info_ptr != NULL) 372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(info_ptr, 0, (sizeof *info_ptr)); 373893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return info_ptr; 375893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 376893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 377893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* This function frees the memory associated with a single info struct. 378893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * Normally, one would use either png_destroy_read_struct() or 379893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * png_destroy_write_struct() to free an info struct, but this may be 380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * useful for some applications. From libpng 1.6.0 this function is also used 381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * internally to implement the png_info release part of the 'struct' destroy 382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * APIs. This ensures that all possible approaches free the same data (all of 383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it). 384893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 385893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 386b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr) 387893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_inforp info_ptr = NULL; 3895f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 3905f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_debug(1, "in png_destroy_info_struct"); 3915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 392a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 393a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 394893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 395893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (info_ptr_ptr != NULL) 396893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project info_ptr = *info_ptr_ptr; 397893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 398893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (info_ptr != NULL) 399893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Do this first in case of an error below; if the app implements its own 401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * memory management this can lead to png_free calling png_error, which 402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * will abort this routine and return control to the app error handler. 403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * An infinite loop may result if it then tries to free the same info 404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ptr. 405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 406893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *info_ptr_ptr = NULL; 407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); 409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(info_ptr, 0, (sizeof *info_ptr)); 410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, info_ptr); 411893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 412893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 413893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 414893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Initialize the info structure. This is now an internal function (0.89) 415893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * and applications using it are urged to use png_create_info_struct() 416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * instead. Use deprecated in 1.6.0, internal use removed (used internally it 417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is just a memset). 418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * NOTE: it is almost inconceivable that this API is used because it bypasses 420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the user-memory mechanism and the user error handling/warning mechanisms in 421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * those cases where it does anything other than a memset. 422893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 423b50c217251b086440efcdb273c22f86a06c80cbaChris CraikPNG_FUNCTION(void,PNGAPI 424b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), 4257a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_DEPRECATED) 426893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_inforp info_ptr = *ptr_ptr; 428893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 4295f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_debug(1, "in png_info_init_3"); 4305f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 431a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (info_ptr == NULL) 432a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((sizeof (png_info)) > png_info_struct_size) 435a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ptr_ptr = NULL; 437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following line is why this API should not be used: */ 438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik free(info_ptr); 439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL, 4407a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis (sizeof *info_ptr))); 4419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (info_ptr == NULL) 4429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return; 443a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott *ptr_ptr = info_ptr; 444a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 445893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 446a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Set everything to 0 */ 447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(info_ptr, 0, (sizeof *info_ptr)); 448893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 449893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The following API is not called internally */ 451893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 452b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_data_freer(png_const_structrp png_ptr, png_inforp info_ptr, 4537a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis int freer, png_uint_32 mask) 454893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 4554215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_data_freer"); 4565f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 457893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL || info_ptr == NULL) 458893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 4595f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4604215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project if (freer == PNG_DESTROY_WILL_FREE_DATA) 461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project info_ptr->free_me |= mask; 462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4634215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project else if (freer == PNG_USER_WILL_FREE_DATA) 464893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project info_ptr->free_me &= ~mask; 465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 466893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "Unknown freer parameter in png_data_freer"); 468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 469893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 470893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 471b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask, 4727a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis int num) 473893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 4744215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_free_data"); 4755f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 476893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL || info_ptr == NULL) 477893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 478893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 4795f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_TEXT_SUPPORTED 480a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Free text item num or (if num == -1) all text items */ 4813cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III if (info_ptr->text != NULL && 4829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett ((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0) 483893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 484a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (num != -1) 485a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 4869b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, info_ptr->text[num].key); 4879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->text[num].key = NULL; 488a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 490a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott else 491a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 492a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott int i; 4939b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 494a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott for (i = 0; i < info_ptr->num_text; i++) 4959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, info_ptr->text[i].key); 4969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 497a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->text); 498a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->text = NULL; 4999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->num_text = 0; 5003cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III info_ptr->max_text = 0; 501a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 502893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 503893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 504893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 5055f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_tRNS_SUPPORTED 506a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Free any tRNS entry */ 5079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (((mask & PNG_FREE_TRNS) & info_ptr->free_me) != 0) 508a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 5099b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->valid &= ~PNG_INFO_tRNS; 510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, info_ptr->trans_alpha); 511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->trans_alpha = NULL; 5129b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->num_trans = 0; 513a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 514893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 515893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 5165f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_sCAL_SUPPORTED 517a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Free any sCAL entry */ 5189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (((mask & PNG_FREE_SCAL) & info_ptr->free_me) != 0) 519a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 520a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->scal_s_width); 521a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->scal_s_height); 522a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->scal_s_width = NULL; 523a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->scal_s_height = NULL; 524a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->valid &= ~PNG_INFO_sCAL; 525a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 526893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 527893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 5285f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_pCAL_SUPPORTED 529a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Free any pCAL entry */ 5309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (((mask & PNG_FREE_PCAL) & info_ptr->free_me) != 0) 531a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 532a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->pcal_purpose); 533a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->pcal_units); 534a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->pcal_purpose = NULL; 535a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->pcal_units = NULL; 5369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 537a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (info_ptr->pcal_params != NULL) 538a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 5399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int i; 5409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i = 0; i < info_ptr->pcal_nparams; i++) 542a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->pcal_params[i]); 5439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 544a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->pcal_params); 545a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->pcal_params = NULL; 546a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 547a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->valid &= ~PNG_INFO_pCAL; 548a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 549893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 550893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 5515f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_iCCP_SUPPORTED 552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Free any profile entry */ 5539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (((mask & PNG_FREE_ICCP) & info_ptr->free_me) != 0) 554a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 555a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->iccp_name); 556a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->iccp_profile); 557a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->iccp_name = NULL; 558a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->iccp_profile = NULL; 559a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->valid &= ~PNG_INFO_iCCP; 560a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 561893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 562893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 5635f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_sPLT_SUPPORTED 564a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Free a given sPLT entry, or (if num == -1) all sPLT entries */ 5653cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III if (info_ptr->splt_palettes != NULL && 5669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett ((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0) 567893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 568a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (num != -1) 569893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 5709b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, info_ptr->splt_palettes[num].name); 5719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, info_ptr->splt_palettes[num].entries); 5729b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->splt_palettes[num].name = NULL; 5739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->splt_palettes[num].entries = NULL; 574a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 576a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott else 577a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 5789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int i; 579a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott 5809b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (i = 0; i < info_ptr->splt_palettes_num; i++) 5819b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 5829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, info_ptr->splt_palettes[i].name); 5839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, info_ptr->splt_palettes[i].entries); 584a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 5859b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 5869b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, info_ptr->splt_palettes); 5879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->splt_palettes = NULL; 5889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->splt_palettes_num = 0; 589a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->valid &= ~PNG_INFO_sPLT; 590893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 591893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 592893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 593893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED 5953cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III if (info_ptr->unknown_chunks != NULL && 5969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett ((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0) 597893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 598a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (num != -1) 599a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 6009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, info_ptr->unknown_chunks[num].data); 6019b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->unknown_chunks[num].data = NULL; 602a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 604a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott else 605a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 606a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott int i; 607893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 6089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (i = 0; i < info_ptr->unknown_chunks_num; i++) 6099b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, info_ptr->unknown_chunks[i].data); 610893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 6119b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, info_ptr->unknown_chunks); 6129b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->unknown_chunks = NULL; 6139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->unknown_chunks_num = 0; 614a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 615893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 616893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 617893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 6183cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#ifdef PNG_eXIf_SUPPORTED 6193cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III /* Free any eXIf entry */ 6203cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III if (((mask & PNG_FREE_EXIF) & info_ptr->free_me) != 0) 6213cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III { 6223cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III# ifdef PNG_READ_eXIf_SUPPORTED 6233cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III if (info_ptr->eXIf_buf) 6243cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III { 6253cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III png_free(png_ptr, info_ptr->eXIf_buf); 6263cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III info_ptr->eXIf_buf = NULL; 6273cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III } 6283cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III# endif 6293cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III if (info_ptr->exif) 6303cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III { 6313cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III png_free(png_ptr, info_ptr->exif); 6323cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III info_ptr->exif = NULL; 6333cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III } 6343cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III info_ptr->valid &= ~PNG_INFO_eXIf; 6353cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III } 6363cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#endif 6373cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III 6385f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_hIST_SUPPORTED 639a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Free any hIST entry */ 6409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0) 641a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 642a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->hist); 643a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->hist = NULL; 644a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->valid &= ~PNG_INFO_hIST; 645a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 646893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 647893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 648a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Free any PLTE entry that was internally allocated */ 6499b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (((mask & PNG_FREE_PLTE) & info_ptr->free_me) != 0) 650a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, info_ptr->palette); 652a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->palette = NULL; 653a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->valid &= ~PNG_INFO_PLTE; 654a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->num_palette = 0; 655a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 656893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 6575f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_INFO_IMAGE_SUPPORTED 658a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Free any image bits attached to the info structure */ 6599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0) 660a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 6613cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III if (info_ptr->row_pointers != NULL) 662a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 row; 664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (row = 0; row < info_ptr->height; row++) 665a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->row_pointers[row]); 6669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 667a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_free(png_ptr, info_ptr->row_pointers); 6685f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott info_ptr->row_pointers = NULL; 669a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 670a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->valid &= ~PNG_INFO_IDAT; 671a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 672893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 673893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (num != -1) 675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik mask &= ~PNG_FREE_MUL; 676893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->free_me &= ~mask; 678893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 6799b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ || WRITE */ 680893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 681893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* This function returns a pointer to the io_ptr associated with the user 682893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * functions. The application should free any memory associated with this 683893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * pointer before png_write_destroy() or png_read_destroy() are called. 684893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 685893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_voidp PNGAPI 686b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_get_io_ptr(png_const_structrp png_ptr) 687893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 688a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 689a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return (NULL); 690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 691893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return (png_ptr->io_ptr); 692893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 693893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 694893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) 695b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_STDIO_SUPPORTED 696893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Initialize the default input/output functions for the PNG file. If you 697893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * use your own read or write routines, you can call either png_set_read_fn() 698893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * or png_set_write_fn() instead of png_init_io(). If you have defined 699b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG_NO_STDIO or otherwise disabled PNG_STDIO_SUPPORTED, you must use a 700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * function of your own because "FILE *" isn't necessarily available. 701893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 702893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 703b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_init_io(png_structrp png_ptr, png_FILE_p fp) 704893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 7054215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_init_io"); 7065f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 707a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 708a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 7095f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 710893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->io_ptr = (png_voidp)fp; 711893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 7149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef PNG_SAVE_INT_32_SUPPORTED 7159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett/* PNG signed integers are saved in 32-bit 2's complement format. ANSI C-90 7169b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * defines a cast of a signed integer to an unsigned integer either to preserve 7179b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * the value, if it is positive, or to calculate: 7189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 7199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * (UNSIGNED_MAX+1) + integer 7209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 7219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the 7229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * negative integral value is added the result will be an unsigned value 7239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * correspnding to the 2's complement representation. 724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 725b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 726b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_save_int_32(png_bytep buf, png_int_32 i) 727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 7283cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III png_save_uint_32(buf, (png_uint_32)i); 729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 7309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 731893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_TIME_RFC1123_SUPPORTED 733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Convert the supplied time into an RFC 1123 string suitable for use in 734893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * a "Creation Time" or other text-based time string. 735893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 736b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint PNGAPI 737b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) 738893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 739893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project static PNG_CONST char short_months[12][4] = 740893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project {"Jan", "Feb", "Mar", "Apr", "May", "Jun", 741893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; 742893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (out == NULL) 744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ptime->year > 9999 /* RFC1123 limitation */ || 747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptime->month == 0 || ptime->month > 12 || 748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptime->day == 0 || ptime->day > 31 || 749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptime->hour > 23 || ptime->minute > 59 || 750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptime->second > 60) 751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 752893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 753893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik size_t pos = 0; 755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char number_buf[5]; /* enough for a four-digit year */ 756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string)) 758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define APPEND_NUMBER(format, value)\ 759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value))) 760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define APPEND(ch) if (pos < 28) out[pos++] = (ch) 761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day); 763b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND(' '); 764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND_STRING(short_months[(ptime->month - 1)]); 765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND(' '); 766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND_NUMBER(PNG_NUMBER_FORMAT_u, ptime->year); 767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND(' '); 768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->hour); 769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND(':'); 770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->minute); 771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND(':'); 772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second); 773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik APPEND_STRING(" +0000"); /* This reliably terminates the buffer */ 7749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED (pos) 775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# undef APPEND 777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# undef APPEND_NUMBER 778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# undef APPEND_STRING 779893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 7849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# if PNG_LIBPNG_VER < 10700 785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* To do: remove the following from libpng-1.7 */ 786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Original API that uses a private buffer in png_struct. 787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Deprecated because it causes png_struct to carry a spurious temporary 788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * buffer (png_struct::time_buffer), better to have the caller pass this in. 789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 790b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_const_charp PNGAPI 791b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime) 792b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr != NULL) 794893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The only failure above if png_ptr != NULL is from an invalid ptime */ 7969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime) == 0) 797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Ignoring invalid time value"); 798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_ptr->time_buffer; 801893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return NULL; 804893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 8059b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif /* LIBPNG_VER < 10700 */ 8069b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif /* TIME_RFC1123 */ 807893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 8089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ || WRITE */ 809893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 810b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_const_charp PNGAPI 811b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_get_copyright(png_const_structrp png_ptr) 812893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ 8145f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_STRING_COPYRIGHT 815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return PNG_STRING_COPYRIGHT 8165f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#else 817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef __STDC__ 818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return PNG_STRING_NEWLINE \ 8193cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III "libpng version 1.6.34 - September 29, 2017" PNG_STRING_NEWLINE \ 8203cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III "Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson" \ 821114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett PNG_STRING_NEWLINE \ 8229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ 8239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ 8249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_STRING_NEWLINE; 825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# else 8263cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III return "libpng version 1.6.34 - September 29, 2017\ 8273cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson\ 8285f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott Copyright (c) 1996-1997 Andreas Dilger\ 829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; 830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 8315f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif 832893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 833893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 834893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* The following return the library version as a short string in the 835893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * format 1.0.0 through 99.99.99zz. To get the version of *.h files 836893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * used with your application, print out PNG_LIBPNG_VER_STRING, which 837893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * is defined in png.h. 838893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * Note: now there is no difference between png_get_libpng_ver() and 839893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * png_get_header_ver(). Due to the version_nn_nn_nn typedef guard, 840893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * it is guaranteed that png.c uses the correct version of png.h. 841893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 842b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_const_charp PNGAPI 843b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_get_libpng_ver(png_const_structrp png_ptr) 844893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 845893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Version of *.c files used when building libpng */ 846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_get_header_ver(png_ptr); 847893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 848893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 849b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_const_charp PNGAPI 850b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_get_header_ver(png_const_structrp png_ptr) 851893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 852893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Version of *.h files used when building libpng */ 853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ 854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return PNG_LIBPNG_VER_STRING; 855893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 856893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 857b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_const_charp PNGAPI 858b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_get_header_version(png_const_structrp png_ptr) 859893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 860893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Returns longer string containing both version and date */ 861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */ 8625f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef __STDC__ 863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return PNG_HEADER_VERSION_STRING 864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifndef PNG_READ_SUPPORTED 8659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett " (NO READ SUPPORT)" 866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 8679b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_STRING_NEWLINE; 8685f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#else 869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return PNG_HEADER_VERSION_STRING; 8705f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif 871893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 872893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 873b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED 874b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* NOTE: this routine is not used internally! */ 875b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth 876b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * large of png_color. This lets grayscale images be treated as 877b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * paletted. Most useful for gamma correction and simplification 878b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * of code. This API is not used internally. 879b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 880b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurarivoid PNGAPI 881b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_build_grayscale_palette(int bit_depth, png_colorp palette) 882b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 883b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int num_palette; 884b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int color_inc; 885b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int i; 886b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int v; 887b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 888b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_debug(1, "in png_do_build_grayscale_palette"); 889b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 890b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (palette == NULL) 891b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return; 892b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 893b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari switch (bit_depth) 894b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 895b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case 1: 896b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari num_palette = 2; 897b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari color_inc = 0xff; 898b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 899b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 900b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case 2: 901b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari num_palette = 4; 902b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari color_inc = 0x55; 903b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 904b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 905b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case 4: 906b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari num_palette = 16; 907b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari color_inc = 0x11; 908b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 909b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 910b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case 8: 911b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari num_palette = 256; 912b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari color_inc = 1; 913b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 914b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 915b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari default: 916b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari num_palette = 0; 917b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari color_inc = 0; 918b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 919b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 920b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 921b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (i = 0, v = 0; i < num_palette; i++, v += color_inc) 922b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 9239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett palette[i].red = (png_byte)(v & 0xff); 9249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett palette[i].green = (png_byte)(v & 0xff); 9259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett palette[i].blue = (png_byte)(v & 0xff); 926b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 927b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 928b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif 929b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED 931893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectint PNGAPI 932b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name) 933893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 934a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Check chunk_name and return "keep" value if it's on the list, else 0 */ 935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep p, p_end; 936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0) 938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return PNG_HANDLE_CHUNK_AS_DEFAULT; 939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 940b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p_end = png_ptr->chunk_list; 941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p = p_end + png_ptr->num_chunk_list*5; /* beyond end */ 942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The code is the fifth byte after each four byte string. Historically this 944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * code was always searched from the end of the list, this is no longer 945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * necessary because the 'set' routine handles duplicate entries correcty. 946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do /* num_chunk_list > 0, so at least one */ 948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik p -= 5; 950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9519b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (memcmp(chunk_name, p, 4) == 0) 952b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return p[4]; 953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (p > p_end); 955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This means that known chunks should be processed and unknown chunks should 957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be handled according to the value of png_ptr->unknown_default; this can be 958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * confusing because, as a result, there are two levels of defaulting for 959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * unknown chunks. 960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return PNG_HANDLE_CHUNK_AS_DEFAULT; 962893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 963893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 964b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\ 965b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED) 966b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint /* PRIVATE */ 967b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name) 968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte chunk_string[5]; 970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name); 972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_handle_as_unknown(png_ptr, chunk_string); 973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 974b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */ 975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* SET_UNKNOWN_CHUNKS */ 976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_SUPPORTED 978893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* This function, added to libpng-1.0.6g, is untested. */ 979893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectint PNGAPI 980b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_reset_zstream(png_structrp png_ptr) 981893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 982a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 983a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return Z_STREAM_ERROR; 984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 985b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* WARNING: this resets the window bits to the maximum! */ 986893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return (inflateReset(&png_ptr->zstream)); 987893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 9889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ */ 989893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 990893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* This function was added to libpng-1.0.7 */ 991893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_uint_32 PNGAPI 992893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_access_version_number(void) 993893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 994893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Version of *.c files used when building libpng */ 995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return((png_uint_32)PNG_LIBPNG_VER); 996893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 997893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 998893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) 999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Ensure that png_ptr->zstream.msg holds some appropriate error message string. 1000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * If it doesn't 'ret' is used to set it to something appropriate, even in cases 1001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * like Z_OK or Z_STREAM_END where the error code is apparently a success code. 1002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1003b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 1004b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_zstream_error(png_structrp png_ptr, int ret) 1005893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Translate 'ret' into an appropriate error string, priority is given to the 1007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * one in zstream if set. This always returns a string, even in cases like 1008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Z_OK or Z_STREAM_END where the error code is a success code. 1009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->zstream.msg == NULL) switch (ret) 1011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 1013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case Z_OK: 1014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code"); 1015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 10164215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project 1017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case Z_STREAM_END: 1018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Normal exit */ 1019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream"); 1020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1021a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott 1022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case Z_NEED_DICT: 1023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This means the deflate stream did not have a dictionary; this 1024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * indicates a bogus PNG. 1025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary"); 1027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1028a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott 1029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case Z_ERRNO: 1030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* gz APIs only: should not happen */ 1031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error"); 1032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 10334215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project 1034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case Z_STREAM_ERROR: 1035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* internal libpng error */ 1036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib"); 1037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 10385f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case Z_DATA_ERROR: 1040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream"); 1041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 10424215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project 1043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case Z_MEM_ERROR: 1044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory"); 1045b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 10464215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project 1047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case Z_BUF_ERROR: 1048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* End of input or output; not a problem if the caller is doing 1049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * incremental read or write. 1050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated"); 1052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 10534215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project 1054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case Z_VERSION_ERROR: 1055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version"); 1056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 10574215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project 1058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_UNEXPECTED_ZLIB_RETURN: 1059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Compile errors here mean that zlib now uses the value co-opted in 1060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pngpriv.h for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above 1061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * and change pngpriv.h. Note that this message is "... return", 1062b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * whereas the default/Z_OK one is "... return code". 1063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return"); 1065b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 10674215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project} 10685f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1069b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* png_convert_size: a PNGAPI but no longer in png.h, so deleted 1070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * at libpng 1.5.5! 1071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1073b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */ 1074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */ 1075b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1076b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_check_gamma(png_const_structrp png_ptr, 10777a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_colorspacerp colorspace, png_fixed_point gAMA, int from) 1078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is called to check a new gamma value against an existing one. The 1079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * routine returns false if the new gamma value should not be written. 1080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1081b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 'from' says where the new gamma value comes from: 1082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 0: the new gamma value is the libpng estimate for an ICC profile 1084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1: the new gamma value comes from a gAMA chunk 1085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2: the new gamma value comes from an sRGB chunk 1086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 10875f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott{ 1088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point gtest; 1089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 && 10917a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis (png_muldiv(>est, colorspace->gamma, PNG_FP_1, gAMA) == 0 || 10929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_gamma_significant(gtest) != 0)) 1093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Either this is an sRGB image, in which case the calculated gamma 1095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * approximation should match, or this is an image with a profile and the 1096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value libpng calculates for the gamma of the profile does not match the 1097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value recorded in the file. The former, sRGB, case is an error, the 1098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * latter is just a warning. 1099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2) 1101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_chunk_report(png_ptr, "gamma value does not match sRGB", 11037a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_CHUNK_ERROR); 1104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Do not overwrite an sRGB value */ 1105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return from == 2; 1106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* sRGB tag not involved */ 1109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_chunk_report(png_ptr, "gamma value does not match libpng estimate", 11117a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_CHUNK_WARNING); 1112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return from == 1; 1113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1119b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 1120b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_set_gamma(png_const_structrp png_ptr, 11217a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_colorspacerp colorspace, png_fixed_point gAMA) 1122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't 11249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * occur. Since the fixed point representation is asymetrical it is 1125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * possible for 1/gamma to overflow the limit of 21474 and this means the 1126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * gamma value must be at least 5/100000 and hence at most 20000.0. For 1127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * safety the limits here are a little narrower. The values are 0.00016 to 1128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 6250.0, which are truly ridiculous gamma values (and will produce 1129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * displays that are all black or all white.) 1130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk 1132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * handling code, which only required the value to be >0. 1133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_charp errmsg; 1135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (gAMA < 16 || gAMA > 625000000) 1137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik errmsg = "gamma value out of range"; 1138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_READ_gAMA_SUPPORTED 11409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Allow the application to set the gamma value more than once */ 11419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && 11429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0) 11439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett errmsg = "duplicate"; 1144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 1145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Do nothing if the colorspace is already invalid */ 11479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) 1148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 11529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA, 11539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 1/*from gAMA*/) != 0) 1154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Store this gamma value. */ 1156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->gamma = gAMA; 1157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= 1158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA); 1159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* At present if the check_gamma test fails the gamma of the colorspace is 1162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * not updated however the colorspace is not invalidated. This 1163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * corresponds to the case where the existing gamma comes from an sRGB 1164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * chunk or profile. An error message has already been output. 1165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Error exit - errmsg has been set. */ 1170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= PNG_COLORSPACE_INVALID; 1171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR); 1172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1174b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 1175b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr) 1176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 11779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0) 1178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Everything is invalid */ 1180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB| 1181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_INFO_iCCP); 1182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_COLORSPACE_SUPPORTED 11849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Clean up the iCCP profile now if it won't be used. */ 11859b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/); 1186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# else 11879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(png_ptr) 1188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 1189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_COLORSPACE_SUPPORTED 11949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Leave the INFO_iCCP flag set if the pngset.c code has already set 11959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * it; this allows a PNG to contain a profile which matches sRGB and 11969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * yet still have that profile retrievable by the application. 11979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett */ 11989b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) != 0) 11999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->valid |= PNG_INFO_sRGB; 1200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 12019b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else 12029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->valid &= ~PNG_INFO_sRGB; 1203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 12049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) 12059b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->valid |= PNG_INFO_cHRM; 1206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 12079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else 12089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->valid &= ~PNG_INFO_cHRM; 1209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 1210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 12119b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0) 1212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->valid |= PNG_INFO_gAMA; 1213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->valid &= ~PNG_INFO_gAMA; 1216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_SUPPORTED 1220b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 1221b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr) 1222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (info_ptr == NULL) /* reduce code size; check here not in the caller */ 1224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->colorspace = png_ptr->colorspace; 1227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_colorspace_sync_info(png_ptr, info_ptr); 1228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 12309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* GAMMA */ 1231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_COLORSPACE_SUPPORTED 1233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for 1234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * cHRM, as opposed to using chromaticities. These internal APIs return 1235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * non-zero on a parameter error. The X, Y and Z values are required to be 1236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * positive and less than 1.0. 1237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1238b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1239b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ) 1240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_int_32 d, dwhite, whiteX, whiteY; 1242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z; 12449b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0) 12459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 12469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0) 12479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 1248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik dwhite = d; 1249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik whiteX = XYZ->red_X; 1250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik whiteY = XYZ->red_Y; 1251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z; 12539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0) 12549b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 12559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0) 12569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 1257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik dwhite += d; 1258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik whiteX += XYZ->green_X; 1259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik whiteY += XYZ->green_Y; 1260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z; 12629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0) 12639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 12649b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0) 12659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 1266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik dwhite += d; 1267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik whiteX += XYZ->blue_X; 1268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik whiteY += XYZ->blue_Y; 1269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The reference white is simply the sum of the end-point (X,Y,Z) vectors, 1271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * thus: 1272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 12739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0) 12749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 12759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0) 12769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 1277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1281b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1282b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) 1283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point red_inverse, green_inverse, blue_scale; 1285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point left, right, denominator; 1286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check xy and, implicitly, z. Note that wide gamut color spaces typically 1288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * have end points with 0 tristimulus values (these are impossible end 1289ee604d7c8d1b52e83c0fde589eb76973b0e06304Christopher Ferris * points, but they are used to cover the possible colors). We check 1290ee604d7c8d1b52e83c0fde589eb76973b0e06304Christopher Ferris * xy->whitey against 5, not 0, to avoid a possible integer overflow. 1291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1292ee604d7c8d1b52e83c0fde589eb76973b0e06304Christopher Ferris if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1; 1293ee604d7c8d1b52e83c0fde589eb76973b0e06304Christopher Ferris if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1; 1294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1; 1295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1; 1296ee604d7c8d1b52e83c0fde589eb76973b0e06304Christopher Ferris if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1; 1297ee604d7c8d1b52e83c0fde589eb76973b0e06304Christopher Ferris if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1; 1298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1; 1299ee604d7c8d1b52e83c0fde589eb76973b0e06304Christopher Ferris if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1; 1300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The reverse calculation is more difficult because the original tristimulus 1302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8 1303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * derived values were recorded in the cHRM chunk; 1304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (red,green,blue,white)x(x,y). This loses one degree of freedom and 1305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * therefore an arbitrary ninth value has to be introduced to undo the 1306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * original transformations. 1307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Think of the original end-points as points in (X,Y,Z) space. The 1309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * chromaticity values (c) have the property: 1310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * C 1312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * c = --------- 1313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * X + Y + Z 1314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * For each c (x,y,z) from the corresponding original C (X,Y,Z). Thus the 1316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * three chromaticity values (x,y,z) for each end-point obey the 1317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * relationship: 1318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * x + y + z = 1 1320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This describes the plane in (X,Y,Z) space that intersects each axis at the 1322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value 1.0; call this the chromaticity plane. Thus the chromaticity 1323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * calculation has scaled each end-point so that it is on the x+y+z=1 plane 1324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * and chromaticity is the intersection of the vector from the origin to the 1325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (X,Y,Z) value with the chromaticity plane. 1326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * To fully invert the chromaticity calculation we would need the three 1328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * end-point scale factors, (red-scale, green-scale, blue-scale), but these 1329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * were not recorded. Instead we calculated the reference white (X,Y,Z) and 1330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * recorded the chromaticity of this. The reference white (X,Y,Z) would have 1331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * given all three of the scale factors since: 1332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * color-C = color-c * color-scale 1334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * white-C = red-C + green-C + blue-C 1335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale 1336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * But cHRM records only white-x and white-y, so we have lost the white scale 1338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * factor: 1339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * white-C = white-c*white-scale 1341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * To handle this the inverse transformation makes an arbitrary assumption 1343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * about white-scale: 1344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Assume: white-Y = 1.0 1346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Hence: white-scale = 1/white-y 1347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Or: red-Y + green-Y + blue-Y = 1.0 1348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Notice the last statement of the assumption gives an equation in three of 1350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the nine values we want to calculate. 8 more equations come from the 1351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * above routine as summarised at the top above (the chromaticity 1352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * calculation): 1353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Given: color-x = color-X / (color-X + color-Y + color-Z) 1355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Hence: (color-x - 1)*color-X + color.x*color-Y + color.x*color-Z = 0 1356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This is 9 simultaneous equations in the 9 variables "color-C" and can be 1358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * solved by Cramer's rule. Cramer's rule requires calculating 10 9x9 matrix 1359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * determinants, however this is not as bad as it seems because only 28 of 1360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the total of 90 terms in the various matrices are non-zero. Nevertheless 1361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Cramer's rule is notoriously numerically unstable because the determinant 1362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * calculation involves the difference of large, but similar, numbers. It is 1363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * difficult to be sure that the calculation is stable for real world values 1364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * and it is certain that it becomes unstable where the end points are close 1365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * together. 1366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * So this code uses the perhaps slightly less optimal but more 1368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * understandable and totally obvious approach of calculating color-scale. 1369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This algorithm depends on the precision in white-scale and that is 1371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (1/white-y), so we can immediately see that as white-y approaches 0 the 1372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * accuracy inherent in the cHRM chunk drops off substantially. 1373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 13749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * libpng arithmetic: a simple inversion of the above equations 1375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ------------------------------------------------------------ 1376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * white_scale = 1/white-y 1378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * white-X = white-x * white-scale 1379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * white-Y = 1.0 1380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * white-Z = (1 - white-x - white-y) * white_scale 1381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * white-C = red-C + green-C + blue-C 1383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * = red-c*red-scale + green-c*green-scale + blue-c*blue-scale 1384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This gives us three equations in (red-scale,green-scale,blue-scale) where 1386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * all the coefficients are now known: 1387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * red-x*red-scale + green-x*green-scale + blue-x*blue-scale 1389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * = white-x/white-y 1390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * red-y*red-scale + green-y*green-scale + blue-y*blue-scale = 1 1391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * red-z*red-scale + green-z*green-scale + blue-z*blue-scale 1392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * = (1 - white-x - white-y)/white-y 1393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * In the last equation color-z is (1 - color-x - color-y) so we can add all 1395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * three equations together to get an alternative third: 1396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * red-scale + green-scale + blue-scale = 1/white-y = white-scale 1398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * So now we have a Cramer's rule solution where the determinants are just 1400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3x3 - far more tractible. Unfortunately 3x3 determinants still involve 1401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * multiplication of three coefficients so we can't guarantee to avoid 1402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * overflow in the libpng fixed point representation. Using Cramer's rule in 1403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * floating point is probably a good choice here, but it's not an option for 1404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * fixed point. Instead proceed to simplify the first two equations by 1405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * eliminating what is likely to be the largest value, blue-scale: 1406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * blue-scale = white-scale - red-scale - green-scale 1408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Hence: 1410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (red-x - blue-x)*red-scale + (green-x - blue-x)*green-scale = 1412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (white-x - blue-x)*white-scale 1413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (red-y - blue-y)*red-scale + (green-y - blue-y)*green-scale = 1415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1 - blue-y*white-scale 1416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * And now we can trivially solve for (red-scale,green-scale): 1418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * green-scale = 1420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (white-x - blue-x)*white-scale - (red-x - blue-x)*red-scale 1421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ----------------------------------------------------------- 1422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * green-x - blue-x 1423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * red-scale = 1425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1 - blue-y*white-scale - (green-y - blue-y) * green-scale 1426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * --------------------------------------------------------- 1427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * red-y - blue-y 1428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Hence: 1430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * red-scale = 1432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ( (green-x - blue-x) * (white-y - blue-y) - 1433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (green-y - blue-y) * (white-x - blue-x) ) / white-y 1434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ------------------------------------------------------------------------- 1435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) 1436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * green-scale = 1438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ( (red-y - blue-y) * (white-x - blue-x) - 1439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (red-x - blue-x) * (white-y - blue-y) ) / white-y 1440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ------------------------------------------------------------------------- 1441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (green-x - blue-x)*(red-y - blue-y)-(green-y - blue-y)*(red-x - blue-x) 1442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Accuracy: 1444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The input values have 5 decimal digits of accuracy. The values are all in 1445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the range 0 < value < 1, so simple products are in the same range but may 1446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * need up to 10 decimal digits to preserve the original precision and avoid 1447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * underflow. Because we are using a 32-bit signed representation we cannot 1448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * match this; the best is a little over 9 decimal digits, less than 10. 1449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The approach used here is to preserve the maximum precision within the 1451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * signed representation. Because the red-scale calculation above uses the 1452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * difference between two products of values that must be in the range -1..+1 1453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it is sufficient to divide the product by 7; ceil(100,000/32767*2). The 1454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * factor is irrelevant in the calculation because it is applied to both 1455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * numerator and denominator. 1456b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Note that the values of the differences of the products of the 1458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * chromaticities in the above equations tend to be small, for example for 1459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the sRGB chromaticities they are: 1460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * red numerator: -0.04751 1462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * green numerator: -0.08788 1463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * denominator: -0.2241 (without white-y multiplication) 1464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The resultant Y coefficients from the chromaticities of some widely used 1466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * color space definitions are (to 15 decimal places): 1467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * sRGB 1469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 0.212639005871510 0.715168678767756 0.072192315360734 1470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Kodak ProPhoto 1471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 0.288071128229293 0.711843217810102 0.000085653960605 1472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Adobe RGB 1473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 0.297344975250536 0.627363566255466 0.075291458493998 1474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Adobe Wide Gamut RGB 1475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 0.258728243040113 0.724682314948566 0.016589442011321 1476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* By the argument, above overflow should be impossible here. The return 1478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value of 2 indicates an internal error to the caller. 1479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 14809b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0) 1481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 2; 14829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0) 1483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 2; 1484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik denominator = left - right; 1485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now find the red numerator. */ 14879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0) 1488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 2; 14899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0) 1490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 2; 1491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Overflow is possible here and it indicates an extreme set of PNG cHRM 1493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * chunk values. This calculation actually returns the reciprocal of the 1494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * scale value because this allows us to delay the multiplication of white-y 1495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * into the denominator, which tends to produce a small number. 1496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 14979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 || 1498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik red_inverse <= xy->whitey /* r+g+b scales = white scale */) 1499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Similarly for green_inverse: */ 15029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0) 1503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 2; 15049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0) 1505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 2; 15069b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 || 1507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik green_inverse <= xy->whitey) 1508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And the blue scale, the checks above guarantee this can't overflow but it 1511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * can still produce 0 for extreme cHRM values. 1512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) - 15149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_reciprocal(green_inverse); 15159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (blue_scale <= 0) 15169b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 1517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And fill in the png_XYZ: */ 15209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0) 15219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 15229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0) 15239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 15249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1, 15259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett red_inverse) == 0) 1526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 15289b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse) == 0) 1529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 15309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse) == 0) 1531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 15329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1, 15339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett green_inverse) == 0) 1534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 15369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1) == 0) 15379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 15389b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1) == 0) 15399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 15409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale, 15419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_FP_1) == 0) 1542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; /*success*/ 1545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1547b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1548b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_XYZ_normalize(png_XYZ *XYZ) 1549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_int_32 Y; 1551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 || 1553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 || 1554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0) 1555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. 1558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore 1559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * relying on addition of two positive values producing a negative one is not 1560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * safe. 1561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Y = XYZ->red_Y; 15639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (0x7fffffff - Y < XYZ->green_X) 15649b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 1565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Y += XYZ->green_Y; 15669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (0x7fffffff - Y < XYZ->blue_X) 15679b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 1568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik Y += XYZ->blue_Y; 1569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (Y != PNG_FP_1) 1571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 15729b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y) == 0) 15739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 15749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y) == 0) 15759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 15769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y) == 0) 15779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 1578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 15799b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y) == 0) 15809b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 15819b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y) == 0) 15829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 15839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y) == 0) 15849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 1585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 15869b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y) == 0) 15879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 15889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y) == 0) 15899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 15909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y) == 0) 15919b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 1592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1597b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1598b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta) 1599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Allow an error of +/-0.01 (absolute value) on each chromaticity */ 16019b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) || 16029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) || 16039b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) || 16049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) || 16059b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) || 16069b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) || 16079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) || 16089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta)) 16099b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 0; 16109b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 1; 1611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM 1614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * chunk chromaticities. Earlier checks used to simply look for the overflow 1615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * condition (where the determinant of the matrix to solve for XYZ ends up zero 1616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * because the chromaticity values are not all distinct.) Despite this it is 1617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * theoretically possible to produce chromaticities that are apparently valid 1618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * but that rapidly degrade to invalid, potentially crashing, sets because of 1619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * arithmetic inaccuracies when calculations are performed on them. The new 1620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * check is to round-trip xy -> XYZ -> xy and then check that the result is 1621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * within a small percentage of the original. 1622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1623b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1624b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy) 1625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result; 1627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_xy xy_test; 1628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* As a side-effect this routine also returns the XYZ endpoints. */ 1630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = png_XYZ_from_xy(XYZ, xy); 16319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (result != 0) 16329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return result; 1633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = png_xy_from_XYZ(&xy_test, XYZ); 16359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (result != 0) 16369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return result; 1637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_colorspace_endpoints_match(xy, &xy_test, 16399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 5/*actually, the math is pretty accurate*/) != 0) 1640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Too much slip */ 1643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* This is the check going the other way. The XYZ is modified to normalize it 1647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (another side-effect) and the xy chromaticities are returned. 1648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1649b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1650b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ) 1651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result; 1653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_XYZ XYZtemp; 1654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = png_XYZ_normalize(XYZ); 16569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (result != 0) 16579b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return result; 1658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = png_xy_from_XYZ(xy, XYZ); 16609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (result != 0) 16619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return result; 1662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik XYZtemp = *XYZ; 1664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_colorspace_check_xy(&XYZtemp, xy); 1665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Used to check for an endpoint match against sRGB */ 1668b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic const png_xy sRGB_xy = /* From ITU-R BT.709-3 */ 1669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* color x y */ 1671b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* red */ 64000, 33000, 1672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* green */ 30000, 60000, 1673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* blue */ 15000, 6000, 1674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* white */ 31270, 32900 1675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 1676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1677b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1678b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr, 16797a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ, 16807a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis int preferred) 1681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 16829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) 1683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The consistency check is performed on the chromaticities; this factors out 1686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * variations because of the normalization (or not) of the end point Y 1687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * values. 1688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 16899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (preferred < 2 && 16909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) 1691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The end points must be reasonably close to any we already have. The 1693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * following allows an error of up to +/-.001 1694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 16959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_colorspace_endpoints_match(xy, &colorspace->end_points_xy, 16969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 100) == 0) 1697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1698b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= PNG_COLORSPACE_INVALID; 1699b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_benign_error(png_ptr, "inconsistent chromaticities"); 1700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; /* failed */ 1701b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1702b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Only overwrite with preferred values */ 17049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (preferred == 0) 1705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; /* ok, but no change */ 1706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->end_points_xy = *xy; 1709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->end_points_XYZ = *XYZ; 1710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS; 1711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The end points are normally quoted to two decimal digits, so allow +/-0.01 1713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * on this test. 1714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 17159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000) != 0) 1716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB; 1717b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags &= PNG_COLORSPACE_CANCEL( 1720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB); 1721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 2; /* ok and changed */ 1723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1725b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint /* PRIVATE */ 1726b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_set_chromaticities(png_const_structrp png_ptr, 17277a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_colorspacerp colorspace, const png_xy *xy, int preferred) 1728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We must check the end points to ensure they are reasonable - in the past 1730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * color management systems have crashed as a result of getting bogus 1731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * colorant values, while this isn't the fault of libpng it is the 1732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * responsibility of libpng because PNG carries the bomb and libpng is in a 1733b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * position to protect against it. 1734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_XYZ XYZ; 1736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (png_colorspace_check_xy(&XYZ, xy)) 1738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 0: /* success */ 1740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ, 17417a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis preferred); 1742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 1: 1744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We can't invert the chromaticities so we can't produce value XYZ 1745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * values. Likely as not a color management system will fail too. 1746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= PNG_COLORSPACE_INVALID; 1748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_benign_error(png_ptr, "invalid chromaticities"); 1749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 1752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* libpng is broken; this should be a warning but if it happens we 1753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * want error reports so for the moment it is an error. 1754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= PNG_COLORSPACE_INVALID; 1756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "internal error checking chromaticities"); 1757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; /* failed */ 1760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1762b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint /* PRIVATE */ 1763b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_set_endpoints(png_const_structrp png_ptr, 17647a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred) 1765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_XYZ XYZ = *XYZ_in; 1767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_xy xy; 1768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (png_colorspace_check_XYZ(&xy, &XYZ)) 1770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 0: 1772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ, 17737a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis preferred); 1774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 1: 1776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* End points are invalid. */ 1777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= PNG_COLORSPACE_INVALID; 1778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_benign_error(png_ptr, "invalid end points"); 1779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 1782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= PNG_COLORSPACE_INVALID; 1783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "internal error checking chromaticities"); 1784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; /* failed */ 1787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED) 1790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Error message generation */ 1791b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic char 1792b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_icc_tag_char(png_uint_32 byte) 1793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1794b50c217251b086440efcdb273c22f86a06c80cbaChris Craik byte &= 0xff; 1795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (byte >= 32 && byte <= 126) 1796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (char)byte; 1797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return '?'; 1799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1801b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1802b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_icc_tag_name(char *name, png_uint_32 tag) 1803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik name[0] = '\''; 1805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik name[1] = png_icc_tag_char(tag >> 24); 1806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik name[2] = png_icc_tag_char(tag >> 16); 1807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik name[3] = png_icc_tag_char(tag >> 8); 1808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik name[4] = png_icc_tag_char(tag ); 1809b50c217251b086440efcdb273c22f86a06c80cbaChris Craik name[5] = '\''; 1810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1812b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1813b50c217251b086440efcdb273c22f86a06c80cbaChris Craikis_ICC_signature_char(png_alloc_size_t it) 1814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) || 1816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (it >= 97 && it <= 122); 1817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1819b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic int 1820b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurariis_ICC_signature(png_alloc_size_t it) 1821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return is_ICC_signature_char(it >> 24) /* checks all the top bits */ && 1823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik is_ICC_signature_char((it >> 16) & 0xff) && 1824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik is_ICC_signature_char((it >> 8) & 0xff) && 1825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik is_ICC_signature_char(it & 0xff); 1826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1828b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1829b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace, 18307a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_const_charp name, png_alloc_size_t value, png_const_charp reason) 1831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik size_t pos; 1833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char message[196]; /* see below for calculation */ 1834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (colorspace != NULL) 1836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= PNG_COLORSPACE_INVALID; 1837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */ 1839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */ 1840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */ 18419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (is_ICC_signature(value) != 0) 1842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* So 'value' is at most 4 bytes and the following cast is safe */ 1844b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_icc_tag_name(message+pos, (png_uint_32)value); 1845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pos += 6; /* total +8; less than the else clause */ 1846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik message[pos++] = ':'; 1847b50c217251b086440efcdb273c22f86a06c80cbaChris Craik message[pos++] = ' '; 1848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_WARNINGS_SUPPORTED 1850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/ 1853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pos = png_safecat(message, (sizeof message), pos, 18557a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_format_number(number, number+(sizeof number), 18567a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_NUMBER_FORMAT_x, value)); 1857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/ 1858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 1860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The 'reason' is an arbitrary message, allow +79 maximum 195 */ 1861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pos = png_safecat(message, (sizeof message), pos, reason); 1862b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari PNG_UNUSED(pos) 1863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is recoverable, but make it unconditionally an app_error on write to 18659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * avoid writing invalid ICC profiles into PNG files (i.e., we handle them 1866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * on read, with a warning, but on write unless the app turns off 1867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * application errors the PNG won't be written.) 1868b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_chunk_report(png_ptr, message, 18707a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR); 1871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* sRGB || iCCP */ 1875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_sRGB_SUPPORTED 1877b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint /* PRIVATE */ 1878b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace, 18797a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis int intent) 1880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* sRGB sets known gamma, end points and (from the chunk) intent. */ 1882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* IMPORTANT: these are not necessarily the values found in an ICC profile 1883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * because ICC profiles store values adapted to a D50 environment; it is 18849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * expected that the ICC profile mediaWhitePointTag will be D50; see the 1885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * checks and code elsewhere to understand this better. 1886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * These XYZ values, which are accurate to 5dp, produce rgb to gray 1888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * coefficients of (6968,23435,2366), which are reduced (because they add up 1889b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to 32769 not 32768) to (6968,23434,2366). These are the values that 1890b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * libpng has traditionally used (and are the best values given the 15bit 1891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * algorithm used by the rgb to gray code.) 1892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */ 1894b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* color X Y Z */ 1896b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* red */ 41239, 21264, 1933, 1897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* green */ 35758, 71517, 11919, 1898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* blue */ 18048, 7219, 95053 1899b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }; 1900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1901b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Do nothing if the colorspace is already invalidated. */ 19029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) 1903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1905b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check the intent, then check for existing settings. It is valid for the 1906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must 1907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be consistent with the correct values. If, however, this function is 1908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * called below because an iCCP chunk matches sRGB then it is quite 1909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * conceivable that an older app recorded incorrect gAMA and cHRM because of 1910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * an incorrect calculation based on the values in the profile - this does 1911b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * *not* invalidate the profile (though it still produces an error, which can 1912b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be ignored.) 1913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST) 1915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, "sRGB", 19163cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III (png_alloc_size_t)intent, "invalid sRGB rendering intent"); 1917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 && 19197a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis colorspace->rendering_intent != intent) 1920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, "sRGB", 19213cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III (png_alloc_size_t)intent, "inconsistent rendering intents"); 1922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1923b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0) 1924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_benign_error(png_ptr, "duplicate sRGB information ignored"); 1926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1927b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1929b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If the standard sRGB cHRM chunk does not match the one from the PNG file 1930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * warn but overwrite the value with the correct one. 1931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 && 19337a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy, 19347a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 100)) 1935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_chunk_report(png_ptr, "cHRM chunk does not match sRGB", 1936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_CHUNK_ERROR); 1937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This check is just done for the error reporting - the routine always 1939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * returns true when the 'from' argument corresponds to sRGB (2). 1940b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE, 19427a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 2/*from sRGB*/); 1943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* intent: bugs in GCC force 'int' to be used as the parameter type. */ 1945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->rendering_intent = (png_uint_16)intent; 1946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT; 1947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* endpoints */ 1949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->end_points_xy = sRGB_xy; 1950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->end_points_XYZ = sRGB_XYZ; 1951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= 1952b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB); 1953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* gamma */ 1955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->gamma = PNG_GAMMA_sRGB_INVERSE; 1956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA; 1957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Finally record that we have an sRGB profile */ 1959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colorspace->flags |= 1960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB); 1961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; /* set */ 1963b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* sRGB */ 1965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_iCCP_SUPPORTED 1967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Encoded value of D50 as an ICC XYZNumber. From the ICC 2010 spec the value 1968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is XYZ(0.9642,1.0,0.8249), which scales to: 1969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (63189.8112, 65536, 54060.6464) 1971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1972b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic const png_byte D50_nCIEXYZ[12] = 1973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d }; 1974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 19757a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidisstatic int /* bool */ 19767a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidisicc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, 19777a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_const_charp name, png_uint_32 profile_length) 1978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (profile_length < 132) 1980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, name, profile_length, 19817a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "too short"); 1982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 19857a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#ifdef PNG_READ_iCCP_SUPPORTED 19867a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidisint /* PRIVATE */ 19877a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidispng_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace, 19887a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_const_charp name, png_uint_32 profile_length) 19897a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis{ 19907a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (!icc_check_length(png_ptr, colorspace, name, profile_length)) 19917a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis return 0; 19927a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 19937a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* This needs to be here because the 'normal' check is in 19947a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * png_decompress_chunk, yet this happens after the attempt to 19957a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * png_malloc_base the required data. We only need this on read; on write 19967a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * the caller supplies the profile buffer so libpng doesn't allocate it. See 19977a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * the call to icc_check_length below (the write case). 19987a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis */ 19997a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis# ifdef PNG_SET_USER_LIMITS_SUPPORTED 20007a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis else if (png_ptr->user_chunk_malloc_max > 0 && 20017a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->user_chunk_malloc_max < profile_length) 20027a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis return png_icc_profile_error(png_ptr, colorspace, name, profile_length, 20037a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "exceeds application limits"); 20047a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis# elif PNG_USER_CHUNK_MALLOC_MAX > 0 20057a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis else if (PNG_USER_CHUNK_MALLOC_MAX < profile_length) 20067a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis return png_icc_profile_error(png_ptr, colorspace, name, profile_length, 20077a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "exceeds libpng limits"); 20087a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis# else /* !SET_USER_LIMITS */ 20097a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* This will get compiled out on all 32-bit and better systems. */ 20107a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis else if (PNG_SIZE_MAX < profile_length) 20117a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis return png_icc_profile_error(png_ptr, colorspace, name, profile_length, 20127a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "exceeds system limits"); 20137a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis# endif /* !SET_USER_LIMITS */ 20147a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 20157a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis return 1; 20167a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis} 20177a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif /* READ_iCCP */ 20187a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 2019b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint /* PRIVATE */ 2020b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, 20217a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_const_charp name, png_uint_32 profile_length, 20227a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_const_bytep profile/* first 132 bytes only */, int color_type) 2023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 temp; 2025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Length check; this cannot be ignored in this code because profile_length 2027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is used later to check the tag table, so even if the profile seems over 2028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * long profile_length from the caller must be correct. The caller can fix 2029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this up on read or write by just passing in the profile header length. 2030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik temp = png_get_uint_32(profile); 2032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (temp != profile_length) 2033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, name, temp, 20347a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "length does not match profile"); 2035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett temp = (png_uint_32) (*(profile+8)); 20379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (temp > 3 && (profile_length & 3)) 20389b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return png_icc_profile_error(png_ptr, colorspace, name, profile_length, 20397a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "invalid length"); 20409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 2041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */ 2042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */ 2043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik profile_length < 132+12*temp) /* truncated tag table */ 2044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, name, temp, 20457a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "tag count too large"); 2046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The 'intent' must be valid or we can't store it, ICC limits the intent to 2048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16 bits. 2049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik temp = png_get_uint_32(profile+64); 2051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (temp >= 0xffff) /* The ICC limit */ 2052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, name, temp, 20537a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "invalid rendering intent"); 2054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is just a warning because the profile may be valid in future 2056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * versions. 2057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (temp >= PNG_sRGB_INTENT_LAST) 2059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)png_icc_profile_error(png_ptr, NULL, name, temp, 20607a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "intent outside defined range"); 2061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2062b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* At this point the tag table can't be checked because it hasn't necessarily 2063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * been loaded; however, various header fields can be checked. These checks 2064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * are for values permitted by the PNG spec in an ICC profile; the PNG spec 2065b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * restricts the profiles that can be passed in an iCCP chunk (they must be 2066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * appropriate to processing PNG data!) 2067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2069b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Data checks (could be skipped). These checks must be independent of the 2070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * version number; however, the version number doesn't accomodate changes in 2071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the header fields (just the known tags and the interpretation of the 2072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * data.) 2073b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik temp = png_get_uint_32(profile+36); /* signature 'ascp' */ 2075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (temp != 0x61637370) 2076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, name, temp, 20777a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "invalid signature"); 2078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Currently the PCS illuminant/adopted white point (the computational 2080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * white point) are required to be D50, 2081b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * however the profile contains a record of the illuminant so perhaps ICC 2082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * expects to be able to change this in the future (despite the rationale in 2083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the introduction for using a fixed PCS adopted white.) Consequently the 2084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * following is just a warning. 2085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0) 2087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/, 20887a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "PCS illuminant is not D50"); 2089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The PNG spec requires this: 2091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * "If the iCCP chunk is present, the image samples conform to the colour 2092b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * space represented by the embedded ICC profile as defined by the 2093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * International Color Consortium [ICC]. The colour space of the ICC profile 2094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * shall be an RGB colour space for colour images (PNG colour types 2, 3, and 2095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 6), or a greyscale colour space for greyscale images (PNG colour types 0 2096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * and 4)." 2097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This checking code ensures the embedded profile (on either read or write) 2099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * conforms to the specification requirements. Notice that an ICC 'gray' 2100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * color-space profile contains the information to transform the monochrome 2101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * data to XYZ or L*a*b (according to which PCS the profile uses) and this 2102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * should be used in preference to the standard libpng K channel replication 2103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * into R, G and B channels. 2104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Previously it was suggested that an RGB profile on grayscale data could be 2106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * handled. However it it is clear that using an RGB profile in this context 2107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * must be an error - there is no specification of what it means. Thus it is 2108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * almost certainly more correct to ignore the profile. 2109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik temp = png_get_uint_32(profile+16); /* data colour space field */ 2111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (temp) 2112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 0x52474220: /* 'RGB ' */ 21149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((color_type & PNG_COLOR_MASK_COLOR) == 0) 2115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, name, temp, 21167a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "RGB color space not permitted on grayscale PNG"); 2117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 0x47524159: /* 'GRAY' */ 21209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((color_type & PNG_COLOR_MASK_COLOR) != 0) 2121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, name, temp, 21227a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "Gray color space not permitted on RGB PNG"); 2123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 2126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, name, temp, 21277a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "invalid ICC profile color space"); 2128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* It is up to the application to check that the profile class matches the 2131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * application requirements; the spec provides no guidance, but it's pretty 2132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer 2133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ('prtr') or 'spac' (for generic color spaces). Issue a warning in these 2134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * cases. Issue an error for device link or abstract profiles - these don't 2135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * contain the records necessary to transform the color-space to anything 2136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * other than the target device (and not even that for an abstract profile). 2137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Profiles of these classes may not be embedded in images. 2138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik temp = png_get_uint_32(profile+12); /* profile/device class */ 2140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (temp) 2141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 21429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett case 0x73636e72: /* 'scnr' */ 21439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett case 0x6d6e7472: /* 'mntr' */ 2144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 0x70727472: /* 'prtr' */ 2145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 0x73706163: /* 'spac' */ 2146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* All supported */ 2147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 0x61627374: /* 'abst' */ 2150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* May not be embedded in an image */ 2151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, name, temp, 21527a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "invalid embedded Abstract ICC profile"); 2153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 21549b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett case 0x6c696e6b: /* 'link' */ 21559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* DeviceLink profiles cannot be interpreted in a non-device specific 2156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * fashion, if an app uses the AToB0Tag in the profile the results are 2157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * undefined unless the result is sent to the intended device, 2158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * therefore a DeviceLink profile should not be found embedded in a 2159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG. 2160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, name, temp, 21627a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "unexpected DeviceLink ICC profile class"); 2163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 21649b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett case 0x6e6d636c: /* 'nmcl' */ 2165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* A NamedColor profile is also device specific, however it doesn't 21669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * contain an AToB0 tag that is open to misinterpretation. Almost 2167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * certainly it will fail the tests below. 2168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)png_icc_profile_error(png_ptr, NULL, name, temp, 21707a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "unexpected NamedColor ICC profile class"); 2171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 2174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* To allow for future enhancements to the profile accept unrecognized 2175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * profile classes with a warning, these then hit the test below on the 2176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * tag content to ensure they are backward compatible with one of the 2177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * understood profiles. 2178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)png_icc_profile_error(png_ptr, NULL, name, temp, 21807a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "unrecognized ICC profile class"); 2181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* For any profile other than a device link one the PCS must be encoded 2185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * either in XYZ or Lab. 2186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik temp = png_get_uint_32(profile+20); 2188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (temp) 2189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 21909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett case 0x58595a20: /* 'XYZ ' */ 21919b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett case 0x4c616220: /* 'Lab ' */ 2192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 2195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_icc_profile_error(png_ptr, colorspace, name, temp, 21967a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "unexpected ICC PCS encoding"); 2197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 2200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2202b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint /* PRIVATE */ 2203b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace, 22047a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_const_charp name, png_uint_32 profile_length, 22057a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_const_bytep profile /* header plus whole tag table */) 2206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 tag_count = png_get_uint_32(profile+128); 2208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 itag; 2209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep tag = profile+132; /* The first tag */ 2210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* First scan all the tags in the table and add bits to the icc_info value 2212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (temporarily in 'tags'). 2213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (itag=0; itag < tag_count; ++itag, tag += 12) 2215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 tag_id = png_get_uint_32(tag+0); 2217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */ 2218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */ 2219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The ICC specification does not exclude zero length tags, therefore the 2221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * start might actually be anywhere if there is no data, but this would be 2222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * a clear abuse of the intent of the standard so the start is checked for 2223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * being in range. All defined tag types have an 8 byte header - a 4 byte 2224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * type signature then 0. 2225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 22263cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III 22273cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III /* This is a hard error; potentially it can cause read outside the 22283cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * profile. 22293cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III */ 22303cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III if (tag_start > profile_length || tag_length > profile_length - tag_start) 22313cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III return png_icc_profile_error(png_ptr, colorspace, name, tag_id, 22323cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III "ICC profile tag outside profile"); 22333cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III 2234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((tag_start & 3) != 0) 2235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 22363cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III /* CNHP730S.icc shipped with Microsoft Windows 64 violates this; it is 2237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * only a warning here because libpng does not care about the 2238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * alignment. 2239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)png_icc_profile_error(png_ptr, NULL, name, tag_id, 22417a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "ICC profile tag start not a multiple of 4"); 2242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; /* success, maybe with warnings */ 2246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_sRGB_SUPPORTED 22499b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#if PNG_sRGB_PROFILE_CHECKS >= 0 2250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Information about the known ICC sRGB profiles */ 2251b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic const struct 2252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 adler, crc, length; 2254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 md5[4]; 2255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte have_md5; 2256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte is_broken; 2257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16 intent; 2258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0) 2260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\ 2261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { adler, crc, length, md5, broke, intent }, 2262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} png_sRGB_checks[] = 2264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This data comes from contrib/tools/checksum-icc run on downloads of 2266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * all four ICC sRGB profiles from www.color.org. 2267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* adler32, crc32, MD5[4], intent, date, length, file-name */ 2269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9, 22707a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0, 22717a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc") 2272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* ICC sRGB v2 perceptual no black-compensation: */ 2274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21, 22757a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0, 22767a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc") 2277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae, 22797a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0, 22807a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc") 2281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* ICC sRGB v4 perceptual */ 2283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812, 22847a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0, 22857a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc") 2286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following profiles have no known MD5 checksum. If there is a match 2288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * on the (empty) MD5 the other fields are used to attempt a match and 2289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * a warning is produced. The first two of these profiles have a 'cprt' tag 2290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * which suggests that they were also made by Hewlett Packard. 2291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce, 22937a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0, 22947a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc") 2295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not 2297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * match the D50 PCS illuminant in the header (it is in fact the D65 values, 2298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * so the white point is recorded as the un-adapted value.) The profiles 2299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * below only differ in one byte - the intent - and are basically the same as 2300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the previous profile except for the mediaWhitePointTag error and a missing 2301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * chromaticAdaptationTag. 2302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552, 23047a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/, 23057a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual") 2306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d, 23087a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/, 23097a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative") 2310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 2311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2312b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 2313b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, 23147a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_const_bytep profile, uLong adler) 2315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The quick check is to verify just the MD5 signature and trust the 2317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * rest of the data. Because the profile has already been verified for 2318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * correctness this is safe. png_colorspace_set_sRGB will check the 'intent' 2319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * field too, so if the profile has been edited with an intent not defined 2320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * by sRGB (but maybe defined by a later ICC specification) the read of 2321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the profile will fail at that point. 2322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 23239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 2324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 length = 0; 2325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 intent = 0x10000; /* invalid */ 2326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if PNG_sRGB_PROFILE_CHECKS > 1 2327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik uLong crc = 0; /* the value for 0 length data */ 2328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 2329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int i; 2330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 23319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_SET_OPTION_SUPPORTED 23329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* First see if PNG_SKIP_sRGB_CHECK_PROFILE has been set to "on" */ 23339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (((png_ptr->options >> PNG_SKIP_sRGB_CHECK_PROFILE) & 3) == 23349b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_OPTION_ON) 23359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return 0; 23369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 23379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 2338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i) 2339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] && 2341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] && 2342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] && 2343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3]) 2344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This may be one of the old HP profiles without an MD5, in that 2346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * case we can only use the length and Adler32 (note that these 2347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * are not used by default if there is an MD5!) 2348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# if PNG_sRGB_PROFILE_CHECKS == 0 23509b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_sRGB_checks[i].have_md5 != 0) 2351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1+png_sRGB_checks[i].is_broken; 2352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 2353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Profile is unsigned or more checks have been configured in. */ 2355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (length == 0) 2356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik length = png_get_uint_32(profile); 2358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik intent = png_get_uint_32(profile+64); 2359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Length *and* intent must match */ 23629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (length == (png_uint_32) png_sRGB_checks[i].length && 23639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett intent == (png_uint_32) png_sRGB_checks[i].intent) 2364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now calculate the adler32 if not done already. */ 2366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (adler == 0) 2367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik adler = adler32(0, NULL, 0); 2369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik adler = adler32(adler, profile, length); 2370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (adler == png_sRGB_checks[i].adler) 2373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* These basic checks suggest that the data has not been 2375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * modified, but if the check level is more than 1 perform 2376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * our own crc32 checksum on the data. 2377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# if PNG_sRGB_PROFILE_CHECKS > 1 2379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (crc == 0) 2380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik crc = crc32(0, NULL, 0); 2382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik crc = crc32(crc, profile, length); 2383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* So this check must pass for the 'return' below to happen. 2386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (crc == png_sRGB_checks[i].crc) 2388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 2389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 23909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_sRGB_checks[i].is_broken != 0) 2391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* These profiles are known to have bad data that may cause 2393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * problems if they are used, therefore attempt to 2394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * discourage their use, skip the 'have_md5' warning below, 2395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * which is made irrelevant by this error. 2396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_chunk_report(png_ptr, "known incorrect sRGB profile", 23987a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_CHUNK_ERROR); 2399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Warn that this being done; this isn't even an error since 2402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the profile is perfectly valid, but it would be nice if 2403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * people used the up-to-date ones. 2404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 24059b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else if (png_sRGB_checks[i].have_md5 == 0) 2406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_chunk_report(png_ptr, 24087a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "out-of-date sRGB profile with no signature", 24097a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_CHUNK_WARNING); 2410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1+png_sRGB_checks[i].is_broken; 2413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2416b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# if PNG_sRGB_PROFILE_CHECKS > 0 2417b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* The signature matched, but the profile had been changed in some 2418b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * way. This probably indicates a data error or uninformed hacking. 2419b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Fall through to "no match". 2420b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 2421b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_chunk_report(png_ptr, 242206f1087a94f1e48298e89d77ccc51a0ced871958Matt Sarett "Not recognizing known sRGB profile that has been edited", 2423b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari PNG_CHUNK_WARNING); 2424b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari break; 2425b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 24269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 2427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; /* no match */ 2431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2433b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 2434b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_icc_set_sRGB(png_const_structrp png_ptr, 24357a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_colorspacerp colorspace, png_const_bytep profile, uLong adler) 2436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Is this profile one of the known ICC sRGB profiles? If it is, just set 2438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the sRGB information. 2439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 24409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0) 2441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)png_colorspace_set_sRGB(png_ptr, colorspace, 2442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (int)/*already checked*/png_get_uint_32(profile+64)); 2443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 24447a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */ 24459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* sRGB */ 2446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2447b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint /* PRIVATE */ 2448b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace, 24497a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_const_charp name, png_uint_32 profile_length, png_const_bytep profile, 24507a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis int color_type) 2451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 24529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0) 2453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 2454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 24557a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (icc_check_length(png_ptr, colorspace, name, profile_length) != 0 && 24569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_icc_check_header(png_ptr, colorspace, name, profile_length, profile, 24577a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis color_type) != 0 && 24589b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_icc_check_tag_table(png_ptr, colorspace, name, profile_length, 24597a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis profile) != 0) 2460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 24617a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis# if defined(PNG_sRGB_SUPPORTED) && PNG_sRGB_PROFILE_CHECKS >= 0 2462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If no sRGB support, don't try storing sRGB information */ 2463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_icc_set_sRGB(png_ptr, colorspace, profile, 0); 2464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 2465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 2466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Failure case */ 2469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 2470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* iCCP */ 2472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED 2474b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 2475b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colorspace_set_rgb_coefficients(png_structrp png_ptr) 2476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Set the rgb_to_gray coefficients from the colorspace. */ 24789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->rgb_to_gray_coefficients_set == 0 && 2479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) 2480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* png_set_background has not been called, get the coefficients from the Y 2482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * values of the colorspace colorants. 2483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y; 2485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y; 2486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y; 2487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point total = r+g+b; 2488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (total > 0 && 2490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 && 2491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 && 2492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 && 2493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik r+g+b <= 32769) 2494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We allow 0 coefficients here. r+g+b may be 32769 if two or 2496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * all of the coefficients were rounded up. Handle this by 2497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * reducing the *largest* coefficient by 1; this matches the 2498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * approach used for the default coefficients in pngrtran.c 2499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int add = 0; 2501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (r+g+b > 32768) 2503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik add = -1; 2504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (r+g+b < 32768) 2505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik add = 1; 2506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (add != 0) 2508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (g >= r && g >= b) 2510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik g += add; 2511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (r >= g && r >= b) 2512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik r += add; 2513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik b += add; 2515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check for an internal error. */ 2518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (r+g+b != 32768) 2519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, 25207a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "internal error handling cHRM coefficients"); 2521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r; 2525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g; 2526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is a png_error at present even though it could be ignored - 2530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it should never happen, but it is important that if it does, the 2531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * bug is fixed. 2532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "internal error handling cHRM->XYZ"); 2535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 25379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ_RGB_TO_GRAY */ 2538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* COLORSPACE */ 2540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2541f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath#ifdef __GNUC__ 2542f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath/* This exists solely to work round a warning from GNU C. */ 2543f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamathstatic int /* PRIVATE */ 2544f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamathpng_gt(size_t a, size_t b) 2545f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath{ 25467a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis return a > b; 2547f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath} 2548f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath#else 2549f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath# define png_gt(a,b) ((a) > (b)) 2550f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath#endif 2551f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath 2552b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 2553b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_check_IHDR(png_const_structrp png_ptr, 25547a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_uint_32 width, png_uint_32 height, int bit_depth, 25557a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis int color_type, int interlace_type, int compression_type, 25567a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis int filter_type) 2557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int error = 0; 25595f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 25605f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott /* Check for width and height valid values */ 25615f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott if (width == 0) 25625f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 2563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Image width is zero in IHDR"); 2564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 25669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 25679b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (width > PNG_UINT_31_MAX) 2568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2569f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath png_warning(png_ptr, "Invalid image width in IHDR"); 2570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 25733cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III if (png_gt(((width + 7) & (~7U)), 25749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett ((PNG_SIZE_MAX 25759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett - 48 /* big_row_buf hack */ 25769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett - 1) /* filter byte */ 25779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett / 8) /* 8-byte RGBA pixels */ 25789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett - 1)) /* extra max_pixel_depth pad */ 2579f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath { 2580f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath /* The size of the row must be within the limits of this architecture. 2581f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath * Because the read code can perform arbitrary transformations the 2582f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath * maximum size is checked here. Because the code in png_read_start_row 2583f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath * adds extra space "for safety's sake" in several places a conservative 2584f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath * limit is used here. 2585f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath * 2586f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath * NOTE: it would be far better to check the size that is actually used, 2587f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath * but the effect in the real world is minor and the changes are more 2588f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath * extensive, therefore much more dangerous and much more difficult to 2589f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath * write in a way that avoids compiler warnings. 2590f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath */ 25919b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_warning(png_ptr, "Image width is too large for this architecture"); 25929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett error = 1; 2593f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath } 2594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 25959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_SET_USER_LIMITS_SUPPORTED 25969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (width > png_ptr->user_width_max) 25979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#else 25989b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (width > PNG_USER_WIDTH_MAX) 25999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 2600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Image width exceeds user limit in IHDR"); 2602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2605f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath if (height == 0) 2606f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath { 2607f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath png_warning(png_ptr, "Image height is zero in IHDR"); 2608f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath error = 1; 2609f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath } 2610f4435dfcdb5733f9c340492cc7fcac88a13f6ebdNarayan Kamath 26119b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (height > PNG_UINT_31_MAX) 2612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 26139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_warning(png_ptr, "Invalid image height in IHDR"); 2614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 26179b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_SET_USER_LIMITS_SUPPORTED 26189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (height > png_ptr->user_height_max) 26199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#else 26209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (height > PNG_USER_HEIGHT_MAX) 26219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 2622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 26239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_warning(png_ptr, "Image height exceeds user limit in IHDR"); 2624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check other values */ 2628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 && 2629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik bit_depth != 8 && bit_depth != 16) 2630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Invalid bit depth in IHDR"); 2632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (color_type < 0 || color_type == 1 || 2636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik color_type == 5 || color_type > 6) 2637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Invalid color type in IHDR"); 2639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (((color_type == PNG_COLOR_TYPE_PALETTE) && bit_depth > 8) || 2643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ((color_type == PNG_COLOR_TYPE_RGB || 2644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik color_type == PNG_COLOR_TYPE_GRAY_ALPHA || 2645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik color_type == PNG_COLOR_TYPE_RGB_ALPHA) && bit_depth < 8)) 2646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Invalid color type/bit depth combination in IHDR"); 2648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (interlace_type >= PNG_INTERLACE_LAST) 2652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Unknown interlace method in IHDR"); 2654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (compression_type != PNG_COMPRESSION_TYPE_BASE) 2658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Unknown compression method in IHDR"); 2660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 26639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_MNG_FEATURES_SUPPORTED 2664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Accept filter_method 64 (intrapixel differencing) only if 2665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and 2666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2. Libpng did not read a PNG signature (this filter_method is only 2667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * used in PNG datastreams that are embedded in MNG datastreams) and 2668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3. The application called png_permit_mng_features with a mask that 2669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * included PNG_FLAG_MNG_FILTER_64 and 2670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 4. The filter_method is 64 and 2671b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 5. The color_type is RGB or RGBA 2672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 26739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && 26749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->mng_features_permitted != 0) 2675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); 2676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (filter_type != PNG_FILTER_TYPE_BASE) 2678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 26799b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 && 2680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (filter_type == PNG_INTRAPIXEL_DIFFERENCING) && 2681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && 2682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (color_type == PNG_COLOR_TYPE_RGB || 2683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik color_type == PNG_COLOR_TYPE_RGB_ALPHA))) 2684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Unknown filter method in IHDR"); 2686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 26899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0) 2690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Invalid filter method in IHDR"); 2692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2695b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 26969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#else 2697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (filter_type != PNG_FILTER_TYPE_BASE) 2698b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2699b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Unknown filter method in IHDR"); 2700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = 1; 2701b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 27029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 2703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (error == 1) 2705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "Invalid IHDR data"); 2706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED) 2709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* ASCII to fp functions */ 2710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Check an ASCII formated floating point value, see the more detailed 2711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * comments in pngpriv.h 2712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The following is used internally to preserve the sticky flags */ 2714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define png_fp_add(state, flags) ((state) |= (flags)) 2715b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define png_fp_set(state, value) ((state) = (value) | ((state) & PNG_FP_STICKY)) 2716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2717b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint /* PRIVATE */ 2718b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_check_fp_number(png_const_charp string, png_size_t size, int *statep, 27197a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_size_tp whereami) 2720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int state = *statep; 2722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t i = *whereami; 2723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (i < size) 2725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2726b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int type; 2727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* First find the type of the next character */ 2728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (string[i]) 2729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 43: type = PNG_FP_SAW_SIGN; break; 2731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 45: type = PNG_FP_SAW_SIGN + PNG_FP_NEGATIVE; break; 2732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 46: type = PNG_FP_SAW_DOT; break; 2733b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 48: type = PNG_FP_SAW_DIGIT; break; 2734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 49: case 50: case 51: case 52: 2735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 53: case 54: case 55: case 56: 2736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 57: type = PNG_FP_SAW_DIGIT + PNG_FP_NONZERO; break; 2737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 69: 2738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 101: type = PNG_FP_SAW_E; break; 2739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: goto PNG_FP_End; 2740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now deal with this type according to the current 2743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * state, the type is arranged to not overlap the 2744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * bits of the PNG_FP_STATE. 2745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY)) 2747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_FP_INTEGER + PNG_FP_SAW_SIGN: 27499b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((state & PNG_FP_SAW_ANY) != 0) 2750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto PNG_FP_End; /* not a part of the number */ 2751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fp_add(state, type); 2753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_FP_INTEGER + PNG_FP_SAW_DOT: 2756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Ok as trailer, ok as lead of fraction. */ 27579b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((state & PNG_FP_SAW_DOT) != 0) /* two dots */ 2758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto PNG_FP_End; 2759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 27609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else if ((state & PNG_FP_SAW_DIGIT) != 0) /* trailing dot? */ 2761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fp_add(state, type); 2762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2763b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fp_set(state, PNG_FP_FRACTION | type); 2765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT: 27699b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((state & PNG_FP_SAW_DOT) != 0) /* delayed fraction */ 2770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT); 2771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fp_add(state, type | PNG_FP_WAS_VALID); 2773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_FP_INTEGER + PNG_FP_SAW_E: 2777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((state & PNG_FP_SAW_DIGIT) == 0) 2778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto PNG_FP_End; 2779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fp_set(state, PNG_FP_EXPONENT); 2781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* case PNG_FP_FRACTION + PNG_FP_SAW_SIGN: 2785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto PNG_FP_End; ** no sign in fraction */ 2786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* case PNG_FP_FRACTION + PNG_FP_SAW_DOT: 2788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto PNG_FP_End; ** Because SAW_DOT is always set */ 2789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_FP_FRACTION + PNG_FP_SAW_DIGIT: 2791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fp_add(state, type | PNG_FP_WAS_VALID); 2792b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2794b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_FP_FRACTION + PNG_FP_SAW_E: 2795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is correct because the trailing '.' on an 2796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * integer is handled above - so we can only get here 2797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * with the sequence ".E" (with no preceding digits). 2798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((state & PNG_FP_SAW_DIGIT) == 0) 2800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto PNG_FP_End; 2801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fp_set(state, PNG_FP_EXPONENT); 2803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN: 28079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((state & PNG_FP_SAW_ANY) != 0) 2808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto PNG_FP_End; /* not a part of the number */ 2809b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fp_add(state, PNG_FP_SAW_SIGN); 2811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2812b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* case PNG_FP_EXPONENT + PNG_FP_SAW_DOT: 2815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto PNG_FP_End; */ 2816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_FP_EXPONENT + PNG_FP_SAW_DIGIT: 2818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fp_add(state, PNG_FP_SAW_DIGIT | PNG_FP_WAS_VALID); 2819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* case PNG_FP_EXPONEXT + PNG_FP_SAW_E: 2823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto PNG_FP_End; */ 2824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: goto PNG_FP_End; /* I.e. break 2 */ 2826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The character seems ok, continue. */ 2829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++i; 2830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2832b50c217251b086440efcdb273c22f86a06c80cbaChris CraikPNG_FP_End: 2833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Here at the end, update the state and return the correct 2834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * return code. 2835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *statep = state; 2837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *whereami = i; 2838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (state & PNG_FP_SAW_DIGIT) != 0; 2840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The same but for a complete string. */ 2844b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint 2845b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_check_fp_string(png_const_charp string, png_size_t size) 2846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2847b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int state=0; 2848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t char_index=0; 2849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 28509b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_check_fp_number(string, size, &state, &char_index) != 0 && 2851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (char_index == size || string[char_index] == 0)) 2852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return state /* must be non-zero - see above */; 2853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; /* i.e. fail */ 2855b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 28569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* pCAL || sCAL */ 2857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_sCAL_SUPPORTED 2859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_FLOATING_POINT_SUPPORTED 2860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Utility used below - a simple accurate power of ten from an integral 2861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * exponent. 2862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2863b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic double 2864b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_pow10(int power) 2865b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int recip = 0; 2867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double d = 1; 2868b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Handle negative exponent with a reciprocal at the end because 2870b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 10 is exact whereas .1 is inexact in base 2 2871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (power < 0) 2873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (power < DBL_MIN_10_EXP) return 0; 28753cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III recip = 1; power = -power; 2876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (power > 0) 2879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Decompose power bitwise. */ 2881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double mult = 10; 2882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do 2883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (power & 1) d *= mult; 2885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik mult *= mult; 2886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik power >>= 1; 2887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (power > 0); 2889b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 28909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (recip != 0) d = 1/d; 2891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* else power is 0 and d is 1 */ 2893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2894b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return d; 2895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2896b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Function to format a floating point value in ASCII with a given 2898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * precision. 2899b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 29003cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#if GCC_STRICT_OVERFLOW 29013cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#pragma GCC diagnostic push 29023cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III/* The problem arises below with exp_b10, which can never overflow because it 29033cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * comes, originally, from frexp and is therefore limited to a range which is 29043cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * typically +/-710 (log2(DBL_MAX)/log2(DBL_MIN)). 29053cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III */ 29063cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#pragma GCC diagnostic warning "-Wstrict-overflow=2" 29073cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#endif /* GCC_STRICT_OVERFLOW */ 2908b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 2909b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, 2910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double fp, unsigned int precision) 2911b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2912b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We use standard functions from math.h, but not printf because 2913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * that would require stdio. The caller must supply a buffer of 2914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * sufficient size or we will png_error. The tests on size and 2915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the space in ascii[] consumed are indicated below. 2916b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (precision < 1) 2918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik precision = DBL_DIG; 2919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Enforce the limit of the implementation precision too. */ 2921b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (precision > DBL_DIG+1) 2922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik precision = DBL_DIG+1; 2923b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Basic sanity checks */ 2925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (size >= precision+5) /* See the requirements below. */ 2926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2927b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fp < 0) 2928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2929b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fp = -fp; 2930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii++ = 45; /* '-' PLUS 1 TOTAL 1 */ 2931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik --size; 2932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fp >= DBL_MIN && fp <= DBL_MAX) 2935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 29369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int exp_b10; /* A base 10 exponent */ 2937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double base; /* 10^exp_b10 */ 2938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* First extract a base 10 exponent of the number, 2940b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the calculation below rounds down when converting 2941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * from base 2 to base 10 (multiply by log10(2) - 2942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 0.3010, but 77/256 is 0.3008, so exp_b10 needs to 2943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be increased. Note that the arithmetic shift 2944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * performs a floor() unlike C arithmetic - using a 2945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * C multiply would break the following for negative 2946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * exponents. 2947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)frexp(fp, &exp_b10); /* exponent to base 2 */ 2949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exp_b10 = (exp_b10 * 77) >> 8; /* <= exponent to base 10 */ 2951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2952b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Avoid underflow here. */ 2953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik base = png_pow10(exp_b10); /* May underflow */ 2954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (base < DBL_MIN || base < fp) 2956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And this may overflow. */ 2958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double test = png_pow10(exp_b10+1); 2959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (test <= DBL_MAX) 29613cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III { 29623cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III ++exp_b10; base = test; 29633cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III } 2964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Normalize fp and correct exp_b10, after this fp is in the 2970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * range [.1,1) and exp_b10 is both the exponent and the digit 2971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * *before* which the decimal point should be inserted 2972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (starting with 0 for the first digit). Note that this 2973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * works even if 10^exp_b10 is out of range because of the 2974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * test on DBL_MAX above. 2975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fp /= base; 29773cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III while (fp >= 1) 29783cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III { 29793cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III fp /= 10; ++exp_b10; 29803cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III } 2981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Because of the code above fp may, at this point, be 2983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * less than .1, this is ok because the code below can 2984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * handle the leading zeros this generates, so no attempt 2985b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is made to correct that here. 2986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2988b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 29899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett unsigned int czero, clead, cdigits; 2990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char exponent[10]; 2991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Allow up to two leading zeros - this will not lengthen 2993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the number compared to using E-n. 2994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (exp_b10 < 0 && exp_b10 > -3) /* PLUS 3 TOTAL 4 */ 2996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 29973cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III czero = 0U-exp_b10; /* PLUS 2 digits: TOTAL 3 */ 2998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exp_b10 = 0; /* Dot added below before first output. */ 2999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik czero = 0; /* No zeros to add */ 3002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Generate the digit list, stripping trailing zeros and 3004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * inserting a '.' before a digit if the exponent is 0. 3005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik clead = czero; /* Count of leading zeros */ 3007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cdigits = 0; /* Count of digits in list. */ 3008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do 3010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double d; 3012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fp *= 10; 3014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Use modf here, not floor and subtract, so that 3015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the separation is done in one step. At the end 3016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * of the loop don't break the number into parts so 3017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * that the final digit is rounded. 3018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 30199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (cdigits+czero+1 < precision+clead) 3020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fp = modf(fp, &d); 3021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik d = floor(fp + .5); 3025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (d > 9) 3027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Rounding up to 10, handle that here. */ 3029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (czero > 0) 3030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 30313cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III --czero; d = 1; 3032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (cdigits == 0) --clead; 3033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (cdigits > 0 && d > 9) 3037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int ch = *--ascii; 3039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (exp_b10 != (-1)) 3041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++exp_b10; 3042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (ch == 46) 3044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 30453cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III ch = *--ascii; ++size; 3046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Advance exp_b10 to '1', so that the 3047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * decimal point happens after the 3048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * previous digit. 3049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exp_b10 = 1; 3051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik --cdigits; 3054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik d = ch - 47; /* I.e. 1+(ch-48) */ 3055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Did we reach the beginning? If so adjust the 3058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * exponent but take into account the leading 3059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * decimal point. 3060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (d > 9) /* cdigits == 0 */ 3062b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (exp_b10 == (-1)) 3064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3065b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Leading decimal point (plus zeros?), if 3066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * we lose the decimal point here it must 3067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be reentered below. 3068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3069b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int ch = *--ascii; 3070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ch == 46) 30723cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III { 30733cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III ++size; exp_b10 = 1; 30743cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III } 3075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Else lost a leading zero, so 'exp_b10' is 3077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * still ok at (-1) 3078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3081b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++exp_b10; 3082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* In all cases we output a '1' */ 3084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik d = 1; 3085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik fp = 0; /* Guarantees termination below. */ 3089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (d == 0) 3092b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++czero; 3094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (cdigits == 0) ++clead; 3095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Included embedded zeros in the digit count. */ 3099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cdigits += czero - clead; 3100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik clead = 0; 3101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (czero > 0) 3103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* exp_b10 == (-1) means we just output the decimal 3105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * place - after the DP don't adjust 'exp_b10' any 3106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * more! 3107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (exp_b10 != (-1)) 3109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 31103cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III if (exp_b10 == 0) 31113cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III { 31123cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III *ascii++ = 46; --size; 31133cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III } 3114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* PLUS 1: TOTAL 4 */ 3115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik --exp_b10; 3116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 31173cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III *ascii++ = 48; --czero; 3118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (exp_b10 != (-1)) 3121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 31229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (exp_b10 == 0) 31233cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III { 31243cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III *ascii++ = 46; --size; /* counted above */ 31253cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III } 31269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 3127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik --exp_b10; 3128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 31293cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III *ascii++ = (char)(48 + (int)d); ++cdigits; 3130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 31329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett while (cdigits+czero < precision+clead && fp > DBL_MIN); 3133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The total output count (max) is now 4+precision */ 3135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check for an exponent, if we don't need one we are 3137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * done and just need to terminate the string. At 31383cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * this point exp_b10==(-1) is effectively a flag - it got 31399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * to '-1' because of the decrement after outputting 3140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the decimal point above (the exponent required is 3141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * *not* -1!) 3142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (exp_b10 >= (-1) && exp_b10 <= 2) 3144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following only happens if we didn't output the 3146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * leading zeros above for negative exponent, so this 31479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * doesn't add to the digit requirement. Note that the 3148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * two zeros here can only be output if the two leading 3149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * zeros were *not* output, so this doesn't increase 3150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the output count. 3151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 31523cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III while (exp_b10-- > 0) *ascii++ = 48; 3153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii = 0; 3155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Total buffer requirement (including the '\0') is 3157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 5+precision - see check at the start. 3158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 3160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Here if an exponent is required, adjust size for 3163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the digits we output but did not count. The total 3164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * digit output here so far is at most 1+precision - no 3165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * decimal point and no leading or trailing zeros have 3166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * been output. 3167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik size -= cdigits; 3169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 31703cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III *ascii++ = 69; --size; /* 'E': PLUS 1 TOTAL 2+precision */ 3171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following use of an unsigned temporary avoids ambiguities in 3173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the signed arithmetic on exp_b10 and permits GCC at least to do 3174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * better optimization. 3175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int uexp_b10; 3178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (exp_b10 < 0) 3180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 31813cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III *ascii++ = 45; --size; /* '-': PLUS 1 TOTAL 3+precision */ 31823cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III uexp_b10 = 0U-exp_b10; 3183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 31863cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III uexp_b10 = 0U+exp_b10; 3187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cdigits = 0; 3189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (uexp_b10 > 0) 3191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik exponent[cdigits++] = (char)(48 + uexp_b10 % 10); 3193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik uexp_b10 /= 10; 3194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Need another size check here for the exponent digits, so 3198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this need not be considered above. 3199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 32009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (size > cdigits) 3201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3202b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (cdigits > 0) *ascii++ = exponent[--cdigits]; 3203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii = 0; 3205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 3207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (!(fp >= DBL_MIN)) 3211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii++ = 48; /* '0' */ 3213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii = 0; 3214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 3215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii++ = 105; /* 'i' */ 3219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii++ = 110; /* 'n' */ 3220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii++ = 102; /* 'f' */ 3221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii = 0; 3222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 3223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Here on buffer too small. */ 3227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "ASCII conversion buffer too small"); 3228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 32293cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#if GCC_STRICT_OVERFLOW 32303cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#pragma GCC diagnostic pop 32313cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#endif /* GCC_STRICT_OVERFLOW */ 3232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif /* FLOATING_POINT */ 3234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_FIXED_POINT_SUPPORTED 3236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Function to format a fixed point value in ASCII. 3237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3238b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 3239b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, 3240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t size, png_fixed_point fp) 3241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Require space for 10 decimal digits, a decimal point, a minus sign and a 3243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * trailing \0, 13 characters: 3244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (size > 12) 3246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 num; 3248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Avoid overflow here on the minimum integer. */ 3250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fp < 0) 32513cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III { 32523cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III *ascii++ = 45; num = (png_uint_32)(-fp); 32533cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III } 3254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 32553cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III num = (png_uint_32)fp; 3256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (num <= 0x80000000) /* else overflowed */ 3258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int ndigits = 0, first = 16 /* flag value */; 3260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char digits[10]; 3261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (num) 3263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Split the low digit off num: */ 3265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int tmp = num/10; 3266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik num -= tmp*10; 3267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik digits[ndigits++] = (char)(48 + num); 3268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Record the first non-zero digit, note that this is a number 3269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * starting at 1, it's not actually the array index. 3270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (first == 16 && num > 0) 3272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik first = ndigits; 3273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik num = tmp; 3274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ndigits > 0) 3277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (ndigits > 5) *ascii++ = digits[--ndigits]; 3279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The remaining digits are fractional digits, ndigits is '5' or 3280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * smaller at this point. It is certainly not zero. Check for a 3281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * non-zero fractional digit: 3282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (first <= 5) 3284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int i; 3286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii++ = 46; /* decimal point */ 3287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* ndigits may be <5 for small numbers, output leading zeros 3288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * then ndigits digits to first: 3289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik i = 5; 32913cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III while (ndigits < i) 32923cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III { 32933cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III *ascii++ = 48; --i; 32943cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III } 3295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (ndigits >= first) *ascii++ = digits[--ndigits]; 3296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Don't output the trailing zeros! */ 3297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii++ = 48; 3301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And null terminate the string: */ 3303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *ascii = 0; 3304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 3305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Here on buffer too small. */ 3309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "ASCII conversion buffer too small"); 3310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif /* FIXED_POINT */ 33129b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* SCAL */ 3313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_FLOATING_POINT_SUPPORTED) && \ 3315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \ 3316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \ 3317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \ 3318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \ 3319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (defined(PNG_sCAL_SUPPORTED) && \ 3320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_FLOATING_ARITHMETIC_SUPPORTED)) 3321b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_fixed_point 3322b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_fixed(png_const_structrp png_ptr, double fp, png_const_charp text) 3323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double r = floor(100000 * fp + .5); 3325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (r > 2147483647. || r < -2147483648.) 3327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_error(png_ptr, text); 3328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3329b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifndef PNG_ERROR_TEXT_SUPPORTED 33309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(text) 3331b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 3332b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 3333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_fixed_point)r; 3334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 3336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3337b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\ 3338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED) 3339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* muldiv functions */ 3340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* This API takes signed arguments and rounds the result to the nearest 3341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * integer (or, for a fixed point number - the standard argument - to 3342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the nearest .00001). Overflow and divide by zero are signalled in 3343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the result, a boolean - true on success, false on overflow. 3344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 33453cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#if GCC_STRICT_OVERFLOW /* from above */ 33463cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III/* It is not obvious which comparison below gets optimized in such a way that 33473cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * signed overflow would change the result; looking through the code does not 33483cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * reveal any tests which have the form GCC complains about, so presumably the 33493cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * optimizer is moving an add or subtract into the 'if' somewhere. 33503cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III */ 33513cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#pragma GCC diagnostic push 33523cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#pragma GCC diagnostic warning "-Wstrict-overflow=2" 33533cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#endif /* GCC_STRICT_OVERFLOW */ 3354b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint 3355b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times, 3356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_int_32 divisor) 3357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Return a * times / divisor, rounded. */ 3359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (divisor != 0) 3360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (a == 0 || times == 0) 3362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *res = 0; 3364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 3365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED 3369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double r = a; 3370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik r *= times; 3371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik r /= divisor; 3372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik r = floor(r+.5); 3373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* A png_fixed_point is a 32-bit integer. */ 3375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (r <= 2147483647. && r >= -2147483648.) 3376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *res = (png_fixed_point)r; 3378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 3379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else 3381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int negative = 0; 3382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 A, T, D; 3383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 s16, s32, s00; 3384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (a < 0) 3386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik negative = 1, A = -a; 3387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik A = a; 3389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (times < 0) 3391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik negative = !negative, T = -times; 3392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik T = times; 3394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (divisor < 0) 3396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik negative = !negative, D = -divisor; 3397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik D = divisor; 3399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Following can't overflow because the arguments only 3401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * have 31 bits each, however the result may be 32 bits. 3402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik s16 = (A >> 16) * (T & 0xffff) + 3404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (A & 0xffff) * (T >> 16); 3405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Can't overflow because the a*times bit is only 30 3406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * bits at most. 3407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik s32 = (A >> 16) * (T >> 16) + (s16 >> 16); 3409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik s00 = (A & 0xffff) * (T & 0xffff); 3410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik s16 = (s16 & 0xffff) << 16; 3412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik s00 += s16; 3413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (s00 < s16) 3415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++s32; /* carry */ 3416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (s32 < D) /* else overflow */ 3418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* s32.s00 is now the 64-bit product, do a standard 3420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * division, we know that s32 < D, so the maximum 3421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * required shift is 31. 3422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int bitshift = 32; 3424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point result = 0; /* NOTE: signed */ 3425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (--bitshift >= 0) 3427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 d32, d00; 3429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (bitshift > 0) 3431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik d32 = D >> (32-bitshift), d00 = D << bitshift; 3432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik d32 = 0, d00 = D; 3435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (s32 > d32) 3437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (s00 < d00) --s32; /* carry */ 3439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik s32 -= d32, s00 -= d00, result += 1<<bitshift; 3440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (s32 == d32 && s00 >= d00) 3444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik s32 = 0, s00 -= d00, result += 1<<bitshift; 3445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Handle the rounding. */ 3448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (s00 >= (D >> 1)) 3449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++result; 3450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 34519b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (negative != 0) 3452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = -result; 3453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check for overflow. */ 34559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((negative != 0 && result <= 0) || 34569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (negative == 0 && result >= 0)) 3457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *res = result; 3459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 3460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 3463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 34645f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 34655f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 3466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 3467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 34683cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#if GCC_STRICT_OVERFLOW 34693cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#pragma GCC diagnostic pop 34703cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III#endif /* GCC_STRICT_OVERFLOW */ 3471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_GAMMA || INCH_CONVERSIONS */ 3472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED) 3474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The following is for when the caller doesn't much care about the 3475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * result. 3476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3477b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_fixed_point 3478b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times, 3479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_int_32 divisor) 3480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point result; 3482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 34839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&result, a, times, divisor) != 0) 3484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return result; 3485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "fixed point overflow ignored"); 3487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 3488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 3490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */ 3492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */ 3493b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_fixed_point 3494b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_reciprocal(png_fixed_point a) 3495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED 3497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double r = floor(1E10/a+.5); 3498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (r <= 2147483647. && r >= -2147483648.) 3500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_fixed_point)r; 3501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else 3502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point res; 3503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 35049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&res, 100000, 100000, a) != 0) 3505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return res; 3506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 3507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; /* error/overflow */ 3509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* This is the shared test on whether a gamma value is 'significant' - whether 3512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it is worth doing gamma correction. 3513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3514b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint /* PRIVATE */ 3515b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_gamma_significant(png_fixed_point gamma_val) 3516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED || 3518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED; 3519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 3521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED 35239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_16BIT_SUPPORTED 3524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* A local convenience routine. */ 3525b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_fixed_point 3526b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_product2(png_fixed_point a, png_fixed_point b) 3527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The required result is 1/a * 1/b; the following preserves accuracy. */ 35299b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED 3530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik double r = a * 1E-5; 3531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik r *= b; 3532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik r = floor(r+.5); 3533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (r <= 2147483647. && r >= -2147483648.) 3535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_fixed_point)r; 35369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#else 3537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point res; 3538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 35399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&res, a, b, 100000) != 0) 3540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return res; 35419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 3542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; /* overflow */ 3544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 35459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* 16BIT */ 3546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The inverse of the above. */ 3548b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_fixed_point 3549b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_reciprocal2(png_fixed_point a, png_fixed_point b) 3550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The required result is 1/a * 1/b; the following preserves accuracy. */ 3552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED 35539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (a != 0 && b != 0) 35549b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 35559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett double r = 1E15/a; 35569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett r /= b; 35579b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett r = floor(r+.5); 3558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 35599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (r <= 2147483647. && r >= -2147483648.) 35609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return (png_fixed_point)r; 35619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 3562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else 3563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This may overflow because the range of png_fixed_point isn't symmetric, 3564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * but this API is only used for the product of file and screen gamma so it 3565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * doesn't matter that the smallest number it can produce is 1/21474, not 3566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1/100000 3567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point res = png_product2(a, b); 3569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (res != 0) 3571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_reciprocal(res); 3572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 3573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; /* overflow */ 3575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_GAMMA */ 3577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */ 3579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED 3580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Fixed point gamma. 3581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The code to calculate the tables used below can be found in the shell script 3583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * contrib/tools/intgamma.sh 3584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * To calculate gamma this code implements fast log() and exp() calls using only 3586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * fixed point arithmetic. This code has sufficient precision for either 8-bit 3587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * or 16-bit sample values. 3588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The tables used here were calculated using simple 'bc' programs, but C double 3590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * precision floating point arithmetic would work fine. 3591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8-bit log table 3593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This is a table of -log(value/255)/log(2) for 'value' in the range 128 to 3594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 255, so it's the base 2 logarithm of a normalized 8-bit floating point 3595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * mantissa. The numbers are 32-bit fractions. 3596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3597b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic const png_uint_32 3598b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_8bit_l2[128] = 3599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U, 3601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U, 3602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U, 3603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3455425220U, 3413129301U, 3371120137U, 3329393864U, 3287946700U, 3246774933U, 3604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3205874930U, 3165243125U, 3124876025U, 3084770202U, 3044922296U, 3005329011U, 3605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2965987113U, 2926893432U, 2888044853U, 2849438323U, 2811070844U, 2772939474U, 3606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2735041326U, 2697373562U, 2659933400U, 2622718104U, 2585724991U, 2548951424U, 3607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2512394810U, 2476052606U, 2439922311U, 2404001468U, 2368287663U, 2332778523U, 3608b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2297471715U, 2262364947U, 2227455964U, 2192742551U, 2158222529U, 2123893754U, 3609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2089754119U, 2055801552U, 2022034013U, 1988449497U, 1955046031U, 1921821672U, 3610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1888774511U, 1855902668U, 1823204291U, 1790677560U, 1758320682U, 1726131893U, 3611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1694109454U, 1662251657U, 1630556815U, 1599023271U, 1567649391U, 1536433567U, 3612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1505374214U, 1474469770U, 1443718700U, 1413119487U, 1382670639U, 1352370686U, 3613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1322218179U, 1292211689U, 1262349810U, 1232631153U, 1203054352U, 1173618059U, 3614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1144320946U, 1115161701U, 1086139034U, 1057251672U, 1028498358U, 999877854U, 3615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 971388940U, 943030410U, 914801076U, 886699767U, 858725327U, 830876614U, 3616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 803152505U, 775551890U, 748073672U, 720716771U, 693480120U, 666362667U, 3617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 639363374U, 612481215U, 585715177U, 559064263U, 532527486U, 506103872U, 3618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 479792461U, 453592303U, 427502463U, 401522014U, 375650043U, 349885648U, 3619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U, 3620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U, 3621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 24347096U, 0U 3622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if 0 3624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following are the values for 16-bit tables - these work fine for the 3625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8-bit conversions but produce very slightly larger errors in the 16-bit 3626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * log (about 1.2 as opposed to 0.7 absolute error in the final value). To 3627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * use these all the shifts below must be adjusted appropriately. 3628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 65166, 64430, 63700, 62976, 62257, 61543, 60835, 60132, 59434, 58741, 58054, 3630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 57371, 56693, 56020, 55352, 54689, 54030, 53375, 52726, 52080, 51439, 50803, 3631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 50170, 49542, 48918, 48298, 47682, 47070, 46462, 45858, 45257, 44661, 44068, 3632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 43479, 42894, 42312, 41733, 41159, 40587, 40020, 39455, 38894, 38336, 37782, 3633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 37230, 36682, 36137, 35595, 35057, 34521, 33988, 33459, 32932, 32408, 31887, 3634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 31369, 30854, 30341, 29832, 29325, 28820, 28319, 27820, 27324, 26830, 26339, 3635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 25850, 25364, 24880, 24399, 23920, 23444, 22970, 22499, 22029, 21562, 21098, 3636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20636, 20175, 19718, 19262, 18808, 18357, 17908, 17461, 17016, 16573, 16132, 3637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 15694, 15257, 14822, 14390, 13959, 13530, 13103, 12678, 12255, 11834, 11415, 3638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10997, 10582, 10168, 9756, 9346, 8937, 8531, 8126, 7723, 7321, 6921, 6523, 3639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 6127, 5732, 5339, 4947, 4557, 4169, 3782, 3397, 3014, 2632, 2251, 1872, 1495, 3640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1119, 744, 372 3641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 3642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 3643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3644b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_int_32 3645b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_log8bit(unsigned int x) 3646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int lg2 = 0; 3648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log, 3649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * because the log is actually negate that means adding 1. The final 3650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * returned value thus has the range 0 (for 255 input) to 7.994 (for 1 3651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * input), return -1 for the overflow (log 0) case, - so the result is 3652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * always at most 19 bits. 3653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((x &= 0xff) == 0) 3655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return -1; 3656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((x & 0xf0) == 0) 3658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lg2 = 4, x <<= 4; 3659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((x & 0xc0) == 0) 3661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lg2 += 2, x <<= 2; 3662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((x & 0x80) == 0) 3664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lg2 += 1, x <<= 1; 3665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* result is at most 19 bits, so this cast is safe: */ 3667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_int_32)((lg2 << 16) + ((png_8bit_l2[x-128]+32768)>>16)); 3668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The above gives exact (to 16 binary places) log2 values for 8-bit images, 3671b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * for 16-bit images we use the most significant 8 bits of the 16-bit value to 3672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * get an approximation then multiply the approximation by a correction factor 3673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * determined by the remaining up to 8 bits. This requires an additional step 3674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * in the 16-bit case. 3675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * We want log2(value/65535), we have log2(v'/255), where: 3677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value = v' * 256 + v'' 3679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * = v' * f 3680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * So f is value/v', which is equal to (256+v''/v') since v' is in the range 128 3682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to 255 and v'' is in the range 0 to 255 f will be in the range 256 to less 3683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * than 258. The final factor also needs to correct for the fact that our 8-bit 3684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value is scaled by 255, whereas the 16-bit values must be scaled by 65535. 3685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This gives a final formula using a calculated value 'x' which is value/v' and 3687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * scaling by 65536 to match the above table: 3688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * log2(x/257) * 65536 3690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Since these numbers are so close to '1' we can use simple linear 3692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * interpolation between the two end values 256/257 (result -368.61) and 258/257 3693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (result 367.179). The values used below are scaled by a further 64 to give 3694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16-bit precision in the interpolation: 3695b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3696b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Start (256): -23591 3697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Zero (257): 0 3698b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * End (258): 23499 3699b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 37009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_16BIT_SUPPORTED 3701b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_int_32 3702b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_log16bit(png_uint_32 x) 3703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int lg2 = 0; 3705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* As above, but now the input has 16 bits. */ 3707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((x &= 0xffff) == 0) 3708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return -1; 37095f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 3710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((x & 0xff00) == 0) 3711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lg2 = 8, x <<= 8; 3712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((x & 0xf000) == 0) 3714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lg2 += 4, x <<= 4; 3715b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((x & 0xc000) == 0) 3717b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lg2 += 2, x <<= 2; 3718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((x & 0x8000) == 0) 3720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lg2 += 1, x <<= 1; 3721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Calculate the base logarithm from the top 8 bits as a 28-bit fractional 3723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value. 3724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lg2 <<= 28; 3726b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lg2 += (png_8bit_l2[(x>>8)-128]+8) >> 4; 3727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now we need to interpolate the factor, this requires a division by the top 3729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8 bits. Do this with maximum precision. 3730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik x = ((x << 16) + (x >> 9)) / (x >> 8); 3732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3733b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Since we divided by the top 8 bits of 'x' there will be a '1' at 1<<24, 3734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the value at 1<<16 (ignoring this) will be 0 or 1; this gives us exactly 3735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 16 bits to interpolate to get the low bits of the result. Round the 3736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * answer. Note that the end point values are scaled by 64 to retain overall 3737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * precision and that 'lg2' is current scaled by an extra 12 bits, so adjust 3738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the overall scaling by 6-12. Round at every step. 3739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik x -= 1U << 24; 3741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (x <= 65536U) /* <= '257' */ 3743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lg2 += ((23591U * (65536U-x)) + (1U << (16+6-12-1))) >> (16+6-12); 3744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lg2 -= ((23499U * (x-65536U)) + (1U << (16+6-12-1))) >> (16+6-12); 3747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Safe, because the result can't have more than 20 bits: */ 3749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_int_32)((lg2 + 2048) >> 12); 3750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 37519b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* 16BIT */ 3752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The 'exp()' case must invert the above, taking a 20-bit fixed point 3754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * logarithmic value and returning a 16 or 8-bit number as appropriate. In 3755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * each case only the low 16 bits are relevant - the fraction - since the 3756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * integer bits (the top 4) simply determine a shift. 3757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 37589b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * The worst case is the 16-bit distinction between 65535 and 65534. This 37599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * requires perhaps spurious accuracy in the decoding of the logarithm to 3760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance 3761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * of getting this accuracy in practice. 3762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3763b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * To deal with this the following exp() function works out the exponent of the 37643cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * fractional part of the logarithm by using an accurate 32-bit value from the 3765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * top four fractional bits then multiplying in the remaining bits. 3766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3767b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic const png_uint_32 3768b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_32bit_exp[16] = 3769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* NOTE: the first entry is deliberately set to the maximum 32-bit value. */ 3771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U, 3772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U, 3773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2553802834U, 2445529972U, 2341847524U, 2242560872U 3774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 3775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Adjustment table; provided to explain the numbers in the code below. */ 3777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if 0 3778b50c217251b086440efcdb273c22f86a06c80cbaChris Craikfor (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"} 3779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 11 44937.64284865548751208448 3780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10 45180.98734845585101160448 3781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9 45303.31936980687359311872 3782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 8 45364.65110595323018870784 3783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 7 45395.35850361789624614912 3784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 6 45410.72259715102037508096 3785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 5 45418.40724413220722311168 3786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4 45422.25021786898173001728 3787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3 45424.17186732298419044352 3788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2 45425.13273269940811464704 3789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1 45425.61317555035558641664 3790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 0 45425.85339951654943850496 37915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif 3792b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3793b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_32 3794b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_exp(png_fixed_point x) 3795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */ 37975f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 3798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Obtain a 4-bit approximation */ 37999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_uint_32 e = png_32bit_exp[(x >> 12) & 0x0f]; 3800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Incorporate the low 12 bits - these decrease the returned value by 3802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * multiplying by a number less than 1 if the bit is set. The multiplier 3803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is determined by the above table and the shift. Notice that the values 3804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * converge on 45426 and this is used to allow linear interpolation of the 3805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * low bits. 3806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (x & 0x800) 3808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik e -= (((e >> 16) * 44938U) + 16U) >> 5; 3809b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (x & 0x400) 3811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik e -= (((e >> 16) * 45181U) + 32U) >> 6; 3812b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (x & 0x200) 3814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik e -= (((e >> 16) * 45303U) + 64U) >> 7; 3815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (x & 0x100) 3817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik e -= (((e >> 16) * 45365U) + 128U) >> 8; 3818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (x & 0x080) 3820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik e -= (((e >> 16) * 45395U) + 256U) >> 9; 3821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (x & 0x040) 3823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik e -= (((e >> 16) * 45410U) + 512U) >> 10; 3824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And handle the low 6 bits in a single block. */ 3826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik e -= (((e >> 16) * 355U * (x & 0x3fU)) + 256U) >> 9; 3827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Handle the upper bits of x. */ 3829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik e >>= x >> 16; 3830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return e; 38315f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 38325f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 3833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check for overflow */ 3834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (x <= 0) 3835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_32bit_exp[0]; 3836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Else underflow */ 3838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 3839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3841b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_byte 3842b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_exp8bit(png_fixed_point lg2) 3843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3844b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Get a 32-bit value: */ 3845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 x = png_exp(lg2); 3846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 38479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Convert the 32-bit value to 0..255 by multiplying by 256-1. Note that the 3848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * second, rounding, step can't overflow because of the first, subtraction, 3849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * step. 3850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik x -= x >> 8; 38529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return (png_byte)(((x + 0x7fffffU) >> 24) & 0xff); 3853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3855b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_16BIT_SUPPORTED 3856b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_16 3857b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_exp16bit(png_fixed_point lg2) 3858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Get a 32-bit value: */ 3860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 x = png_exp(lg2); 3861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Convert the 32-bit value to 0..65535 by multiplying by 65536-1: */ 3863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik x -= x >> 16; 3864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_uint_16)((x + 32767U) >> 16); 3865b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3866b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* 16BIT */ 3867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* FLOATING_ARITHMETIC */ 3868b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3869b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_byte 3870b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val) 3871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (value > 0 && value < 255) 38735f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 3874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED 38759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* 'value' is unsigned, ANSI-C90 requires the compiler to correctly 38769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * convert this to a floating point value. This includes values that 38779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * would overflow if 'value' were to be converted to 'int'. 38789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 38799b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * Apparently GCC, however, does an intermediate conversion to (int) 38809b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * on some (ARM) but not all (x86) platforms, possibly because of 38819b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * hardware FP limitations. (E.g. if the hardware conversion always 38829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * assumes the integer register contains a signed value.) This results 38839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * in ANSI-C undefined behavior for large values. 38849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 38859b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * Other implementations on the same machine might actually be ANSI-C90 38869b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * conformant and therefore compile spurious extra code for the large 38879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * values. 38889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 38899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * We can be reasonably sure that an unsigned to float conversion 38909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * won't be faster than an int to float one. Therefore this code 38919b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * assumes responsibility for the undefined behavior, which it knows 38929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * can't happen because of the check above. 38939b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 38949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * Note the argument to this routine is an (unsigned int) because, on 38959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 16-bit platforms, it is assigned a value which might be out of 38969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * range for an (int); that would result in undefined behavior in the 38979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * caller if the *argument* ('value') were to be declared (int). 38989b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett */ 38999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett double r = floor(255*pow((int)/*SAFE*/value/255.,gamma_val*.00001)+.5); 3900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_byte)r; 3901b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# else 3902b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_int_32 lg2 = png_log8bit(value); 3903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point res; 3904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 39059b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0) 3906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_exp8bit(res); 3907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Overflow. */ 3909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik value = 0; 3910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 39115f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 39125f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 39139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return (png_byte)(value & 0xff); 3914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3916b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_16BIT_SUPPORTED 3917b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_uint_16 3918b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val) 3919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (value > 0 && value < 65535) 39215f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 39227a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED 39237a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* The same (unsigned int)->(double) constraints apply here as above, 39247a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * however in this case the (unsigned int) to (int) conversion can 39257a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * overflow on an ANSI-C90 compliant system so the cast needs to ensure 39267a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * that this is not possible. 39277a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis */ 39287a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis double r = floor(65535*pow((png_int_32)value/65535., 39297a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis gamma_val*.00001)+.5); 39307a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis return (png_uint_16)r; 39317a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis# else 39327a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_int_32 lg2 = png_log16bit(value); 39337a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_fixed_point res; 39347a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 39357a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0) 39367a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis return png_exp16bit(res); 39377a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 39387a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* Overflow. */ 39397a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis value = 0; 39407a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis# endif 39415f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 39425f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 3943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_uint_16)value; 3944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3945b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* 16BIT */ 3946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* This does the right thing based on the bit_depth field of the 3948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * png_struct, interpreting values as 8-bit or 16-bit. While the result 3949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is nominally a 16-bit value if bit depth is 8 then the result is 3950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8-bit (as are the arguments.) 3951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3952b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_uint_16 /* PRIVATE */ 3953b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_gamma_correct(png_structrp png_ptr, unsigned int value, 3954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point gamma_val) 3955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->bit_depth == 8) 3957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_gamma_8bit_correct(value, gamma_val); 3958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3959b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_16BIT_SUPPORTED 3960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_gamma_16bit_correct(value, gamma_val); 3962b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 3963b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* should not reach this */ 3964b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return 0; 3965b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* 16BIT */ 3966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3968b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_16BIT_SUPPORTED 3969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Internal function to build a single 16-bit table - the table consists of 3970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount 3971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to shift the input values right (or 16-number_of_signifiant_bits). 3972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The caller is responsible for ensuring that the table gets cleaned up on 3974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * png_error (i.e. if one of the mallocs below fails) - i.e. the *table argument 3975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * should be somewhere that will be cleaned. 3976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3977b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 3978b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable, 39797a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) 3980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Various values derived from 'shift': */ 3982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_CONST unsigned int num = 1U << (8U - shift); 39839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED 39849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* CSE the division and work round wacky GCC warnings (see the comments 39859b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * in png_gamma_8bit_correct for where these come from.) 39869b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett */ 39879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_CONST double fmax = 1./(((png_int_32)1 << (16U - shift))-1); 39889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 3989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_CONST unsigned int max = (1U << (16U - shift))-1U; 3990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_CONST unsigned int max_by_2 = 1U << (15U-shift); 3991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int i; 3992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16pp table = *ptable = 3994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p))); 3995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i = 0; i < num; i++) 39975f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 3998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16p sub_table = table[i] = 3999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_uint_16p)png_malloc(png_ptr, 256 * (sizeof (png_uint_16))); 4000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The 'threshold' test is repeated here because it can arise for one of 4002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the 16-bit tables even if the others don't hit it. 4003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 40049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_gamma_significant(gamma_val) != 0) 4005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The old code would overflow at the end and this would cause the 4007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 'pow' function to return a result >1, resulting in an 4008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * arithmetic error. This code follows the spec exactly; ig is 4009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the recovered input sample, it always has 8-16 bits. 4010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 4011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * We want input * 65535/max, rounded, the arithmetic fits in 32 4012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * bits (unsigned) so long as max <= 32767. 4013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int j; 4015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (j = 0; j < 256; j++) 4016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 ig = (j << (8-shift)) + i; 4018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED 4019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Inline the 'max' scaling operation: */ 40209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* See png_gamma_8bit_correct for why the cast to (int) is 40219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * required here. 40229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett */ 40239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett double d = floor(65535.*pow(ig*fmax, gamma_val*.00001)+.5); 4024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sub_table[j] = (png_uint_16)d; 4025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# else 40269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (shift != 0) 4027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ig = (ig * 65535U + max_by_2)/max; 4028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sub_table[j] = png_gamma_16bit_correct(ig, gamma_val); 4030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 4031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 4034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We must still build a table, but do it the fast way. */ 4036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int j; 4037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (j = 0; j < 256; j++) 4039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 ig = (j << (8-shift)) + i; 4041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 40429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (shift != 0) 4043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ig = (ig * 65535U + max_by_2)/max; 4044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4045b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sub_table[j] = (png_uint_16)ig; 4046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 40485f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 4049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 40505f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* NOTE: this function expects the *inverse* of the overall gamma transformation 4052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * required. 4053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4054b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 4055b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable, 40567a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val) 4057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 4058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_CONST unsigned int num = 1U << (8U - shift); 4059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_CONST unsigned int max = (1U << (16U - shift))-1U; 4060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int i; 4061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 last; 40625f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16pp table = *ptable = 4064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p))); 4065b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 'num' is the number of tables and also the number of low bits of low 4067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * bits of the input 16-bit value used to select a table. Each table is 40689b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * itself indexed by the high 8 bits of the value. 4069b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i = 0; i < num; i++) 4071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik table[i] = (png_uint_16p)png_malloc(png_ptr, 4072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 256 * (sizeof (png_uint_16))); 4073b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 'gamma_val' is set to the reciprocal of the value calculated above, so 4075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pow(out,g) is an *input* value. 'last' is the last input value set. 4076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 4077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * In the loop 'i' is used to find output values. Since the output is 4078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8-bit there are only 256 possible values. The tables are set up to 4079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * select the closest possible output value for each input by finding 4080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the input value at the boundary between each pair of output values 4081b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * and filling the table up to that boundary with the lower output 4082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value. 4083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 4084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The boundary values are 0.5,1.5..253.5,254.5. Since these are 9-bit 4085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * values the code below uses a 16-bit value in i; the values start at 4086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 128.5 (for 0.5) and step by 257, for a total of 254 values (the last 4087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * entries are filled with 255). Start i at 128 and fill all 'last' 4088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * table entries <= 'max' 4089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik last = 0; 4091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i = 0; i < 255; ++i) /* 8-bit output value */ 40925f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 4093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Find the corresponding maximum input value */ 4094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16 out = (png_uint_16)(i * 257U); /* 16-bit output value */ 4095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Find the boundary value in 16 bits: */ 4097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 bound = png_gamma_16bit_correct(out+128U, gamma_val); 4098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Adjust (round) to (16-shift) bits: */ 4100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik bound = (bound * max + 32768U)/65535U + 1U; 4101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (last < bound) 4103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik table[last & (0xffU >> shift)][last >> (8U - shift)] = out; 4105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik last++; 4106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 41075f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 41085f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And fill in the final entries. */ 4110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (last < (num << 8)) 41115f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 4112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik table[last & (0xff >> shift)][last >> (8U - shift)] = 65535U; 4113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik last++; 41145f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 4115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 4116b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* 16BIT */ 41175f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Build a single 8-bit table: same as the 16-bit case but much simpler (and 4119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * typically much faster). Note that libpng currently does no sBIT processing 41209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * (apparently contrary to the spec) so a 256-entry table is always generated. 4121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4122b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 4123b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_build_8bit_table(png_structrp png_ptr, png_bytepp ptable, 41247a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_CONST png_fixed_point gamma_val) 4125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 4126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int i; 4127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256); 4128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 41299b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_gamma_significant(gamma_val) != 0) 41309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (i=0; i<256; i++) 41319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett table[i] = png_gamma_8bit_correct(i, gamma_val); 4132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 41339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else 41349b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (i=0; i<256; ++i) 41359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett table[i] = (png_byte)(i & 0xff); 4136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 4137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Used from png_read_destroy and below to release the memory used by the gamma 4139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * tables. 4140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4141b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 4142b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_destroy_gamma_table(png_structrp png_ptr) 4143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 4144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->gamma_table); 4145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->gamma_table = NULL; 4146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4147b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_16BIT_SUPPORTED 4148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->gamma_16_table != NULL) 41495f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 4150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i; 4151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int istop = (1 << (8 - png_ptr->gamma_shift)); 4152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i = 0; i < istop; i++) 4153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->gamma_16_table[i]); 4155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->gamma_16_table); 4157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->gamma_16_table = NULL; 41585f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 4159b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* 16BIT */ 41605f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ 4162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ 4163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 4164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->gamma_from_1); 4165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->gamma_from_1 = NULL; 4166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->gamma_to_1); 4167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->gamma_to_1 = NULL; 4168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4169b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_16BIT_SUPPORTED 4170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->gamma_16_from_1 != NULL) 41715f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 4172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i; 4173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int istop = (1 << (8 - png_ptr->gamma_shift)); 4174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i = 0; i < istop; i++) 4175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->gamma_16_from_1[i]); 4177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->gamma_16_from_1); 4179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->gamma_16_from_1 = NULL; 4180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->gamma_16_to_1 != NULL) 4182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i; 4184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int istop = (1 << (8 - png_ptr->gamma_shift)); 4185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i = 0; i < istop; i++) 4186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->gamma_16_to_1[i]); 4188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->gamma_16_to_1); 4190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->gamma_16_to_1 = NULL; 41915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 4192b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* 16BIT */ 4193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ 4194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 41955f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* We build the 8- or 16-bit gamma tables here. Note that for 16-bit 4197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * tables, we don't make a full table if we are reducing to 8-bit in 4198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the future. Note also how the gamma_16 tables are segmented so that 4199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * we don't need to allocate > 64K chunks for a full 16-bit table. 4200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4201b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 4202b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_build_gamma_table(png_structrp png_ptr, int bit_depth) 4203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 42047a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_debug(1, "in png_build_gamma_table"); 42057a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42067a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* Remove any existing table; this copes with multiple calls to 42077a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * png_read_update_info. The warning is because building the gamma tables 42087a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * multiple times is a performance hit - it's harmless but the ability to 42097a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * call png_read_update_info() multiple times is new in 1.5.6 so it seems 42107a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * sensible to warn if the app introduces such a hit. 42117a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis */ 42127a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (png_ptr->gamma_table != NULL || png_ptr->gamma_16_table != NULL) 42137a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 42147a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_warning(png_ptr, "gamma table being rebuilt"); 42157a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_destroy_gamma_table(png_ptr); 42167a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 42177a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42187a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (bit_depth <= 8) 42197a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 42207a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_build_8bit_table(png_ptr, &png_ptr->gamma_table, 42217a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->screen_gamma > 0 ? 42227a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_reciprocal2(png_ptr->colorspace.gamma, 42237a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->screen_gamma) : PNG_FP_1); 4224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ 4226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ 4227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 42287a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) 42297a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 42307a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1, 42317a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_reciprocal(png_ptr->colorspace.gamma)); 42327a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42337a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1, 42347a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->screen_gamma > 0 ? 42357a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_reciprocal(png_ptr->screen_gamma) : 42367a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); 42377a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 4238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ 42397a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 4240b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_16BIT_SUPPORTED 42417a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis else 42427a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 42437a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_byte shift, sig_bit; 42447a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42457a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0) 42467a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 42477a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis sig_bit = png_ptr->sig_bit.red; 42487a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42497a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (png_ptr->sig_bit.green > sig_bit) 42507a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis sig_bit = png_ptr->sig_bit.green; 42517a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42527a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (png_ptr->sig_bit.blue > sig_bit) 42537a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis sig_bit = png_ptr->sig_bit.blue; 42547a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 42557a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis else 42567a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis sig_bit = png_ptr->sig_bit.gray; 42577a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42587a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* 16-bit gamma code uses this equation: 42597a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * 42607a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * ov = table[(iv & 0xff) >> gamma_shift][iv >> 8] 42617a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * 42627a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * Where 'iv' is the input color value and 'ov' is the output value - 42637a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * pow(iv, gamma). 42647a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * 42657a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * Thus the gamma table consists of up to 256 256-entry tables. The table 42667a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * is selected by the (8-gamma_shift) most significant of the low 8 bits 42677a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * of the color value then indexed by the upper 8 bits: 42687a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * 42697a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * table[low bits][high 8 bits] 42707a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * 42717a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * So the table 'n' corresponds to all those 'iv' of: 42727a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * 42737a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * <all high 8-bit values><n << gamma_shift>..<(n+1 << gamma_shift)-1> 42747a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * 42757a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis */ 42767a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (sig_bit > 0 && sig_bit < 16U) 42777a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* shift == insignificant bits */ 42787a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis shift = (png_byte)((16U - sig_bit) & 0xff); 42797a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42807a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis else 42817a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis shift = 0; /* keep all 16 bits */ 42827a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42837a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0) 42847a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 42857a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively 42867a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * the significant bits in the *input* when the output will 42877a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * eventually be 8 bits. By default it is 11. 42887a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis */ 42897a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (shift < (16U - PNG_MAX_GAMMA_8)) 42907a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis shift = (16U - PNG_MAX_GAMMA_8); 42917a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 42927a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42937a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (shift > 8U) 42947a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis shift = 8U; /* Guarantees at least one table! */ 42957a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42967a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->gamma_shift = shift; 42977a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 42987a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now 42997a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * PNG_COMPOSE). This effectively smashed the background calculation for 43007a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * 16-bit output because the 8-bit table assumes the result will be 43017a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * reduced to 8 bits. 43027a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis */ 43037a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0) 43047a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift, 43057a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma, 43067a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->screen_gamma) : PNG_FP_1); 43077a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 43087a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis else 43097a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift, 43107a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma, 43117a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->screen_gamma) : PNG_FP_1); 4312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \ 4314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \ 4315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_READ_RGB_TO_GRAY_SUPPORTED) 43167a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0) 43177a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 43187a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift, 43197a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_reciprocal(png_ptr->colorspace.gamma)); 43207a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 43217a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* Notice that the '16 from 1' table should be full precision, however 43227a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * the lookup on this table still uses gamma_shift, so it can't be. 43237a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * TODO: fix this. 43247a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis */ 43257a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift, 43267a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) : 43277a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */); 43287a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 4329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */ 43307a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 4331b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* 16BIT */ 4332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 4333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* READ_GAMMA */ 4334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 43359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett/* HARDWARE OR SOFTWARE OPTION SUPPORT */ 4336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_SET_OPTION_SUPPORTED 4337b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint PNGAPI 4338b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_option(png_structrp png_ptr, int option, int onoff) 4339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 4340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT && 4341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (option & 1) == 0) 43425f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 43433cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III png_uint_32 mask = 3U << option; 43443cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III png_uint_32 setting = (2U + (onoff != 0)) << option; 43453cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III png_uint_32 current = png_ptr->options; 4346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 43473cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III png_ptr->options = (png_uint_32)(((current & ~mask) | setting) & 0xff); 4348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 43493cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III return (int)(current & mask) >> option; 43505f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 43515f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return PNG_OPTION_INVALID; 4353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 4354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 4355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* sRGB support */ 4357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ 4358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) 4359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* sRGB conversion tables; these are machine generated with the code in 4360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the 43613cc83ac4b563ffa7a1bae9572f5fc3c1ee5f8a10Leon Scroggins III * specification (see the article at https://en.wikipedia.org/wiki/SRGB) 4362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is used, not the gamma=1/2.2 approximation use elsewhere in libpng. 43639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * The sRGB to linear table is exact (to the nearest 16-bit linear fraction). 4364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The inverse (linear to sRGB) table has accuracies as follows: 4365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 4366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * For all possible (255*65535+1) input values: 4367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 4368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact 4369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 4370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * For the input values corresponding to the 65536 16-bit values: 4371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 4372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact 4373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 43749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * In all cases the inexact readings are only off by one. 4375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_SIMPLIFIED_READ_SUPPORTED 4378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The convert-to-sRGB table is only currently required for read. */ 4379b50c217251b086440efcdb273c22f86a06c80cbaChris Craikconst png_uint_16 png_sRGB_table[256] = 4380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 4381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 0,20,40,60,80,99,119,139, 4382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 159,179,199,219,241,264,288,313, 4383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 340,367,396,427,458,491,526,562, 4384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 599,637,677,718,761,805,851,898, 4385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 947,997,1048,1101,1156,1212,1270,1330, 4386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1391,1453,1517,1583,1651,1720,1790,1863, 4387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1937,2013,2090,2170,2250,2333,2418,2504, 4388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2592,2681,2773,2866,2961,3058,3157,3258, 4389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3360,3464,3570,3678,3788,3900,4014,4129, 4390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4247,4366,4488,4611,4736,4864,4993,5124, 4391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 5257,5392,5530,5669,5810,5953,6099,6246, 4392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 6395,6547,6700,6856,7014,7174,7335,7500, 4393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 7666,7834,8004,8177,8352,8528,8708,8889, 4394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9072,9258,9445,9635,9828,10022,10219,10417, 4395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10619,10822,11028,11235,11446,11658,11873,12090, 4396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 12309,12530,12754,12980,13209,13440,13673,13909, 4397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 14146,14387,14629,14874,15122,15371,15623,15878, 4398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 16135,16394,16656,16920,17187,17456,17727,18001, 4399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 18277,18556,18837,19121,19407,19696,19987,20281, 4400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20577,20876,21177,21481,21787,22096,22407,22721, 4401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 23038,23357,23678,24002,24329,24658,24990,25325, 4402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 25662,26001,26344,26688,27036,27386,27739,28094, 4403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 28452,28813,29176,29542,29911,30282,30656,31033, 4404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 31412,31794,32179,32567,32957,33350,33745,34143, 4405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 34544,34948,35355,35764,36176,36591,37008,37429, 4406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 37852,38278,38706,39138,39572,40009,40449,40891, 4407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 41337,41785,42236,42690,43147,43606,44069,44534, 4408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 45002,45473,45947,46423,46903,47385,47871,48359, 4409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 48850,49344,49841,50341,50844,51349,51858,52369, 4410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 52884,53401,53921,54445,54971,55500,56032,56567, 4411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 57105,57646,58190,58737,59287,59840,60396,60955, 4412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 61517,62082,62650,63221,63795,64372,64952,65535 4413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 44149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* SIMPLIFIED_READ */ 4415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The base/delta tables are required for both read and write (but currently 4417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * only the simplified versions.) 4418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4419b50c217251b086440efcdb273c22f86a06c80cbaChris Craikconst png_uint_16 png_sRGB_base[512] = 4420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 4421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 128,1782,3383,4644,5675,6564,7357,8074, 4422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 8732,9346,9921,10463,10977,11466,11935,12384, 4423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 12816,13233,13634,14024,14402,14769,15125,15473, 4424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 15812,16142,16466,16781,17090,17393,17690,17981, 4425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 18266,18546,18822,19093,19359,19621,19879,20133, 4426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20383,20630,20873,21113,21349,21583,21813,22041, 4427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 22265,22487,22707,22923,23138,23350,23559,23767, 4428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 23972,24175,24376,24575,24772,24967,25160,25352, 4429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 25542,25730,25916,26101,26284,26465,26645,26823, 4430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 27000,27176,27350,27523,27695,27865,28034,28201, 4431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 28368,28533,28697,28860,29021,29182,29341,29500, 4432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 29657,29813,29969,30123,30276,30429,30580,30730, 4433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 30880,31028,31176,31323,31469,31614,31758,31902, 4434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 32045,32186,32327,32468,32607,32746,32884,33021, 4435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 33158,33294,33429,33564,33697,33831,33963,34095, 4436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 34226,34357,34486,34616,34744,34873,35000,35127, 4437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 35253,35379,35504,35629,35753,35876,35999,36122, 4438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 36244,36365,36486,36606,36726,36845,36964,37083, 4439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 37201,37318,37435,37551,37668,37783,37898,38013, 4440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 38127,38241,38354,38467,38580,38692,38803,38915, 4441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 39026,39136,39246,39356,39465,39574,39682,39790, 4442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 39898,40005,40112,40219,40325,40431,40537,40642, 4443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 40747,40851,40955,41059,41163,41266,41369,41471, 4444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 41573,41675,41777,41878,41979,42079,42179,42279, 4445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 42379,42478,42577,42676,42775,42873,42971,43068, 4446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 43165,43262,43359,43456,43552,43648,43743,43839, 4447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 43934,44028,44123,44217,44311,44405,44499,44592, 4448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 44685,44778,44870,44962,45054,45146,45238,45329, 4449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 45420,45511,45601,45692,45782,45872,45961,46051, 4450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 46140,46229,46318,46406,46494,46583,46670,46758, 4451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 46846,46933,47020,47107,47193,47280,47366,47452, 4452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 47538,47623,47709,47794,47879,47964,48048,48133, 4453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 48217,48301,48385,48468,48552,48635,48718,48801, 4454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 48884,48966,49048,49131,49213,49294,49376,49458, 4455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 49539,49620,49701,49782,49862,49943,50023,50103, 4456b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 50183,50263,50342,50422,50501,50580,50659,50738, 4457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 50816,50895,50973,51051,51129,51207,51285,51362, 4458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 51439,51517,51594,51671,51747,51824,51900,51977, 4459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 52053,52129,52205,52280,52356,52432,52507,52582, 4460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 52657,52732,52807,52881,52956,53030,53104,53178, 4461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 53252,53326,53400,53473,53546,53620,53693,53766, 4462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 53839,53911,53984,54056,54129,54201,54273,54345, 4463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 54417,54489,54560,54632,54703,54774,54845,54916, 4464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 54987,55058,55129,55199,55269,55340,55410,55480, 4465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 55550,55620,55689,55759,55828,55898,55967,56036, 4466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 56105,56174,56243,56311,56380,56448,56517,56585, 4467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 56653,56721,56789,56857,56924,56992,57059,57127, 4468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 57194,57261,57328,57395,57462,57529,57595,57662, 4469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 57728,57795,57861,57927,57993,58059,58125,58191, 4470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 58256,58322,58387,58453,58518,58583,58648,58713, 4471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 58778,58843,58908,58972,59037,59101,59165,59230, 4472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 59294,59358,59422,59486,59549,59613,59677,59740, 4473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 59804,59867,59930,59993,60056,60119,60182,60245, 4474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 60308,60370,60433,60495,60558,60620,60682,60744, 4475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 60806,60868,60930,60992,61054,61115,61177,61238, 4476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 61300,61361,61422,61483,61544,61605,61666,61727, 4477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 61788,61848,61909,61969,62030,62090,62150,62211, 4478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 62271,62331,62391,62450,62510,62570,62630,62689, 4479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 62749,62808,62867,62927,62986,63045,63104,63163, 4480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 63222,63281,63340,63398,63457,63515,63574,63632, 4481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 63691,63749,63807,63865,63923,63981,64039,64097, 4482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 64155,64212,64270,64328,64385,64443,64500,64557, 4483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 64614,64672,64729,64786,64843,64900,64956,65013, 4484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 65070,65126,65183,65239,65296,65352,65409,65465 4485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 4486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4487b50c217251b086440efcdb273c22f86a06c80cbaChris Craikconst png_byte png_sRGB_delta[512] = 4488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 4489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54, 4490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36, 4491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28, 4492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24, 4493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21, 4494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19, 4495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17, 4496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16, 4497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15, 4498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14, 4499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13, 4500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12, 4501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12, 4502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11, 4503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, 4504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11, 4505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, 4506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, 4507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10, 4508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 4509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 4510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 4511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9, 4512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 4513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 4514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 4515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 4516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, 4517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7, 4518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 4519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, 4520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7 4521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik}; 4522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* SIMPLIFIED READ/WRITE sRGB support */ 4523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* SIMPLIFIED READ/WRITE SUPPORT */ 4525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ 4526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) 4527b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 4528b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_free_function(png_voidp argument) 4529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 4530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = png_voidcast(png_imagep, argument); 4531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_controlp cp = image->opaque; 4532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_control c; 4533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Double check that we have a png_ptr - it should be impossible to get here 4535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * without one. 45365f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott */ 4537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (cp->png_ptr == NULL) 4538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 45395f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* First free any data held in the control structure. */ 4541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_STDIO_SUPPORTED 45429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (cp->owned_file != 0) 45435f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 4544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr); 4545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cp->owned_file = 0; 45465f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Ignore errors here. */ 4548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fp != NULL) 4549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cp->png_ptr->io_ptr = NULL; 4551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)fclose(fp); 4552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 45535f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 4554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 4555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Copy the control structure so that the original, allocated, version can be 4557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * safely freed. Notice that a png_error here stops the remainder of the 4558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * cleanup, but this is probably fine because that would indicate bad memory 4559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * problems anyway. 4560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c = *cp; 4562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque = &c; 4563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(c.png_ptr, cp); 4564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Then the structures, calling the correct API. */ 45669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (c.for_write != 0) 4567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED 4569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_write_struct(&c.png_ptr, &c.info_ptr); 4570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# else 4571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(c.png_ptr, "simplified write not supported"); 4572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 4573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 4575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_SIMPLIFIED_READ_SUPPORTED 4577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL); 4578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# else 4579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(c.png_ptr, "simplified read not supported"); 4580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 45815f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 45825f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Success. */ 4584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 4585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 4586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4587b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 4588b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_free(png_imagep image) 4589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 4590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Safely call the real function, but only if doing so is safe at this point 4591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (if not inside an error handling context). Otherwise assume 4592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * png_safe_execute will call this API after the return. 4593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image != NULL && image->opaque != NULL && 4595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque->error_buf == NULL) 45965f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 4597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Ignore errors here: */ 4598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)png_safe_execute(image, png_image_free_function, image); 4599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque = NULL; 46005f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 4601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 46025f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 4603b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint /* PRIVATE */ 4604b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_error(png_imagep image, png_const_charp error_message) 4605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 4606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Utility to log an error. */ 4607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_safecat(image->message, (sizeof image->message), 0, error_message); 4608b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->warning_or_error |= PNG_IMAGE_ERROR; 4609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_free(image); 4610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 46115f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott} 4612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* SIMPLIFIED READ/WRITE */ 46149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* READ || WRITE */ 4615