1893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* pngread.c - read a PNG file 3893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 4b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Last changed in libpng 1.6.10 [March 6, 2014] 5b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * Copyright (c) 1998-2014 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.) 8893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 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 12a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * 13893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * This file contains routines that an application calls directly to 14893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * read a PNG file or stream. 15893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 16893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 17b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include "pngpriv.h" 18b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) 19b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# include <errno.h> 20b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 215f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 22b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_SUPPORTED 23893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 24893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Create a PNG structure for reading, and allocate any memory needed. */ 25b50c217251b086440efcdb273c22f86a06c80cbaChris CraikPNG_FUNCTION(png_structp,PNGAPI 26b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr, 27b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) 28893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 29b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifndef PNG_USER_MEM_SUPPORTED 30b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, 31b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error_fn, warn_fn, NULL, NULL, NULL); 32b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else 33b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_create_read_struct_2(user_png_ver, error_ptr, error_fn, 34b50c217251b086440efcdb273c22f86a06c80cbaChris Craik warn_fn, NULL, NULL, NULL); 35893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 36893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 375f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott/* Alternate create PNG structure for reading, and allocate any memory 385f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott * needed. 395f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott */ 40b50c217251b086440efcdb273c22f86a06c80cbaChris CraikPNG_FUNCTION(png_structp,PNGAPI 41b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, 42b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, 43b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) 44893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 45b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr, 46b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); 47893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif /* PNG_USER_MEM_SUPPORTED */ 48893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 49b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr != NULL) 50893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 51b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->mode = PNG_IS_READ_STRUCT; 52893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 53b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Added in libpng-1.6.0; this can be used to detect a read structure if 54b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * required (it will be zero in a write structure.) 55b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 56b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_SEQUENTIAL_READ_SUPPORTED 57b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE; 58b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 595f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 60b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED 61b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; 625f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 63b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* In stable builds only warn if an application error can be completely 64b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * handled. 65b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 66b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC 67b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; 68b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 69b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 70b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 71b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* TODO: delay this, it can be done in png_init_io (if the app doesn't 72b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * do it itself) avoiding setting the default function if it is not 73b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * required. 745f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott */ 75b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_read_fn(png_ptr, NULL, NULL); 76b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 77b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#ifdef PNG_INDEX_SUPPORTED 78b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_ptr->index = NULL; 79b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#endif 80893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 81893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 82b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_ptr; 83893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 84893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 85893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 865f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 87893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Read the information before the actual image data. This has been 88893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * changed in v0.90 to allow reading a file that already has the magic 89893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * bytes read from the stream. You can tell libpng how many bytes have 90893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * been read from the beginning of the stream (up to the maximum of 8) 91893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * via png_set_sig_bytes(), and we will only check the remaining bytes 92893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * here. The application can then have access to the signature bytes we 93893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * read if it is determined that this isn't a valid PNG file. 94893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 95893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 96b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_read_info(png_structrp png_ptr, png_inforp info_ptr) 97893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 98b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 99b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int keep; 100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1025f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_debug(1, "in png_read_info"); 103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 104a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL || info_ptr == NULL) 105a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Read and check the PNG file signature. */ 108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_sig(png_ptr, info_ptr); 109893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1104215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project for (;;) 111893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1124215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_uint_32 length = png_read_chunk_header(png_ptr); 113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 chunk_name = png_ptr->chunk_name; 114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* IDAT logic needs to happen here to simplify getting the two flags 116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * right. 117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (chunk_name == png_IDAT) 119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!(png_ptr->mode & PNG_HAVE_IHDR)) 121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_chunk_error(png_ptr, "Missing IHDR before IDAT"); 122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && 124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik !(png_ptr->mode & PNG_HAVE_PLTE)) 125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_chunk_error(png_ptr, "Missing PLTE before IDAT"); 126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (png_ptr->mode & PNG_AFTER_IDAT) 128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_chunk_benign_error(png_ptr, "Too many IDATs found"); 129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->mode |= PNG_HAVE_IDAT; 131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (png_ptr->mode & PNG_HAVE_IDAT) 134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->mode |= PNG_AFTER_IDAT; 135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 136893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* This should be a binary subdivision search or a hash for 137893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * matching the chunk name rather than a linear search. 138893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (chunk_name == png_IHDR) 140893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_IHDR(png_ptr, info_ptr, length); 141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_IEND) 143893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_IEND(png_ptr, info_ptr, length); 144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 145893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) 147893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_handle_unknown(png_ptr, info_ptr, length, keep); 149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (chunk_name == png_PLTE) 151893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->mode |= PNG_HAVE_PLTE; 152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_IDAT) 154893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->idat_size = 0; /* It has been consumed */ 156893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 157893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 158893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 159893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_PLTE) 161893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_PLTE(png_ptr, info_ptr, length); 162893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_IDAT) 164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 165893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->idat_size = length; 166893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 167893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1695f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_bKGD_SUPPORTED 170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_bKGD) 171893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_bKGD(png_ptr, info_ptr, length); 172893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1745f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_cHRM_SUPPORTED 175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_cHRM) 176893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_cHRM(png_ptr, info_ptr, length); 177893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1795f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_gAMA_SUPPORTED 180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_gAMA) 181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_gAMA(png_ptr, info_ptr, length); 182893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1845f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_hIST_SUPPORTED 185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_hIST) 186893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_hIST(png_ptr, info_ptr, length); 187893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1895f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_oFFs_SUPPORTED 190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_oFFs) 191893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_oFFs(png_ptr, info_ptr, length); 192893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_pCAL_SUPPORTED 195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_pCAL) 196893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_pCAL(png_ptr, info_ptr, length); 197893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1995f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sCAL_SUPPORTED 200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_sCAL) 201893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_sCAL(png_ptr, info_ptr, length); 202893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2045f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_pHYs_SUPPORTED 205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_pHYs) 206893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_pHYs(png_ptr, info_ptr, length); 207893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2095f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sBIT_SUPPORTED 210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_sBIT) 211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_sBIT(png_ptr, info_ptr, length); 212893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2145f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sRGB_SUPPORTED 215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_sRGB) 216893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_sRGB(png_ptr, info_ptr, length); 217893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2195f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_iCCP_SUPPORTED 220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_iCCP) 221893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_iCCP(png_ptr, info_ptr, length); 222893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2245f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sPLT_SUPPORTED 225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_sPLT) 226893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_sPLT(png_ptr, info_ptr, length); 227893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2295f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_tEXt_SUPPORTED 230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_tEXt) 231893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_tEXt(png_ptr, info_ptr, length); 232893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2345f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_tIME_SUPPORTED 235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_tIME) 236893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_tIME(png_ptr, info_ptr, length); 237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2395f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_tRNS_SUPPORTED 240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_tRNS) 241893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_tRNS(png_ptr, info_ptr, length); 242893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2445f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_zTXt_SUPPORTED 245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_zTXt) 246893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_zTXt(png_ptr, info_ptr, length); 247893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2495f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_iTXt_SUPPORTED 250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_iTXt) 251893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_iTXt(png_ptr, info_ptr, length); 252893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 254893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_handle_unknown(png_ptr, info_ptr, length, 256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_HANDLE_CHUNK_AS_DEFAULT); 257893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 258893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 2595f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 260893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 261a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Optional call to update the users info_ptr structure */ 262893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 263b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_read_update_info(png_structrp png_ptr, png_inforp info_ptr) 264893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 2654215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_read_update_info"); 2665f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr != NULL) 268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 269b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#ifdef PNG_INDEX_SUPPORTED 270b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari if (png_ptr->index) { 271b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_read_start_row(png_ptr); 272b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari } 273b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#endif 274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) 275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_start_row(png_ptr); 277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_READ_TRANSFORMS_SUPPORTED 279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_transform_info(png_ptr, info_ptr); 280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# else 281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_UNUSED(info_ptr) 282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 284b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#ifndef PNG_INDEX_SUPPORTED 285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* New in 1.6.0 this avoids the bug of doing the initializations twice */ 286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_app_error(png_ptr, 288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_read_update_info/png_start_read_image: duplicate call"); 289b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#endif 290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 291893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 292893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2935f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 294893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Initialize palette, background, etc, after transformations 295893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * are set, but before any reading takes place. This allows 296893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * the user to obtain a gamma-corrected palette, for example. 297893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * If the user doesn't call this, we will do it ourselves. 298893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 299893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 300b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_start_read_image(png_structrp png_ptr) 301893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 3024215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_start_read_image"); 303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr != NULL) 305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0) 307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_start_row(png_ptr); 308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* New in 1.6.0 this avoids the bug of doing the initializations twice */ 310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_app_error(png_ptr, 312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_start_read_image/png_read_update_info: duplicate call"); 313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 314893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 3155f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 316893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 3175f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 318b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_MNG_FEATURES_SUPPORTED 319b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Undoes intrapixel differencing, 320b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * NOTE: this is apparently only supported in the 'sequential' reader. 321b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 322b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 323b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_do_read_intrapixel(png_row_infop row_info, png_bytep row) 324b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 325b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_debug(1, "in png_do_read_intrapixel"); 326b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 327b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ( 328b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari (row_info->color_type & PNG_COLOR_MASK_COLOR)) 329b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 330b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int bytes_per_pixel; 331b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 row_width = row_info->width; 332b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 333b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (row_info->bit_depth == 8) 334b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 335b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_bytep rp; 336b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 i; 337b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 338b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (row_info->color_type == PNG_COLOR_TYPE_RGB) 339b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bytes_per_pixel = 3; 340b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 341b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 342b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bytes_per_pixel = 4; 343b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 344b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 345b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return; 346b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 347b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 348b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 349b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff); 350b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff); 351b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 352b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 353b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (row_info->bit_depth == 16) 354b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 355b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_bytep rp; 356b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 i; 357b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 358b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (row_info->color_type == PNG_COLOR_TYPE_RGB) 359b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bytes_per_pixel = 6; 360b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 361b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 362b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bytes_per_pixel = 8; 363b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 364b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 365b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return; 366b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 367b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 368b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 369b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); 370b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); 371b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); 372b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 red = (s0 + s1 + 65536) & 0xffff; 373b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 blue = (s2 + s1 + 65536) & 0xffff; 374b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *(rp ) = (png_byte)((red >> 8) & 0xff); 375b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *(rp + 1) = (png_byte)(red & 0xff); 376b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *(rp + 4) = (png_byte)((blue >> 8) & 0xff); 377b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari *(rp + 5) = (png_byte)(blue & 0xff); 378b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 379b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 380b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 381b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 382b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#endif /* PNG_MNG_FEATURES_SUPPORTED */ 383b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 384893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 385b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row) 386893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_row_info row_info; 388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 389a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 390a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3924215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug2(1, "in png_read_row (row %lu, pass %d)", 393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (unsigned long)png_ptr->row_number, png_ptr->pass); 3945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* png_read_start_row sets the information (in particular iwidth) for this 396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * interlace pass. 397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 398893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) 399893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_start_row(png_ptr); 400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 1.5.6: row_info moved out of png_struct to a local here. */ 402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.width = png_ptr->iwidth; /* NOTE: width of current interlaced row */ 403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.color_type = png_ptr->color_type; 404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.bit_depth = png_ptr->bit_depth; 405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.channels = png_ptr->channels; 406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.pixel_depth = png_ptr->pixel_depth; 407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); 408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 409893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->row_number == 0 && png_ptr->pass == 0) 410893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 411a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Check for transforms that have been set but were defined out */ 412893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED) 413893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->transformations & PNG_INVERT_MONO) 414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined"); 415893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 417893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED) 418893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->transformations & PNG_FILLER) 419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined"); 420893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4225f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ 4235f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott !defined(PNG_READ_PACKSWAP_SUPPORTED) 424893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->transformations & PNG_PACKSWAP) 425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined"); 426893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 428893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED) 429893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->transformations & PNG_PACK) 430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined"); 431893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED) 434893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->transformations & PNG_SHIFT) 435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined"); 436893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 438893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED) 439893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->transformations & PNG_BGR) 440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined"); 441893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 443893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED) 444893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->transformations & PNG_SWAP_BYTES) 445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined"); 446893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 447893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 448893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 4495f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_INTERLACING_SUPPORTED 450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If interlaced and we do not need a new row, combine row and return. 451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Notice that the pixels we have from previous rows have been transformed 452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * already; we can only combine like with like (transformed or 453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * untransformed) and, because of the libpng API for interlaced images, this 454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * means we must transform before de-interlacing. 455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 456893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE)) 457893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 458893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project switch (png_ptr->pass) 459893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 460893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 0: 461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->row_number & 0x07) 462893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 463893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (dsp_row != NULL) 464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_combine_row(png_ptr, dsp_row, 1/*display*/); 465893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_finish_row(png_ptr); 466893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 467893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 470893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 1: 471893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ((png_ptr->row_number & 0x07) || png_ptr->width < 5) 472893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 473893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (dsp_row != NULL) 474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_combine_row(png_ptr, dsp_row, 1/*display*/); 475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 476893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_finish_row(png_ptr); 477893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 478893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 479893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 481893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 2: 482893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ((png_ptr->row_number & 0x07) != 4) 483893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 484893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (dsp_row != NULL && (png_ptr->row_number & 4)) 485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_combine_row(png_ptr, dsp_row, 1/*display*/); 486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 487893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_finish_row(png_ptr); 488893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 489893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 490893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 492893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 3: 493893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ((png_ptr->row_number & 3) || png_ptr->width < 3) 494893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 495893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (dsp_row != NULL) 496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_combine_row(png_ptr, dsp_row, 1/*display*/); 497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 498893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_finish_row(png_ptr); 499893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 500893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 501893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 503893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 4: 504893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ((png_ptr->row_number & 3) != 2) 505893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 506893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (dsp_row != NULL && (png_ptr->row_number & 2)) 507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_combine_row(png_ptr, dsp_row, 1/*display*/); 508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 509893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_finish_row(png_ptr); 510893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 511893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 512893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 514893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 5: 515893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ((png_ptr->row_number & 1) || png_ptr->width < 2) 516893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 517893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (dsp_row != NULL) 518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_combine_row(png_ptr, dsp_row, 1/*display*/); 519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 520893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_finish_row(png_ptr); 521893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 522893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 523893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 526893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 6: 527893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (!(png_ptr->row_number & 1)) 528893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 529893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_finish_row(png_ptr); 530893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 531893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 532893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 533893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 534893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 535893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 536893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 537893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (!(png_ptr->mode & PNG_HAVE_IDAT)) 538893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_error(png_ptr, "Invalid attempt to read row data"); 539893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Fill the row with IDAT data: */ 541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1); 542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE) 544893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->row_buf[0] < PNG_FILTER_VALUE_LAST) 546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_filter_row(png_ptr, &row_info, png_ptr->row_buf + 1, 547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->prev_row + 1, png_ptr->row_buf[0]); 548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "bad adaptive filter value"); 550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* libpng 1.5.6: the following line was copying png_ptr->rowbytes before 553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1.5.6, while the buffer really is this big in current versions of libpng 554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it may not be in the future, so this was changed just to copy the 555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * interlaced count: 556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1); 558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_MNG_FEATURES_SUPPORTED 560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && 561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) 562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Intrapixel differencing */ 564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_do_read_intrapixel(&row_info, png_ptr->row_buf + 1); 565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 5664ce0ee15f268e0161438b4133936cb2826f7fd50Joseph Wen#endif 5674ce0ee15f268e0161438b4133936cb2826f7fd50Joseph Wen 568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_TRANSFORMS_SUPPORTED 569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->transformations) 570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_do_read_transformations(png_ptr, &row_info); 5714ce0ee15f268e0161438b4133936cb2826f7fd50Joseph Wen#endif 572893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The transformed pixel depth should match the depth now in row_info. */ 574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->transformed_pixel_depth == 0) 575893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->transformed_pixel_depth = row_info.pixel_depth; 577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (row_info.pixel_depth > png_ptr->maximum_pixel_depth) 578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "sequential row overflow"); 579893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 580893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (png_ptr->transformed_pixel_depth != row_info.pixel_depth) 582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "internal sequential row size calculation error"); 583893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 5845f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_INTERLACING_SUPPORTED 585a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Blow up interlaced rows to full size */ 586893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->interlaced && 587893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project (png_ptr->transformations & PNG_INTERLACE)) 588893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 589893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->pass < 6) 590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass, 591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->transformations); 592893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 593893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (dsp_row != NULL) 594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_combine_row(png_ptr, dsp_row, 1/*display*/); 595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 596893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (row != NULL) 597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_combine_row(png_ptr, row, 0/*row*/); 598893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 600893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 601893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 602893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 603893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (row != NULL) 604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_combine_row(png_ptr, row, -1/*ignored*/); 605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 606893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (dsp_row != NULL) 607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_combine_row(png_ptr, dsp_row, -1/*ignored*/); 608893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 609893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_finish_row(png_ptr); 610893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 611893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->read_row_fn != NULL) 612893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project (*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); 613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 614893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 6155f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 616893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 6175f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 618893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Read one or more rows of image data. If the image is interlaced, 619893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * and png_set_interlace_handling() has been called, the rows need to 620893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * contain the contents of the rows from the previous pass. If the 621893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * image has alpha or transparency, and png_handle_alpha()[*] has been 622893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * called, the rows contents must be initialized to the contents of the 623893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * screen. 624893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 625893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * "row" holds the actual image, and pixels are placed in it 626893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * as they arrive. If the image is displayed after each pass, it will 627893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * appear to "sparkle" in. "display_row" can be used to display a 628893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * "chunky" progressive image, with finer detail added as it becomes 629893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * available. If you do not want this "chunky" display, you may pass 630893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * NULL for display_row. If you do not want the sparkle display, and 631893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * you have not called png_handle_alpha(), you may pass NULL for rows. 632893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * If you have called png_handle_alpha(), and the image has either an 633893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * alpha channel or a transparency chunk, you must provide a buffer for 634893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * rows. In this case, you do not have to provide a display_row buffer 635893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * also, but you may. If the image is not interlaced, or if you have 636893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * not called png_set_interlace_handling(), the display_row buffer will 637893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * be ignored, so pass NULL to it. 638893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 639893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * [*] png_handle_alpha() does not exist yet, as of this version of libpng 640893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 641893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 642893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 643b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_read_rows(png_structrp png_ptr, png_bytepp row, 644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytepp display_row, png_uint_32 num_rows) 645893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 646893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_uint_32 i; 647893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytepp rp; 648893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytepp dp; 649893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 6504215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_read_rows"); 651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 652a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 653a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 655893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project rp = row; 656893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project dp = display_row; 657893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (rp != NULL && dp != NULL) 658893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0; i < num_rows; i++) 659893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 660893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep rptr = *rp++; 661893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep dptr = *dp++; 662893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 663893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_row(png_ptr, rptr, dptr); 664893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 6664215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project else if (rp != NULL) 667893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0; i < num_rows; i++) 668893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 669893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep rptr = *rp; 670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_row(png_ptr, rptr, NULL); 671893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project rp++; 672893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 6744215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project else if (dp != NULL) 675893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0; i < num_rows; i++) 676893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 677893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep dptr = *dp; 678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_row(png_ptr, NULL, dptr); 679893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project dp++; 680893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 681893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 6825f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 683893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 684b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#ifdef PNG_INDEX_SUPPORTED 685b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#define IDAT_HEADER_SIZE 8 686b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 687b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari/* Set the png read position to a new position based on idat_position and 688b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari * offset. 689b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari */ 690b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurarivoid 691b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripuraripng_set_read_offset(png_structp png_ptr, 692b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_uint_32 idat_position, png_uint_32 bytes_left) 693b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari{ 694b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_seek_data(png_ptr, idat_position); 695b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_ptr->idat_size = png_read_chunk_header(png_ptr); 696b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 697b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // We need to add back IDAT_HEADER_SIZE because in zlib's perspective, 698b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // IDAT_HEADER in PNG is already stripped out. 699b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_seek_data(png_ptr, idat_position + IDAT_HEADER_SIZE + png_ptr->idat_size - bytes_left); 700b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_ptr->idat_size = bytes_left; 701b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari} 702b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 703b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari/* Configure png decoder to decode the pass starting from *row. 704b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari * The requested row may be adjusted to align with an indexing row. 705b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari * The actual row for the decoder to start its decoding will be returned in 706b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari * *row. 707b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari */ 708b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurarivoid PNGAPI 709b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripuraripng_configure_decoder(png_structp png_ptr, int *row, int pass) 710b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari{ 711b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_indexp index = png_ptr->index; 712b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari int n = *row / index->step[pass]; 713b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_line_indexp line_index = index->pass_line_index[pass][n]; 714b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 715b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // Adjust row to an indexing row. 716b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari *row = n * index->step[pass]; 717b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_ptr->row_number = *row; 718b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 719b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#ifdef PNG_READ_INTERLACING_SUPPORTED 720b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari if (png_ptr->interlaced) 721b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_set_interlaced_pass(png_ptr, pass); 722b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#endif 723b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 724b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari long row_byte_length = 725b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1; 726b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 727b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari inflateEnd(&png_ptr->zstream); 728b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari inflateCopy(&png_ptr->zstream, line_index->z_state); 729b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 730b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // Set the png read position to line_index. 731b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_set_read_offset(png_ptr, line_index->stream_idat_position, 732b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari line_index->bytes_left_in_idat); 733b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari memcpy(png_ptr->prev_row, line_index->prev_row, row_byte_length); 734b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_ptr->zstream.avail_in = 0; 735b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari} 736b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 737b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari/* Build the line index and store the index in png_ptr->index. 738b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari */ 739b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurarivoid PNGAPI 740b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripuraripng_build_index(png_structp png_ptr) 741b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari{ 742b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // number of rows in a 8x8 block for each interlaced pass. 743b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari int number_rows_in_pass[7] = {1, 1, 1, 2, 2, 4, 4}; 744b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 745b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari int ret; 746b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_uint_32 i, j; 747b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_bytep rp; 748b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari int p, pass_number = 1; 749b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 750b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#ifdef PNG_READ_INTERLACING_SUPPORTED 751b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari pass_number = png_set_interlace_handling(png_ptr); 752b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#endif 753b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 754b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari if (png_ptr == NULL) 755b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari return; 756b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 757b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_read_start_row(png_ptr); 758b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 759b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#ifdef PNG_READ_INTERLACING_SUPPORTED 760b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari if (!png_ptr->interlaced) 761b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#endif 762b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari { 763b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari number_rows_in_pass[0] = 8; 764b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari } 765b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 766d3ff9df7a1191da1c47710ea8bd568204e74a976Henrik Smiding // Allocate a buffer big enough for any transform. 767d3ff9df7a1191da1c47710ea8bd568204e74a976Henrik Smiding rp = png_malloc(png_ptr, PNG_ROWBYTES(png_ptr->maximum_pixel_depth, png_ptr->width)); 768b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 769b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_indexp index = png_malloc(png_ptr, sizeof(png_index)); 770b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_ptr->index = index; 771b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 772b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari index->stream_idat_position = png_ptr->total_data_read - IDAT_HEADER_SIZE; 773b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 774b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // Set the default size of index in each pass to 0, 775b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // so that we can free index correctly in png_destroy_read_struct. 776b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari for (p = 0; p < 7; p++) 777b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari index->size[p] = 0; 778b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 779b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari for (p = 0; p < pass_number; p++) 780b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari { 781b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // We adjust the index step in each pass to make sure each pass 782b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // has roughly the same size of index. 783b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // This way, we won't consume to much memory in recording index. 784b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari index->step[p] = INDEX_SAMPLE_SIZE * (8 / number_rows_in_pass[p]); 785d3ff9df7a1191da1c47710ea8bd568204e74a976Henrik Smiding const png_uint_32 temp_size = 786b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari (png_ptr->height + index->step[p] - 1) / index->step[p]; 787b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari index->pass_line_index[p] = 7888594e1a8521b2cbdd941719b929b15ba943b1d4aDerek Sollenberger png_malloc(png_ptr, temp_size * sizeof(png_line_indexp)); 789b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 790b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // Get the row_byte_length seen by the filter. This value may be 791b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // different from the row_byte_length of a bitmap in the case of 792b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // color palette mode. 793b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari int row_byte_length = 794b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1; 795b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 796b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // Now, we record index for each indexing row. 7978594e1a8521b2cbdd941719b929b15ba943b1d4aDerek Sollenberger for (i = 0; i < temp_size; i++) 798b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari { 799b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_line_indexp line_index = png_malloc(png_ptr, sizeof(png_line_index)); 800b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari index->pass_line_index[p][i] = line_index; 801b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 802b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari line_index->z_state = png_malloc(png_ptr, sizeof(z_stream)); 803b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari inflateCopy(line_index->z_state, &png_ptr->zstream); 804b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari line_index->prev_row = png_malloc(png_ptr, row_byte_length); 805b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari memcpy(line_index->prev_row, png_ptr->prev_row, row_byte_length); 806b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari line_index->stream_idat_position = index->stream_idat_position; 807b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari line_index->bytes_left_in_idat = png_ptr->idat_size + png_ptr->zstream.avail_in; 808b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 8098594e1a8521b2cbdd941719b929b15ba943b1d4aDerek Sollenberger // increment the size now that we have the backing data structures. 8108594e1a8521b2cbdd941719b929b15ba943b1d4aDerek Sollenberger // This prevents a crash in the event that png_read_row fails and 8118594e1a8521b2cbdd941719b929b15ba943b1d4aDerek Sollenberger // we need to cleanup the partially constructed png_index_struct; 8128594e1a8521b2cbdd941719b929b15ba943b1d4aDerek Sollenberger index->size[p] += 1; 8138594e1a8521b2cbdd941719b929b15ba943b1d4aDerek Sollenberger 814b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari // Skip the "step" number of rows to the next indexing row. 815b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari for (j = 0; j < index->step[p] && 816b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari i * index->step[p] + j < png_ptr->height; j++) 817b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari { 818b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_read_row(png_ptr, rp, NULL); 819b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari } 820b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari } 821b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari } 822b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_free(png_ptr, rp); 823b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari} 824b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#endif 825b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 8265f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 827893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Read the entire image. If the image has an alpha channel or a tRNS 828893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * chunk, and you have called png_handle_alpha()[*], you will need to 829893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * initialize the image to the current image that PNG will be overlaying. 830893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * We set the num_rows again here, in case it was incorrectly set in 831893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * png_read_start_row() by a call to png_read_update_info() or 832893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * png_start_read_image() if png_set_interlace_handling() wasn't called 833893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * prior to either of these functions like it should have been. You can 834893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * only call this function once. If you desire to have an image for 835893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * each pass of a interlaced image, use png_read_rows() instead. 836893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 837893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * [*] png_handle_alpha() does not exist yet, as of this version of libpng 838893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 839893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 840b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_read_image(png_structrp png_ptr, png_bytepp image) 841893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 8424215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_uint_32 i, image_height; 843893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int pass, j; 844893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytepp rp; 845893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 8464215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_read_image"); 847b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 848a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 849a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 850893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 851893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_READ_INTERLACING_SUPPORTED 852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!(png_ptr->flags & PNG_FLAG_ROW_INIT)) 853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pass = png_set_interlace_handling(png_ptr); 855b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And make sure transforms are initialized. */ 856b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_start_read_image(png_ptr); 857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE)) 861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Caller called png_start_read_image or png_read_update_info without 863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * first turning on the PNG_INTERLACE transform. We can fix this here, 864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * but the caller should do it! 865b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Interlace handling should be turned on when " 867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "using png_read_image"); 868b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Make sure this is set correctly */ 869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->num_rows = png_ptr->height; 870b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Obtain the pass number, which also turns on the PNG_INTERLACE flag in 873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the above error case. 874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik pass = png_set_interlace_handling(png_ptr); 876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 877893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 878893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->interlaced) 879893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_error(png_ptr, 880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "Cannot read interlaced image -- interlace handler disabled"); 881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 882893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project pass = 1; 883893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 884893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 885893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project image_height=png_ptr->height; 886893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 887893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (j = 0; j < pass; j++) 888893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 889893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project rp = image; 890893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0; i < image_height; i++) 891893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_row(png_ptr, *rp, NULL); 893893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project rp++; 894893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 895893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 896893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 8975f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 898893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 8995f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 900893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Read the end of the PNG file. Will not read past the end of the 901893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * file, will verify the end is accurate, and will read any comments 902893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * or time information at the end of the file, if info is not NULL. 903893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 904893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 905b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_read_end(png_structrp png_ptr, png_inforp info_ptr) 906893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int keep; 909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9114215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_read_end"); 912b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 913a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 914a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 915893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 916b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If png_read_end is called in the middle of reading the rows there may 917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * still be pending IDAT data and an owned zstream. Deal with this here. 918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!png_chunk_unknown_handling(png_ptr, png_IDAT)) 921893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_finish_IDAT(png_ptr); 923b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED 925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Report invalid palette index; added at libng-1.5.10 */ 926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE && 927b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->num_palette_max > png_ptr->num_palette) 928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_benign_error(png_ptr, "Read palette index exceeding num_palette"); 929893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do 932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 9334215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_uint_32 length = png_read_chunk_header(png_ptr); 934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 chunk_name = png_ptr->chunk_name; 935893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 936b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (chunk_name == png_IEND) 937b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_handle_IEND(png_ptr, info_ptr, length); 938b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 939b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (chunk_name == png_IHDR) 940893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_IHDR(png_ptr, info_ptr, length); 941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 942b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (info_ptr == NULL) 943b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_crc_finish(png_ptr, length); 944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 945893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0) 947893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (chunk_name == png_IDAT) 949893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 950893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) 951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_benign_error(png_ptr, "Too many IDATs found"); 952893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_handle_unknown(png_ptr, info_ptr, length, keep); 954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (chunk_name == png_PLTE) 955893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->mode |= PNG_HAVE_PLTE; 956893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 957893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_IDAT) 960893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 961893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Zero length IDATs are legal after the last IDAT has been 962893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * read, but not after other chunks have been read. 963893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 964893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT)) 965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_benign_error(png_ptr, "Too many IDATs found"); 966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 967893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_crc_finish(png_ptr, length); 968893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_PLTE) 970893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_PLTE(png_ptr, info_ptr, length); 971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9725f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_bKGD_SUPPORTED 973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_bKGD) 974893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_bKGD(png_ptr, info_ptr, length); 975893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9775f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_cHRM_SUPPORTED 978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_cHRM) 979893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_cHRM(png_ptr, info_ptr, length); 980893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9825f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_gAMA_SUPPORTED 983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_gAMA) 984893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_gAMA(png_ptr, info_ptr, length); 985893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9875f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_hIST_SUPPORTED 988b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_hIST) 989893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_hIST(png_ptr, info_ptr, length); 990893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9925f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_oFFs_SUPPORTED 993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_oFFs) 994893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_oFFs(png_ptr, info_ptr, length); 995893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9975f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_pCAL_SUPPORTED 998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_pCAL) 999893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_pCAL(png_ptr, info_ptr, length); 1000893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10025f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sCAL_SUPPORTED 1003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_sCAL) 1004893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_sCAL(png_ptr, info_ptr, length); 1005893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10075f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_pHYs_SUPPORTED 1008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_pHYs) 1009893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_pHYs(png_ptr, info_ptr, length); 1010893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10125f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sBIT_SUPPORTED 1013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_sBIT) 1014893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_sBIT(png_ptr, info_ptr, length); 1015893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10175f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sRGB_SUPPORTED 1018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_sRGB) 1019893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_sRGB(png_ptr, info_ptr, length); 1020893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10225f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_iCCP_SUPPORTED 1023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_iCCP) 1024893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_iCCP(png_ptr, info_ptr, length); 1025893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10275f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_sPLT_SUPPORTED 1028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_sPLT) 1029893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_sPLT(png_ptr, info_ptr, length); 1030893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10325f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_tEXt_SUPPORTED 1033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_tEXt) 1034893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_tEXt(png_ptr, info_ptr, length); 1035893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10375f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_tIME_SUPPORTED 1038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_tIME) 1039893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_tIME(png_ptr, info_ptr, length); 1040893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10425f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_tRNS_SUPPORTED 1043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_tRNS) 1044893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_tRNS(png_ptr, info_ptr, length); 1045893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10475f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_zTXt_SUPPORTED 1048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_zTXt) 1049893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_zTXt(png_ptr, info_ptr, length); 1050893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10525f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_READ_iTXt_SUPPORTED 1053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (chunk_name == png_iTXt) 1054893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_handle_iTXt(png_ptr, info_ptr, length); 1055893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1057893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 1058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_handle_unknown(png_ptr, info_ptr, length, 1059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_HANDLE_CHUNK_AS_DEFAULT); 1060893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } while (!(png_ptr->mode & PNG_HAVE_IEND)); 1061893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 10625f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 1063893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Free all memory used in the read struct */ 1065b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1066b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_read_destroy(png_structrp png_ptr) 1067893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 10684215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_read_destroy"); 1069893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_GAMMA_SUPPORTED 1071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_gamma_table(png_ptr); 1072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1073893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1074893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_free(png_ptr, png_ptr->big_row_buf); 1075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->big_prev_row); 1076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->read_buffer); 1077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_READ_QUANTIZE_SUPPORTED 1079893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_free(png_ptr, png_ptr->palette_lookup); 1080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->quantize_index); 1081893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1083893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->free_me & PNG_FREE_PLTE) 1084893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_zfree(png_ptr, png_ptr->palette); 1085893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->free_me &= ~PNG_FREE_PLTE; 1086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1087893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_tRNS_SUPPORTED) || \ 1088893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) 1089893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->free_me & PNG_FREE_TRNS) 1090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->trans_alpha); 1091893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->free_me &= ~PNG_FREE_TRNS; 1092893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1093893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1094893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project inflateEnd(&png_ptr->zstream); 1095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1096893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_PROGRESSIVE_READ_SUPPORTED 1097893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_free(png_ptr, png_ptr->save_buffer); 1098893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1099893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) &&\ 1101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) 1102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->unknown_chunk.data); 1103893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED 1106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->chunk_list); 1107893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1108893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1109b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#ifdef PNG_INDEX_SUPPORTED 1110b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari if (png_ptr->index) { 1111b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari unsigned int i, p; 1112b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_indexp index = png_ptr->index; 1113b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari for (p = 0; p < 7; p++) { 1114b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari for (i = 0; i < index->size[p]; i++) { 1115b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari inflateEnd(index->pass_line_index[p][i]->z_state); 1116b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_free(png_ptr, index->pass_line_index[p][i]->z_state); 1117b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_free(png_ptr, index->pass_line_index[p][i]->prev_row); 1118b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_free(png_ptr, index->pass_line_index[p][i]); 1119b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari } 1120b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari if (index->size[p] != 0) { 1121b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_free(png_ptr, index->pass_line_index[p]); 1122b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari } 1123b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari } 1124b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari png_free(png_ptr, index); 1125b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari } 1126b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari#endif 1127b0277d0706e596e9a1dd889903f8ceb2680bcadbSireesh Tripurari 1128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error 1129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * callbacks are still set at this point. They are required to complete the 1130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * destruction of the png_struct itself. 1131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1133893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Free all memory used by the read */ 1135b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 1136b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr, 1137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_infopp end_info_ptr_ptr) 1138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = NULL; 1140893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug(1, "in png_destroy_read_struct"); 1142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr_ptr != NULL) 1144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr = *png_ptr_ptr; 1145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr == NULL) 1147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* libpng 1.6.0: use the API to destroy info structs to ensure consistent 1150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * behavior. Prior to 1.6.0 libpng did extra 'info' destruction in this API. 1151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The extra was, apparently, unnecessary yet this hides memory leak bugs. 1152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_info_struct(png_ptr, end_info_ptr_ptr); 1154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_info_struct(png_ptr, info_ptr_ptr); 1155893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *png_ptr_ptr = NULL; 1157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_destroy(png_ptr); 1158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_png_struct(png_ptr); 1159893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1160893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1161893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 1162b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn) 1163893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1164a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 1165a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 1166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1167893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->read_row_fn = read_row_fn; 1168893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1169893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1170893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 11715f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_SEQUENTIAL_READ_SUPPORTED 11725f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_INFO_IMAGE_SUPPORTED 1173893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 1174b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_read_png(png_structrp png_ptr, png_inforp info_ptr, 1175893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int transforms, 1176893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project voidp params) 1177893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr == NULL || info_ptr == NULL) 1179a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 1180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* png_read_info() gives us all of the information from the 1182893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * PNG file before the first IDAT (image data chunk). 1183893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1184893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_info(png_ptr, info_ptr); 1185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep))) 11864215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_error(png_ptr, "Image is too high to process with png_read_png()"); 1187893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1188893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* -------------- image transformations start here ------------------- */ 1189b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM 1190b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * is not implemented. This will only happen in de-configured (non-default) 1191b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * libpng builds. The results can be unexpected - png_read_png may return 1192b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * short or mal-formed rows because the transform is skipped. 1193b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 1194893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Tell libpng to strip 16-bit/color files down to 8 bits per color. 1196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (transforms & PNG_TRANSFORM_SCALE_16) 1198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Added at libpng-1.5.4. "strip_16" produces the same result that it 1199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * did in earlier versions, while "scale_16" is now more accurate. 1200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1201b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED 1202b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_scale_16(png_ptr); 1203b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1204b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported"); 1205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If both SCALE and STRIP are required pngrtran will effectively cancel the 1208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * latter by doing SCALE first. This is ok and allows apps not to check for 1209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * which is supported to get the right answer. 1210893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (transforms & PNG_TRANSFORM_STRIP_16) 1212b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED 1213a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_strip_16(png_ptr); 1214b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1215b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported"); 1216893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1217893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1218893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Strip alpha bytes from the input data without combining with 1219893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * the background (not recommended). 1220893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1221893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (transforms & PNG_TRANSFORM_STRIP_ALPHA) 1222b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED 1223a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_strip_alpha(png_ptr); 1224b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1225b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported"); 1226893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1227893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1228893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Extract multiple pixels with bit depths of 1, 2, or 4 from a single 1229893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * byte into separate bytes (useful for paletted and grayscale images). 1230893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1231893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (transforms & PNG_TRANSFORM_PACKING) 1232b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_PACK_SUPPORTED 1233a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_packing(png_ptr); 1234b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1235b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported"); 1236893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1238893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Change the order of packed pixels to least significant bit first 1239893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (not useful if you are using png_set_packing). 1240893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1241893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (transforms & PNG_TRANSFORM_PACKSWAP) 1242b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_PACKSWAP_SUPPORTED 1243a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_packswap(png_ptr); 1244b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1245b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported"); 1246893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1247893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Expand paletted colors into true RGB triplets 1249893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel 1250893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * Expand paletted or RGB images with transparency to full alpha 1251893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * channels so the data will be available as RGBA quartets. 1252893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (transforms & PNG_TRANSFORM_EXPAND) 1254b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_EXPAND_SUPPORTED 1255b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_set_expand(png_ptr); 1256b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1257b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported"); 1258893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1259893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We don't handle background color or gamma transformation or quantizing. 1261893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1262893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1263a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Invert monochrome files to have 0 as white and 1 as black 1264893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1265893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (transforms & PNG_TRANSFORM_INVERT_MONO) 1266b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_INVERT_SUPPORTED 1267a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_invert_mono(png_ptr); 1268b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1269b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported"); 1270893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1271893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1272893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* If you want to shift the pixel values from the range [0,255] or 1273893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * [0,65535] to the original [0,7] or [0,31], or whatever range the 1274893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * colors were originally in: 1275893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1276b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (transforms & PNG_TRANSFORM_SHIFT) 1277b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SHIFT_SUPPORTED 1278b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (info_ptr->valid & PNG_INFO_sBIT) 1279b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_set_shift(png_ptr, &info_ptr->sig_bit); 1280b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1281b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported"); 1282893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1283893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Flip the RGB pixels to BGR (or RGBA to BGRA) */ 1285893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (transforms & PNG_TRANSFORM_BGR) 1286b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_BGR_SUPPORTED 1287a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_bgr(png_ptr); 1288b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1289b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported"); 1290893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1291893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */ 1293893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (transforms & PNG_TRANSFORM_SWAP_ALPHA) 1294b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED 1295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_swap_alpha(png_ptr); 1296b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1297b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported"); 1298893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1299893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Swap bytes of 16-bit files to least significant byte first */ 1301893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (transforms & PNG_TRANSFORM_SWAP_ENDIAN) 1302b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_SWAP_SUPPORTED 1303a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_swap(png_ptr); 1304b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1305b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported"); 1306893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1307893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 13085f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott/* Added at libpng-1.2.41 */ 1309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Invert the alpha channel from opacity to transparency */ 13105f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott if (transforms & PNG_TRANSFORM_INVERT_ALPHA) 1311b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED 1312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_invert_alpha(png_ptr); 1313b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1314b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported"); 13155f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif 13165f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 13175f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott/* Added at libpng-1.2.41 */ 1318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Expand grayscale image to RGB */ 13195f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott if (transforms & PNG_TRANSFORM_GRAY_TO_RGB) 1320b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED 1321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_gray_to_rgb(png_ptr); 1322b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1323b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported"); 1324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Added at libpng-1.5.4 */ 1327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (transforms & PNG_TRANSFORM_EXPAND_16) 1328b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_READ_EXPAND_16_SUPPORTED 1329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_expand_16(png_ptr); 1330b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1331b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported"); 13325f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif 13335f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1334893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* We don't handle adding filler bytes */ 1335893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We use png_read_image and rely on that for interlace handling, but we also 1337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * call png_read_update_info therefore must turn on interlace handling now: 1338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)png_set_interlace_handling(png_ptr); 1340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1341893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Optional call to gamma correct and add the background to the palette 1342893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * and update info structure. REQUIRED if you are expecting libpng to 1343893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * update the palette for you (i.e., you selected such a transform above). 1344893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_update_info(png_ptr, info_ptr); 1346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1347893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* -------------- image transformations end here ------------------- */ 1348893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1349893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0); 13504215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project if (info_ptr->row_pointers == NULL) 1351893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 iptr; 1353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1354b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr, 1355b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari info_ptr->height * (sizeof (png_bytep)))); 1356b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (iptr=0; iptr<info_ptr->height; iptr++) 1358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->row_pointers[iptr] = NULL; 13595f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1360893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project info_ptr->free_me |= PNG_FREE_ROWS; 13615f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1362b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (iptr = 0; iptr < info_ptr->height; iptr++) 1363b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari info_ptr->row_pointers[iptr] = png_voidcast(png_bytep, 1364b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_malloc(png_ptr, info_ptr->rowbytes)); 1365893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1366893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1367893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_image(png_ptr, info_ptr->row_pointers); 1368893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project info_ptr->valid |= PNG_INFO_IDAT; 1369893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1370a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Read rest of file, and get additional chunks in info_ptr - REQUIRED */ 1371893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_read_end(png_ptr, info_ptr); 1372893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_UNUSED(params) 1374893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1375893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif /* PNG_INFO_IMAGE_SUPPORTED */ 13765f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */ 1377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_SIMPLIFIED_READ_SUPPORTED 1379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* SIMPLIFIED READ 1380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This code currently relies on the sequential reader, though it could easily 1382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be made to work with the progressive one. 1383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Arguments to png_image_finish_read: */ 1385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Encoding of PNG data (used by the color-map code) */ 1387b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define P_NOTSET 0 /* File encoding not yet known */ 1388b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define P_sRGB 1 /* 8-bit encoded to sRGB gamma */ 1389b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define P_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */ 1390b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define P_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */ 1391b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# define P_LINEAR8 4 /* 8-bit linear: only from a file value */ 1392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Color-map processing: after libpng has run on the PNG image further 1394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * processing may be needed to conver the data to color-map indicies. 1395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_CMAP_NONE 0 1397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_CMAP_GA 1 /* Process GA data to a color-map with alpha */ 1398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_CMAP_TRANS 2 /* Process GA data to a background index */ 1399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_CMAP_RGB 3 /* Process RGB data */ 1400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */ 1401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The following document where the background is for each processing case. */ 1403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_CMAP_NONE_BACKGROUND 256 1404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_CMAP_GA_BACKGROUND 231 1405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_CMAP_TRANS_BACKGROUND 254 1406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_CMAP_RGB_BACKGROUND 256 1407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_CMAP_RGB_ALPHA_BACKGROUND 216 1408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1409b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef struct 1410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Arguments: */ 1412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image; 1413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidp buffer; 1414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_int_32 row_stride; 1415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidp colormap; 1416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_colorp background; 1417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Local variables: */ 1418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidp local_row; 1419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidp first_row; 1420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t row_bytes; /* step between rows */ 1421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int file_encoding; /* E_ values above */ 1422b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */ 1423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int colormap_processing; /* PNG_CMAP_ values above */ 1424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} png_image_read_control; 1425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Do all the *safe* initialization - 'safe' means that png_error won't be 1427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * called, so setting up the jmp_buf is not required. This means that anything 1428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * called from here must *not* call png_malloc - it has to call png_malloc_warn 1429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * instead so that control is returned safely back to this routine. 1430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1431b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1432b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_read_init(png_imagep image) 1433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->opaque == NULL) 1435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image, 1437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_safe_error, png_safe_warning); 1438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And set the rest of the structure to NULL to ensure that the various 1440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * fields are consistent. 1441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(image, 0, (sizeof *image)); 1443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->version = PNG_IMAGE_VERSION; 1444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr != NULL) 1446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_infop info_ptr = png_create_info_struct(png_ptr); 1448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (info_ptr != NULL) 1450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_controlp control = png_voidcast(png_controlp, 1452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_malloc_warn(png_ptr, (sizeof *control))); 1453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (control != NULL) 1455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1456b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(control, 0, (sizeof *control)); 1457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik control->png_ptr = png_ptr; 1459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik control->info_ptr = info_ptr; 1460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik control->for_write = 0; 1461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque = control; 1463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Error clean up */ 1467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_info_struct(png_ptr, &info_ptr); 1468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_read_struct(&png_ptr, NULL, NULL); 1471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, "png_image_read: out of memory"); 1474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, "png_image_read: opaque pointer not NULL"); 1477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Utility to find the base format of a PNG file from a png_struct. */ 1480b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_32 1481b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_format(png_structrp png_ptr) 1482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 format = 0; 1484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->color_type & PNG_COLOR_MASK_COLOR) 1486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format |= PNG_FORMAT_FLAG_COLOR; 1487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) 1489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format |= PNG_FORMAT_FLAG_ALPHA; 1490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS 1492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * sets the png_struct fields; that's all we are interested in here. The 1493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * precise interaction with an app call to png_set_tRNS and PNG file reading 1494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is unclear. 1495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (png_ptr->num_trans > 0) 1497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format |= PNG_FORMAT_FLAG_ALPHA; 1498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->bit_depth == 16) 1500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format |= PNG_FORMAT_FLAG_LINEAR; 1501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->color_type & PNG_COLOR_MASK_PALETTE) 1503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format |= PNG_FORMAT_FLAG_COLORMAP; 1504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return format; 1506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Is the given gamma significantly different from sRGB? The test is the same 1509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * one used in pngrtran.c when deciding whether to do gamma correction. The 1510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * arithmetic optimizes the division by using the fact that the inverse of the 1511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * file sRGB gamma is 2.2 1512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1513b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1514b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_gamma_not_sRGB(png_fixed_point g) 1515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (g < PNG_FP_1) 1517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* An uninitialized gamma is assumed to be sRGB for the simplified API. */ 1519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (g == 0) 1520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */); 1523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Do the main body of a 'png_image_begin_read' function; read the PNG file 1529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * header and fill in all the information. This is executed in a safe context, 1530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * unlike the init routine above. 1531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1532b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1533b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_read_header(png_voidp argument) 1534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = png_voidcast(png_imagep, argument); 1536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = image->opaque->png_ptr; 1537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_inforp info_ptr = image->opaque->info_ptr; 1538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_benign_errors(png_ptr, 1/*warn*/); 1540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_info(png_ptr, info_ptr); 1541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Do this the fast way; just read directly out of png_struct. */ 1543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->width = png_ptr->width; 1544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->height = png_ptr->height; 1545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 format = png_image_format(png_ptr); 1548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->format = format; 1550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_COLORSPACE_SUPPORTED 1552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Does the colorspace match sRGB? If there is no color endpoint 1553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (colorant) information assume yes, otherwise require the 1554b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set. If the 1555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * colorspace has been determined to be invalid ignore it. 1556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags 1558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB| 1559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS)) 1560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB; 1561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We need the maximum number of entries regardless of the format the 1565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * application sets here. 1566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 cmap_entries; 1569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (png_ptr->color_type) 1571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_COLOR_TYPE_GRAY: 1573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = 1U << png_ptr->bit_depth; 1574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_COLOR_TYPE_PALETTE: 1577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = png_ptr->num_palette; 1578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 1581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = 256; 1582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (cmap_entries > 256) 1586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = 256; 1587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->colormap_entries = cmap_entries; 1589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_STDIO_SUPPORTED 1595b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint PNGAPI 1596b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_begin_read_from_stdio(png_imagep image, FILE* file) 1597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image != NULL && image->version == PNG_IMAGE_VERSION) 1599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (file != NULL) 1601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_image_read_init(image)) 1603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is slightly evil, but png_init_io doesn't do anything other 1605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * than this and we haven't changed the standard IO functions so 1606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this saves a 'safe' function. 1607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1608b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque->png_ptr->io_ptr = file; 1609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_safe_execute(image, png_image_read_header, image); 1610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 1615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_image_begin_read_from_stdio: invalid argument"); 1616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (image != NULL) 1619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 1620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION"); 1621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1625b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint PNGAPI 1626b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_begin_read_from_file(png_imagep image, const char *file_name) 1627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image != NULL && image->version == PNG_IMAGE_VERSION) 1629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (file_name != NULL) 1631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik FILE *fp = fopen(file_name, "rb"); 1633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fp != NULL) 1635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_image_read_init(image)) 1637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque->png_ptr->io_ptr = fp; 1639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque->owned_file = 1; 1640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_safe_execute(image, png_image_read_header, image); 1641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Clean up: just the opened file. */ 1644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)fclose(fp); 1645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, strerror(errno)); 1649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 1653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_image_begin_read_from_file: invalid argument"); 1654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (image != NULL) 1657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 1658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION"); 1659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_STDIO_SUPPORTED */ 1663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1664b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void PNGCBAPI 1665b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need) 1666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr != NULL) 1668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr); 1670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image != NULL) 1671b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_controlp cp = image->opaque; 1673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (cp != NULL) 1674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep memory = cp->memory; 1676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t size = cp->size; 1677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (memory != NULL && size >= need) 1679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memcpy(out, memory, need); 1681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cp->memory = memory + need; 1682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cp->size = size - need; 1683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "read beyond end of data"); 1687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "invalid memory read"); 1691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1694b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint PNGAPI png_image_begin_read_from_memory(png_imagep image, 1695b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_voidp memory, png_size_t size) 1696b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image != NULL && image->version == PNG_IMAGE_VERSION) 1698b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1699b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (memory != NULL && size > 0) 1700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1701b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_image_read_init(image)) 1702b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now set the IO functions to read from the memory buffer and 1704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * store it into io_ptr. Again do this in-place to avoid calling a 1705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * libpng function that requires error handling. 1706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque->memory = png_voidcast(png_const_bytep, memory); 1708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque->size = size; 1709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque->png_ptr->io_ptr = image; 1710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque->png_ptr->read_data_fn = png_image_memory_read; 1711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_safe_execute(image, png_image_read_header, image); 1713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1715b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1717b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 1718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_image_begin_read_from_memory: invalid argument"); 1719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (image != NULL) 1722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 1723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION"); 1724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1726b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Utility function to skip chunks that are not used by the simplified image 1729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * read functions and an appropriate macro to call it. 1730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED 1732b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1733b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_skip_unused_chunks(png_structrp png_ptr) 1734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Prepare the reader to ignore all recognized chunks whose data will not 1736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be used, i.e., all chunks recognized by libpng except for those 1737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * involved in basic image reading: 1738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * IHDR, PLTE, IDAT, IEND 1740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Or image data handling: 1742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1743b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT. 1744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This provides a small performance improvement and eliminates any 1746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * potential vulnerability to security problems in the unused chunks. 1747b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * 1748b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored 1749b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * too. This allows the simplified API to be compiled without iCCP support, 1750b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * however if the support is there the chunk is still checked to detect 1751b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * errors (which are unfortunately quite common.) 1752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static PNG_CONST png_byte chunks_to_process[] = { 1755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 98, 75, 71, 68, '\0', /* bKGD */ 1756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 99, 72, 82, 77, '\0', /* cHRM */ 1757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 103, 65, 77, 65, '\0', /* gAMA */ 1758b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_READ_iCCP_SUPPORTED 1759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 105, 67, 67, 80, '\0', /* iCCP */ 1760b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 1761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 115, 66, 73, 84, '\0', /* sBIT */ 1762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 115, 82, 71, 66, '\0', /* sRGB */ 1763b50c217251b086440efcdb273c22f86a06c80cbaChris Craik }; 1764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Ignore unknown chunks and all other chunks except for the 1766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * IHDR, PLTE, tRNS, IDAT, and IEND chunks. 1767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER, 1769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik NULL, -1); 1770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* But do not ignore image data handling chunks */ 1772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT, 1773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik chunks_to_process, (sizeof chunks_to_process)/5); 1774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p) 1778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else 1779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define PNG_SKIP_CHUNKS(p) ((void)0) 1780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_HANDLE_AS_UNKNOWN_SUPPORTED */ 1781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The following macro gives the exact rounded answer for all values in the 1783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * range 0..255 (it actually divides by 51.2, but the rounding still generates 1784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the correct numbers 0..5 1785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8) 1787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Utility functions to make particular color-maps */ 1789b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1790b50c217251b086440efcdb273c22f86a06c80cbaChris Craikset_file_encoding(png_image_read_control *display) 1791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1792b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma; 1793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_gamma_significant(g)) 1794b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_gamma_not_sRGB(g)) 1796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1797b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display->file_encoding = P_FILE; 1798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->gamma_to_linear = png_reciprocal(g); 1799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1802b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display->file_encoding = P_sRGB; 1803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1806b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari display->file_encoding = P_LINEAR8; 1807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1809b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic unsigned int 1810b50c217251b086440efcdb273c22f86a06c80cbaChris Craikdecode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) 1811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1812b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (encoding == P_FILE) /* double check */ 1813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik encoding = display->file_encoding; 1814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1815b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (encoding == P_NOTSET) /* must be the file encoding */ 1816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik set_file_encoding(display); 1818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik encoding = display->file_encoding; 1819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (encoding) 1822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1823b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case P_FILE: 1824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik value = png_gamma_16bit_correct(value*257, display->gamma_to_linear); 1825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1827b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case P_sRGB: 1828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik value = png_sRGB_table[value]; 1829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1831b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case P_LINEAR: 1832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1834b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case P_LINEAR8: 1835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik value *= 257; 1836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 1839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(display->image->opaque->png_ptr, 1840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "unexpected encoding (internal error)"); 1841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1844b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return value; 1845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1847b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_uint_32 1848b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_colormap_compose(png_image_read_control *display, 1849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha, 1850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 background, int encoding) 1851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The file value is composed on the background, the background has the given 1853b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * encoding and so does the result, the file is encoded with P_FILE and the 1854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * file and alpha are 8-bit values. The (output) encoding will always be 1855b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * P_LINEAR or P_sRGB. 1856b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 f = decode_gamma(display, foreground, foreground_encoding); 1858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 b = decode_gamma(display, background, encoding); 1859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The alpha is always an 8-bit value (it comes from the palette), the value 1861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires. 1862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik f = f * alpha + b * (255-alpha); 1864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1865b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (encoding == P_LINEAR) 1866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Scale to 65535; divide by 255, approximately (in fact this is extremely 1868b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * accurate, it divides by 255.00000005937181414556, with no overflow.) 1869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1870b50c217251b086440efcdb273c22f86a06c80cbaChris Craik f *= 257; /* Now scaled by 65535 */ 1871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik f += f >> 16; 1872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik f = (f+32768) >> 16; 1873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1875b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else /* P_sRGB */ 1876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik f = PNG_sRGB_FROM_LINEAR(f); 1877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return f; 1879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1881b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must 1882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be 8-bit. 1883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1884b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1885b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_create_colormap_entry(png_image_read_control *display, 1886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue, 1887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 alpha, int encoding) 1888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1889b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = display->image; 1890b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) ? 1891b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari P_LINEAR : P_sRGB; 1892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 && 1893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (red != green || green != blue); 1894b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ip > 255) 1896b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(image->opaque->png_ptr, "color-map index out of range"); 1897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Update the cache with whether the file gamma is significantly different 1899b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * from sRGB. 1900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1901b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (encoding == P_FILE) 1902b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1903b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (display->file_encoding == P_NOTSET) 1904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik set_file_encoding(display); 1905b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1906b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Note that the cached value may be P_FILE too, but if it is then the 1907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * gamma_to_linear member has been set. 1908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik encoding = display->file_encoding; 1910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1911b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1912b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (encoding == P_FILE) 1913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point g = display->gamma_to_linear; 1915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1916b50c217251b086440efcdb273c22f86a06c80cbaChris Craik red = png_gamma_16bit_correct(red*257, g); 1917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik green = png_gamma_16bit_correct(green*257, g); 1918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik blue = png_gamma_16bit_correct(blue*257, g); 1919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1920b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (convert_to_Y || output_encoding == P_LINEAR) 1921b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik alpha *= 257; 1923b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari encoding = P_LINEAR; 1924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1927b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik red = PNG_sRGB_FROM_LINEAR(red * 255); 1929b50c217251b086440efcdb273c22f86a06c80cbaChris Craik green = PNG_sRGB_FROM_LINEAR(green * 255); 1930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik blue = PNG_sRGB_FROM_LINEAR(blue * 255); 1931b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari encoding = P_sRGB; 1932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1935b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (encoding == P_LINEAR8) 1936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This encoding occurs quite frequently in test cases because PngSuite 1938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * includes a gAMA 1.0 chunk with most images. 1939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1940b50c217251b086440efcdb273c22f86a06c80cbaChris Craik red *= 257; 1941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik green *= 257; 1942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik blue *= 257; 1943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik alpha *= 257; 1944b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari encoding = P_LINEAR; 1945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1947b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (encoding == P_sRGB && (convert_to_Y || output_encoding == P_LINEAR)) 1948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The values are 8-bit sRGB values, but must be converted to 16-bit 1950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * linear. 1951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1952b50c217251b086440efcdb273c22f86a06c80cbaChris Craik red = png_sRGB_table[red]; 1953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik green = png_sRGB_table[green]; 1954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik blue = png_sRGB_table[blue]; 1955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik alpha *= 257; 1956b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari encoding = P_LINEAR; 1957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is set if the color isn't gray but the output is. */ 1960b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (encoding == P_LINEAR) 1961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (convert_to_Y) 1963b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* NOTE: these values are copied from png_do_rgb_to_gray */ 1965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y = (png_uint_32)6968 * red + (png_uint_32)23434 * green + 1966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_uint_32)2366 * blue; 1967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1968b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (output_encoding == P_LINEAR) 1969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y = (y + 16384) >> 15; 1970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* y is scaled by 32768, we need it scaled by 255: */ 1974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y = (y + 128) >> 8; 1975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y *= 255; 1976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7); 1977b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari encoding = P_sRGB; 1978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik blue = red = green = y; 1981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1983b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (output_encoding == P_sRGB) 1984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1985b50c217251b086440efcdb273c22f86a06c80cbaChris Craik red = PNG_sRGB_FROM_LINEAR(red * 255); 1986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik green = PNG_sRGB_FROM_LINEAR(green * 255); 1987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik blue = PNG_sRGB_FROM_LINEAR(blue * 255); 1988b50c217251b086440efcdb273c22f86a06c80cbaChris Craik alpha = PNG_DIV257(alpha); 1989b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari encoding = P_sRGB; 1990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (encoding != output_encoding) 1994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(image->opaque->png_ptr, "bad encoding (internal error)"); 1995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Store the value. */ 1997b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1998b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_FORMAT_AFIRST_SUPPORTED 1999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 && 2000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; 2001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# else 2002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define afirst 0 2003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 2004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_FORMAT_BGR_SUPPORTED 2005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) ? 2 : 0; 2006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# else 2007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define bgr 0 2008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 2009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2010b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (output_encoding == P_LINEAR) 2011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap); 2013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); 2015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The linear 16-bit values must be pre-multiplied by the alpha channel 2017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value, if less than 65535 (this is, effectively, composite on black 2018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * if the alpha channel is removed.) 2019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) 2021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 4: 2023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[afirst ? 0 : 3] = (png_uint_16)alpha; 2024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* FALL THROUGH */ 2025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 3: 2027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha < 65535) 2028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha > 0) 2030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik blue = (blue * alpha + 32767U)/65535U; 2032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik green = (green * alpha + 32767U)/65535U; 2033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik red = (red * alpha + 32767U)/65535U; 2034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik red = green = blue = 0; 2038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[afirst + (2 ^ bgr)] = (png_uint_16)blue; 2040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[afirst + 1] = (png_uint_16)green; 2041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[afirst + bgr] = (png_uint_16)red; 2042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 2: 2045b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[1 ^ afirst] = (png_uint_16)alpha; 2046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* FALL THROUGH */ 2047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 1: 2049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha < 65535) 2050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha > 0) 2052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik green = (green * alpha + 32767U)/65535U; 2053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik green = 0; 2056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[afirst] = (png_uint_16)green; 2058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 2061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2062b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2065b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else /* output encoding is P_sRGB */ 2066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep entry = png_voidcast(png_bytep, display->colormap); 2068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2069b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format); 2070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format)) 2072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2073b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 4: 2074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[afirst ? 0 : 3] = (png_byte)alpha; 2075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 3: 2076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[afirst + (2 ^ bgr)] = (png_byte)blue; 2077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[afirst + 1] = (png_byte)green; 2078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[afirst + bgr] = (png_byte)red; 2079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2081b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 2: 2082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[1 ^ afirst] = (png_byte)alpha; 2083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 1: 2084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[afirst] = (png_byte)green; 2085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 2088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2092b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef afirst 2093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# undef afirst 2094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 2095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef bgr 2096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# undef bgr 2097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 2098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2101b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 2102b50c217251b086440efcdb273c22f86a06c80cbaChris Craikmake_gray_file_colormap(png_image_read_control *display) 2103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int i; 2105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=0; i<256; ++i) 2107b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_create_colormap_entry(display, i, i, i, i, 255, P_FILE); 2108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return i; 2110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2112b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 2113b50c217251b086440efcdb273c22f86a06c80cbaChris Craikmake_gray_colormap(png_image_read_control *display) 2114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int i; 2116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=0; i<256; ++i) 2118b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB); 2119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return i; 2121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_GRAY_COLORMAP_ENTRIES 256 2123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2124b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 2125b50c217251b086440efcdb273c22f86a06c80cbaChris Craikmake_ga_colormap(png_image_read_control *display) 2126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int i, a; 2128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Alpha is retained, the output will be a color-map with entries 2130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * selected by six levels of alpha. One transparent entry, 6 gray 2131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * levels for all the intermediate alpha values, leaving 230 entries 2132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * for the opaque grays. The color-map entries are the six values 2133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the 2134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * relevant entry. 2135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * if (alpha > 229) // opaque 2137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * { 2138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * // The 231 entries are selected to make the math below work: 2139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * base = 0; 2140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * entry = (231 * gray + 128) >> 8; 2141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * } 2142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * else if (alpha < 26) // transparent 2143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * { 2144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * base = 231; 2145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * entry = 0; 2146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * } 2147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * else // partially opaque 2148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * { 2149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * base = 226 + 6 * PNG_DIV51(alpha); 2150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * entry = PNG_DIV51(gray); 2151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * } 2152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik i = 0; 2154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (i < 231) 2155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int gray = (i * 256 + 115) / 231; 2157b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB); 2158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 255 is used here for the component values for consistency with the code 2161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * that undoes premultiplication in pngwrite.c. 2162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2163b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB); 2164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (a=1; a<5; ++a) 2166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int g; 2168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (g=0; g<6; ++g) 2170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51, 2171b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari P_sRGB); 2172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return i; 2175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_GA_COLORMAP_ENTRIES 256 2178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2179b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 2180b50c217251b086440efcdb273c22f86a06c80cbaChris Craikmake_rgb_colormap(png_image_read_control *display) 2181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int i, r; 2183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Build a 6x6x6 opaque RGB cube */ 2185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=r=0; r<6; ++r) 2186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int g; 2188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (g=0; g<6; ++g) 2190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int b; 2192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (b=0; b<6; ++b) 2194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255, 2195b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari P_sRGB); 2196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return i; 2200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2202b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_RGB_COLORMAP_ENTRIES 216 2203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Return a palette index to the above palette given three 8-bit sRGB values. */ 2205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#define PNG_RGB_INDEX(r,g,b) \ 2206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b))) 2207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2208b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 2209b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_read_colormap(png_voidp argument) 2210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_read_control *display = 2212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidcast(png_image_read_control*, argument); 2213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_imagep image = display->image; 2214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_structrp png_ptr = image->opaque->png_ptr; 2216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_uint_32 output_format = image->format; 2217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) ? 2218b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari P_LINEAR : P_sRGB; 2219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int cmap_entries; 2221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int output_processing; /* Output processing option */ 2222b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */ 2223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Background information; the background color and the index of this color 2225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * in the color-map if it exists (else 256). 2226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int background_index = 256; 2228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 back_r, back_g, back_b; 2229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Flags to accumulate things that need to be done to the input. */ 2231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int expand_tRNS = 0; 2232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is 2234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * very difficult to do, the results look awful, and it is difficult to see 2235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * what possible use it is because the application can't control the 2236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * color-map. 2237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 || 2239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->num_trans > 0) /* alpha in input */ && 2240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */) 2241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2242b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (output_encoding == P_LINEAR) /* compose on black */ 2243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_b = back_g = back_r = 0; 2244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (display->background == NULL /* no way to remove it */) 2246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, 2247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "a background color must be supplied to remove alpha/transparency"); 2248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Get a copy of the background color (this avoids repeating the checks 2250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the 2251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * output format. 2252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_g = display->background->green; 2256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (output_format & PNG_FORMAT_FLAG_COLOR) 2257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_r = display->background->red; 2259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_b = display->background->blue; 2260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_b = back_r = back_g; 2263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2266b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (output_encoding == P_LINEAR) 2267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_b = back_r = back_g = 65535; 2268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_b = back_r = back_g = 255; 2271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Default the input file gamma if required - this is necessary because 2273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * libpng assumes that if no gamma information is present the data is in the 2274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * output format, but the simplified API deduces the gamma from the input 2275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * format. 2276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0) 2278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Do this directly, not using the png_colorspace functions, to ensure 2280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * that it happens even if the colorspace is invalid (though probably if 2281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it is the setting will be ignored) Note that the same thing can be 2282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * achieved at the application interface with png_set_gAMA. 2283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->bit_depth == 16 && 2285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) 2286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR; 2287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE; 2290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA; 2292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Decide what to do based on the PNG color type of the input data. The 2295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * utility function png_create_colormap_entry deals with most aspects of the 2296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * output transformations; this code works out how to produce bytes of 2297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * color-map entries from the original format. 2298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (png_ptr->color_type) 2300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_COLOR_TYPE_GRAY: 2302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->bit_depth <= 8) 2303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* There at most 256 colors in the output, regardless of 2305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * transparency. 2306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0; 2308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = 1U << png_ptr->bit_depth; 2310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (cmap_entries > image->colormap_entries) 2311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "gray[8] color-map: too few entries"); 2312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik step = 255 / (cmap_entries - 1); 2314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_NONE; 2315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If there is a tRNS chunk then this either selects a transparent 2317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value or, if the output has no alpha, the background color. 2318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->num_trans > 0) 2320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik trans = png_ptr->trans_color.gray; 2322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) 2324b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari back_alpha = output_encoding == P_LINEAR ? 65535 : 255; 2325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* png_create_colormap_entry just takes an RGBA and writes the 2328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * corresponding color-map entry using the format from 'image', 2329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * including the required conversion to sRGB or linear as 2330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * appropriate. The input values are always either sRGB (if the 2331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * gamma correction flag is 0) or 0..255 scaled file encoded values 2332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (if the function must gamma correct them). 2333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=val=0; i<cmap_entries; ++i, val += step) 2335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 'i' is a file value. While this will result in duplicated 2337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * entries for 8-bit non-sRGB encoded files it is necessary to 2338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * have non-gamma corrected values to do tRNS handling. 2339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (i != trans) 2341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, i, val, val, val, 255, 2342b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari P_FILE/*8-bit with file gamma*/); 2343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Else this entry is transparent. The colors don't matter if 2345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * there is an alpha channel (back_alpha == 0), but it does no 2346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * harm to pass them in; the values are not set above so this 2347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * passes in white. 2348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * NOTE: this preserves the full precision of the application 2350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * supplied background color when it is used. 2351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, i, back_r, back_g, back_b, 2354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_alpha, output_encoding); 2355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We need libpng to preserve the original encoding. */ 2358b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari data_encoding = P_FILE; 2359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The rows from libpng, while technically gray values, are now also 2361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * color-map indicies; however, they may need to be expanded to 1 2362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * byte per pixel. This is what png_set_packing does (i.e., it 2363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * unpacks the bit values into bytes.) 2364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->bit_depth < 8) 2366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_packing(png_ptr); 2367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* bit depth is 16 */ 2370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The 16-bit input values can be converted directly to 8-bit gamma 2372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * encoded values; however, if a tRNS chunk is present 257 color-map 2373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * entries are required. This means that the extra entry requires 2374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * special processing; add an alpha channel, sacrifice gray level 2375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 254 and convert transparent (alpha==0) entries to that. 2376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Use libpng to chop the data to 8 bits. Convert it to sRGB at the 2378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * same time to minimize quality loss. If a tRNS chunk is present 2379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this means libpng must handle it too; otherwise it is impossible 2380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to do the exact match on the 16-bit value. 2381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * If the output has no alpha channel *and* the background color is 2383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * gray then it is possible to let libpng handle the substitution by 2384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * ensuring that the corresponding gray level matches the background 2385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * color exactly. 2386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2387b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari data_encoding = P_sRGB; 2388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) 2390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "gray[16] color-map: too few entries"); 2391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = make_gray_colormap(display); 2393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->num_trans > 0) 2395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int back_alpha; 2397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (output_format & PNG_FORMAT_FLAG_ALPHA) 2399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_alpha = 0; 2400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (back_r == back_g && back_g == back_b) 2404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Background is gray; no special processing will be 2406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * required. 2407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_color_16 c; 2409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 gray = back_g; 2410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2411b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (output_encoding == P_LINEAR) 2412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik gray = PNG_sRGB_FROM_LINEAR(gray * 255); 2414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And make sure the corresponding palette entry 2416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * matches. 2417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, gray, back_g, back_g, 2419b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari back_g, 65535, P_LINEAR); 2420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The background passed to libpng, however, must be the 2423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * sRGB value. 2424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.index = 0; /*unused*/ 2426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.gray = c.red = c.green = c.blue = (png_uint_16)gray; 2427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* NOTE: does this work without expanding tRNS to alpha? 2429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * It should be the color->gray case below apparently 2430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * doesn't. 2431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_background_fixed(png_ptr, &c, 2433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, 2434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 0/*gamma: not used*/); 2435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_NONE; 2437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2440b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari back_alpha = output_encoding == P_LINEAR ? 65535 : 255; 2441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* output_processing means that the libpng-processed row will be 2444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 8-bit GA and it has to be processing to single byte color-map 2445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * values. Entry 254 is replaced by either a completely 2446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * transparent entry or by the background color at full 2447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * precision (and the background color is not a simple gray leve 2448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * in this case.) 2449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik expand_tRNS = 1; 2451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_TRANS; 2452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik background_index = 254; 2453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And set (overwrite) color-map entry 254 to the actual 2455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * background color at full precision. 2456b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, 254, back_r, back_g, back_b, 2458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_alpha, output_encoding); 2459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_NONE; 2463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_COLOR_TYPE_GRAY_ALPHA: 2467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 8-bit or 16-bit PNG with two channels - gray and alpha. A minimum 2468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * of 65536 combinations. If, however, the alpha channel is to be 2469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * removed there are only 256 possibilities if the background is gray. 2470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (Otherwise there is a subset of the 65536 possibilities defined by 2471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the triangle between black, white and the background color.) 2472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Reduce 16-bit files to 8-bit and sRGB encode the result. No need to 2474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * worry about tRNS matching - tRNS is ignored if there is an alpha 2475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * channel. 2476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2477b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari data_encoding = P_sRGB; 2478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (output_format & PNG_FORMAT_FLAG_ALPHA) 2480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) 2482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "gray+alpha color-map: too few entries"); 2483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = make_ga_colormap(display); 2485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik background_index = PNG_CMAP_GA_BACKGROUND; 2487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_GA; 2488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* alpha is removed */ 2491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Alpha must be removed as the PNG data is processed when the 2493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * background is a color because the G and A channels are 2494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * independent and the vector addition (non-parallel vectors) is a 2495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2-D problem. 2496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This can be reduced to the same algorithm as above by making a 2498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * colormap containing gray levels (for the opaque grays), a 2499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * background entry (for a transparent pixel) and a set of four six 2500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * level color values, one set for each intermediate alpha value. 2501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * See the comments in make_ga_colormap for how this works in the 2502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * per-pixel processing. 2503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * If the background is gray, however, we only need a 256 entry gray 2505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * level color map. It is sufficient to make the entry generated 2506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * for the background color be exactly the color specified. 2507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 || 2509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (back_r == back_g && back_g == back_b)) 2510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Background is gray; no special processing will be required. */ 2512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_color_16 c; 2513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 gray = back_g; 2514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) 2516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "gray-alpha color-map: too few entries"); 2517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = make_gray_colormap(display); 2519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2520b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (output_encoding == P_LINEAR) 2521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik gray = PNG_sRGB_FROM_LINEAR(gray * 255); 2523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And make sure the corresponding palette entry matches. */ 2525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, gray, back_g, back_g, 2526b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari back_g, 65535, P_LINEAR); 2527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The background passed to libpng, however, must be the sRGB 2530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * value. 2531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.index = 0; /*unused*/ 2533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.gray = c.red = c.green = c.blue = (png_uint_16)gray; 2534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_background_fixed(png_ptr, &c, 2536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, 2537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 0/*gamma: not used*/); 2538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_NONE; 2540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 i, a; 2545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is the same as png_make_ga_colormap, above, except that 2547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the entries are all opaque. 2548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) 2550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "ga-alpha color-map: too few entries"); 2551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik i = 0; 2553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (i < 231) 2554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 gray = (i * 256 + 115) / 231; 2556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, i++, gray, gray, gray, 2557b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 255, P_sRGB); 2558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* NOTE: this preserves the full precision of the application 2561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * background color. 2562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik background_index = i; 2564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, i++, back_r, back_g, back_b, 2565b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari output_encoding == P_LINEAR ? 65535U : 255U, output_encoding); 2566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* For non-opaque input composite on the sRGB background - this 2568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * requires inverting the encoding for each component. The input 2569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is still converted to the sRGB encoding because this is a 2570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * reasonable approximate to the logarithmic curve of human 2571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * visual sensitivity, at least over the narrow range which PNG 2572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * represents. Consequently 'G' is always sRGB encoded, while 2573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 'A' is linear. We need the linear background colors. 2574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2575b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (output_encoding == P_sRGB) /* else already linear */ 2576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This may produce a value not exactly matching the 2578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * background, but that's ok because these numbers are only 2579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * used when alpha != 0 2580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_r = png_sRGB_table[back_r]; 2582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_g = png_sRGB_table[back_g]; 2583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_b = png_sRGB_table[back_b]; 2584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (a=1; a<5; ++a) 2587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int g; 2589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled 2591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * by an 8-bit alpha value (0..255). 2592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 alpha = 51 * a; 2594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 back_rx = (255-alpha) * back_r; 2595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 back_gx = (255-alpha) * back_g; 2596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 back_bx = (255-alpha) * back_b; 2597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (g=0; g<6; ++g) 2599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 gray = png_sRGB_table[g*51] * alpha; 2601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, i++, 2603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_sRGB_FROM_LINEAR(gray + back_rx), 2604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_sRGB_FROM_LINEAR(gray + back_gx), 2605b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB); 2606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2608b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = i; 2610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_GA; 2611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_COLOR_TYPE_RGB: 2616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_COLOR_TYPE_RGB_ALPHA: 2617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Exclude the case where the output is gray; we can always handle this 2618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * with the cases above. 2619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0) 2621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The color-map will be grayscale, so we may as well convert the 2623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * input RGB values to a simple grayscale and use the grayscale 2624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * code above. 2625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * NOTE: calling this apparently damages the recognition of the 2627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * transparent color in background color handling; call 2628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * png_set_tRNS_to_alpha before png_set_background_fixed. 2629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1, 2631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik -1); 2632b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari data_encoding = P_sRGB; 2633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The output will now be one or two 8-bit gray or gray+alpha 2635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * channels. The more complex case arises when the input has alpha. 2636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 2638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->num_trans > 0) && 2639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (output_format & PNG_FORMAT_FLAG_ALPHA) != 0) 2640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Both input and output have an alpha channel, so no background 2642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * processing is required; just map the GA bytes to the right 2643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * color-map entry. 2644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik expand_tRNS = 1; 2646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries) 2648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "rgb[ga] color-map: too few entries"); 2649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = make_ga_colormap(display); 2651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik background_index = PNG_CMAP_GA_BACKGROUND; 2652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_GA; 2653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Either the input or the output has no alpha channel, so there 2658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * will be no non-opaque pixels in the color-map; it will just be 2659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * grayscale. 2660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries) 2662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "rgb[gray] color-map: too few entries"); 2663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Ideally this code would use libpng to do the gamma correction, 2665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * but if an input alpha channel is to be removed we will hit the 2666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * libpng bug in gamma+compose+rgb-to-gray (the double gamma 2667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * correction bug). Fix this by dropping the gamma correction in 2668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this case and doing it in the palette; this will result in 2669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * duplicate palette entries, but that's better than the 2670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * alternative of double gamma correction. 2671b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 2673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->num_trans > 0) && 2674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_gamma_not_sRGB(png_ptr->colorspace.gamma)) 2675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = make_gray_file_colormap(display); 2677b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari data_encoding = P_FILE; 2678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = make_gray_colormap(display); 2682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* But if the input has alpha or transparency it must be removed 2684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 2686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->num_trans > 0) 2687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_color_16 c; 2689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 gray = back_g; 2690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We need to ensure that the application background exists in 2692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the colormap and that completely transparent pixels map to 2693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it. Achieve this simply by ensuring that the entry 2694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * selected for the background really is the background color. 2695b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2696b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (data_encoding == P_FILE) /* from the fixup above */ 2697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2698b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The app supplied a gray which is in output_encoding, we 2699b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * need to convert it to a value of the input (P_FILE) 2700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * encoding then set this palette entry to the required 2701b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * output encoding. 2702b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2703b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (output_encoding == P_sRGB) 2704b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari gray = png_sRGB_table[gray]; /* now P_LINEAR */ 2705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik gray = PNG_DIV257(png_gamma_16bit_correct(gray, 2707b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_ptr->colorspace.gamma)); /* now P_FILE */ 2708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And make sure the corresponding palette entry contains 2710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * exactly the required sRGB value. 2711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, gray, back_g, back_g, 2713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_g, 0/*unused*/, output_encoding); 2714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2715b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2716b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (output_encoding == P_LINEAR) 2717b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik gray = PNG_sRGB_FROM_LINEAR(gray * 255); 2719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* And make sure the corresponding palette entry matches. 2721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, gray, back_g, back_g, 2723b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari back_g, 0/*unused*/, P_LINEAR); 2724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2726b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The background passed to libpng, however, must be the 2727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * output (normally sRGB) value. 2728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.index = 0; /*unused*/ 2730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.gray = c.red = c.green = c.blue = (png_uint_16)gray; 2731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* NOTE: the following is apparently a bug in libpng. Without 2733b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it the transparent color recognition in 2734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * png_set_background_fixed seems to go wrong. 2735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik expand_tRNS = 1; 2737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_background_fixed(png_ptr, &c, 2738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, 2739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 0/*gamma: not used*/); 2740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_NONE; 2743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* output is color */ 2747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We could use png_quantize here so long as there is no transparent 2749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * color or alpha; png_quantize ignores alpha. Easier overall just 2750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube. 2751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Consequently we always want libpng to produce sRGB data. 2752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2753b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari data_encoding = P_sRGB; 2754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Is there any transparency or alpha? */ 2756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA || 2757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->num_trans > 0) 2758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Is there alpha in the output too? If so all four channels are 2760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * processed into a special RGB cube with alpha support. 2761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (output_format & PNG_FORMAT_FLAG_ALPHA) 2763b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 r; 2765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) 2767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "rgb+alpha color-map: too few entries"); 2768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = make_rgb_colormap(display); 2770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Add a transparent entry. */ 2772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, cmap_entries, 255, 255, 2773b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 255, 0, P_sRGB); 2774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is stored as the background index for the processing 2776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * algorithm. 2777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik background_index = cmap_entries++; 2779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Add 27 r,g,b entries each with alpha 0.5. */ 2781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (r=0; r<256; r = (r << 1) | 0x7f) 2782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 g; 2784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (g=0; g<256; g = (g << 1) | 0x7f) 2786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 b; 2788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This generates components with the values 0, 127 and 2790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 255 2791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2792b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (b=0; b<256; b = (b << 1) | 0x7f) 2793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, cmap_entries++, 2794b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari r, g, b, 128, P_sRGB); 2795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik expand_tRNS = 1; 2799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_RGB_ALPHA; 2800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Alpha/transparency must be removed. The background must 2805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * exist in the color map (achieved by setting adding it after 2806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the 666 color-map). If the standard processing code will 2807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pick up this entry automatically that's all that is 2808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * required; libpng can be called to do the background 2809b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * processing. 2810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int sample_size = 2812b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_IMAGE_SAMPLE_SIZE(output_format); 2813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 r, g, b; /* sRGB background */ 2814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries) 2816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "rgb-alpha color-map: too few entries"); 2817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = make_rgb_colormap(display); 2819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, cmap_entries, back_r, 2821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_g, back_b, 0/*unused*/, output_encoding); 2822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2823b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (output_encoding == P_LINEAR) 2824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik r = PNG_sRGB_FROM_LINEAR(back_r * 255); 2826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik g = PNG_sRGB_FROM_LINEAR(back_g * 255); 2827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik b = PNG_sRGB_FROM_LINEAR(back_b * 255); 2828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik r = back_r; 2833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik g = back_g; 2834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik b = back_g; 2835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Compare the newly-created color-map entry with the one the 2838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG_CMAP_RGB algorithm will use. If the two entries don't 2839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * match, add the new one and set this as the background 2840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * index. 2841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (memcmp((png_const_bytep)display->colormap + 2843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sample_size * cmap_entries, 2844b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_const_bytep)display->colormap + 2845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sample_size * PNG_RGB_INDEX(r,g,b), 2846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik sample_size) != 0) 2847b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The background color must be added. */ 2849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik background_index = cmap_entries++; 2850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Add 27 r,g,b entries each with created by composing with 2852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the background at alpha 0.5. 2853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (r=0; r<256; r = (r << 1) | 0x7f) 2855b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2856b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (g=0; g<256; g = (g << 1) | 0x7f) 2857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This generates components with the values 0, 127 2859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * and 255 2860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (b=0; b<256; b = (b << 1) | 0x7f) 2862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, cmap_entries++, 2863b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_colormap_compose(display, r, P_sRGB, 128, 2864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_r, output_encoding), 2865b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_colormap_compose(display, g, P_sRGB, 128, 2866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_g, output_encoding), 2867b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_colormap_compose(display, b, P_sRGB, 128, 2868b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_b, output_encoding), 2869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 0/*unused*/, output_encoding); 2870b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik expand_tRNS = 1; 2874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_RGB_ALPHA; 2875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* background color is in the standard color-map */ 2878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_color_16 c; 2880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.index = 0; /*unused*/ 2882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.red = (png_uint_16)back_r; 2883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.gray = c.green = (png_uint_16)back_g; 2884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.blue = (png_uint_16)back_b; 2885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_background_fixed(png_ptr, &c, 2887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, 2888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 0/*gamma: not used*/); 2889b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2890b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_RGB; 2891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2894b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* no alpha or transparency in the input */ 2896b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Alpha in the output is irrelevant, simply map the opaque input 2898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pixels to the 6x6x6 color-map. 2899b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries) 2901b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "rgb color-map: too few entries"); 2902b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = make_rgb_colormap(display); 2904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_RGB; 2905b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_COLOR_TYPE_PALETTE: 2910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* It's already got a color-map. It may be necessary to eliminate the 2911b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * tRNS entries though. 2912b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int num_trans = png_ptr->num_trans; 2915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL; 2916b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_colorp colormap = png_ptr->palette; 2917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const int do_background = trans != NULL && 2918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (output_format & PNG_FORMAT_FLAG_ALPHA) == 0; 2919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int i; 2920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2921b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Just in case: */ 2922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (trans == NULL) 2923b50c217251b086440efcdb273c22f86a06c80cbaChris Craik num_trans = 0; 2924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_processing = PNG_CMAP_NONE; 2926b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari data_encoding = P_FILE; /* Don't change from color-map indicies */ 2927b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = png_ptr->num_palette; 2928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (cmap_entries > 256) 2929b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cmap_entries = 256; 2930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (cmap_entries > image->colormap_entries) 2932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "palette color-map: too few entries"); 2933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=0; i < cmap_entries; ++i) 2935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (do_background && i < num_trans && trans[i] < 255) 2937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (trans[i] == 0) 2939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, i, back_r, back_g, 2940b50c217251b086440efcdb273c22f86a06c80cbaChris Craik back_b, 0, output_encoding); 2941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Must compose the PNG file color in the color-map entry 2945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * on the sRGB color in 'back'. 2946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, i, 2948b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_colormap_compose(display, colormap[i].red, P_FILE, 2949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik trans[i], back_r, output_encoding), 2950b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_colormap_compose(display, colormap[i].green, P_FILE, 2951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik trans[i], back_g, output_encoding), 2952b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_colormap_compose(display, colormap[i].blue, P_FILE, 2953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik trans[i], back_b, output_encoding), 2954b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari output_encoding == P_LINEAR ? trans[i] * 257U : 2955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik trans[i], 2956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_encoding); 2957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_create_colormap_entry(display, i, colormap[i].red, 2962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik colormap[i].green, colormap[i].blue, 2963b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/); 2964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The PNG data may have indicies packed in fewer than 8 bits, it 2967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * must be expanded if so. 2968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->bit_depth < 8) 2970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_packing(png_ptr); 2971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 2975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "invalid PNG color type"); 2976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /*NOT REACHED*/ 2977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now deal with the output processing */ 2981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (expand_tRNS && png_ptr->num_trans > 0 && 2982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0) 2983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_tRNS_to_alpha(png_ptr); 2984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2985b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (data_encoding) 2986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 2988b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "bad data option (internal error)"); 2989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 2990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2991b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case P_sRGB: 2992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Change to 8-bit sRGB */ 2993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); 2994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* FALL THROUGH */ 2995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2996b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari case P_FILE: 2997b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->bit_depth > 8) 2998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_scale_16(png_ptr); 2999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (cmap_entries > 256 || cmap_entries > image->colormap_entries) 3003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "color map overflow (BAD internal error)"); 3004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->colormap_entries = cmap_entries; 3006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Double check using the recorded background index */ 3008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (output_processing) 3009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_NONE: 3011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (background_index != PNG_CMAP_NONE_BACKGROUND) 3012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto bad_background; 3013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_GA: 3016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (background_index != PNG_CMAP_GA_BACKGROUND) 3017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto bad_background; 3018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_TRANS: 3021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (background_index >= cmap_entries || 3022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik background_index != PNG_CMAP_TRANS_BACKGROUND) 3023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto bad_background; 3024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_RGB: 3027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (background_index != PNG_CMAP_RGB_BACKGROUND) 3028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto bad_background; 3029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_RGB_ALPHA: 3032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND) 3033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto bad_background; 3034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 3037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "bad processing option (internal error)"); 3038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik bad_background: 3040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "bad background index (internal error)"); 3041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->colormap_processing = output_processing; 3044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3045b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1/*ok*/; 3046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The final part of the color-map read called from png_image_finish_read. */ 3049b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 3050b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_read_and_map(png_voidp argument) 3051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_read_control *display = png_voidcast(png_image_read_control*, 3053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik argument); 3054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = display->image; 3055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = image->opaque->png_ptr; 3056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int passes; 3057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Called when the libpng data must be transformed into the color-mapped 3059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * form. There is a local row buffer in display->local and this routine must 3060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * do the interlace handling. 3061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3062b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (png_ptr->interlaced) 3063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_INTERLACE_NONE: 3065b50c217251b086440efcdb273c22f86a06c80cbaChris Craik passes = 1; 3066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_INTERLACE_ADAM7: 3069b50c217251b086440efcdb273c22f86a06c80cbaChris Craik passes = PNG_INTERLACE_ADAM7_PASSES; 3070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 3073b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "unknown interlace type"); 3074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 height = image->height; 3078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 width = image->width; 3079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int proc = display->colormap_processing; 3080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep first_row = png_voidcast(png_bytep, display->first_row); 3081b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t step_row = display->row_bytes; 3082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int pass; 3083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (pass = 0; pass < passes; ++pass) 3085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int startx, stepx, stepy; 3087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y; 3088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) 3090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The row may be empty for a short image: */ 3092b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_PASS_COLS(width, pass) == 0) 3093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik continue; 3094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik startx = PNG_PASS_START_COL(pass); 3096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepx = PNG_PASS_COL_OFFSET(pass); 3097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y = PNG_PASS_START_ROW(pass); 3098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepy = PNG_PASS_ROW_OFFSET(pass); 3099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y = 0; 3104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik startx = 0; 3105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepx = stepy = 1; 3106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; y<height; y += stepy) 3109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep inrow = png_voidcast(png_bytep, display->local_row); 3111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep outrow = first_row + y * step_row; 3112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep end_row = outrow + width; 3113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Read read the libpng data into the temporary buffer. */ 3115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_row(png_ptr, inrow, NULL); 3116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now process the row according to the processing option, note 3118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * that the caller verifies that the format of the libpng output 3119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * data is as required. 3120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow += startx; 3122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (proc) 3123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_GA: 3125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; outrow < end_row; outrow += stepx) 3126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The data is always in the PNG order */ 3128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int gray = *inrow++; 3129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int alpha = *inrow++; 3130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int entry; 3131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* NOTE: this code is copied as a comment in 3133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * make_ga_colormap above. Please update the 3134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * comment if you change this code! 3135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha > 229) /* opaque */ 3137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry = (231 * gray + 128) >> 8; 3139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (alpha < 26) /* transparent */ 3141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry = 231; 3143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* partially opaque */ 3145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray); 3147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *outrow = (png_byte)entry; 3150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_TRANS: 3154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; outrow < end_row; outrow += stepx) 3155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte gray = *inrow++; 3157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte alpha = *inrow++; 3158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha == 0) 3160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *outrow = PNG_CMAP_TRANS_BACKGROUND; 3161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (gray != PNG_CMAP_TRANS_BACKGROUND) 3163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *outrow = gray; 3164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1); 3167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_RGB: 3171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; outrow < end_row; outrow += stepx) 3172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]); 3174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik inrow += 3; 3175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_RGB_ALPHA: 3179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; outrow < end_row; outrow += stepx) 3180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int alpha = inrow[3]; 3182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Because the alpha entries only hold alpha==0.5 values 3184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * split the processing at alpha==0.25 (64) and 0.75 3185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (196). 3186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha >= 196) 3189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], 3190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik inrow[2]); 3191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (alpha < 64) 3193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND; 3194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Likewise there are three entries for each of r, g 3198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * and b. We could select the entry by popcount on 3199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the top two bits on those architectures that 3200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * support it, this is what the code below does, 3201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * crudely. 3202b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1; 3204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Here are how the values map: 3206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 0x00 .. 0x3f -> 0 3208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 0x40 .. 0xbf -> 1 3209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 0xc0 .. 0xff -> 2 3210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * So, as above with the explicit alpha checks, the 3212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * breakpoints are at 64 and 196. 3213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (inrow[0] & 0x80) back_i += 9; /* red */ 3215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (inrow[0] & 0x40) back_i += 9; 3216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (inrow[0] & 0x80) back_i += 3; /* green */ 3217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (inrow[0] & 0x40) back_i += 3; 3218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (inrow[0] & 0x80) back_i += 1; /* blue */ 3219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (inrow[0] & 0x40) back_i += 1; 3220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *outrow = (png_byte)back_i; 3222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik inrow += 4; 3225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 3229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 3236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3238b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 3239b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_read_colormapped(png_voidp argument) 3240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_read_control *display = png_voidcast(png_image_read_control*, 3242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik argument); 3243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = display->image; 3244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_controlp control = image->opaque; 3245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = control->png_ptr; 3246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_inforp info_ptr = control->info_ptr; 3247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int passes = 0; /* As a flag */ 3249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_SKIP_CHUNKS(png_ptr); 3251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Update the 'info' structure and make sure the result is as required; first 3253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * make sure to turn on the interlace handling if it will be required 3254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (because it can't be turned on *after* the call to png_read_update_info!) 3255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (display->colormap_processing == PNG_CMAP_NONE) 3257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik passes = png_set_interlace_handling(png_ptr); 3258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_update_info(png_ptr, info_ptr); 3260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The expected output can be deduced from the colormap_processing option. */ 3262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (display->colormap_processing) 3263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_NONE: 3265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Output must be one channel and one byte per pixel, the output 3266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * encoding can be anything. 3267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE || 3269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->color_type == PNG_COLOR_TYPE_GRAY) && 3270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->bit_depth == 8) 3271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto bad_output; 3274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_TRANS: 3276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_GA: 3277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Output must be two channels and the 'G' one must be sRGB, the latter 3278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * can be checked with an exact number because it should have been set 3279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * to this number above! 3280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA && 3282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->bit_depth == 8 && 3283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->screen_gamma == PNG_GAMMA_sRGB && 3284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->colormap_entries == 256) 3285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto bad_output; 3288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_RGB: 3290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Output must be 8-bit sRGB encoded RGB */ 3291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (info_ptr->color_type == PNG_COLOR_TYPE_RGB && 3292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->bit_depth == 8 && 3293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->screen_gamma == PNG_GAMMA_sRGB && 3294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->colormap_entries == 216) 3295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik goto bad_output; 3298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_CMAP_RGB_ALPHA: 3300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Output must be 8-bit sRGB encoded RGBA */ 3301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA && 3302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->bit_depth == 8 && 3303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->screen_gamma == PNG_GAMMA_sRGB && 3304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->colormap_entries == 244 /* 216 + 1 + 27 */) 3305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* goto bad_output; */ 3308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* FALL THROUGH */ 3309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 3311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik bad_output: 3312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "bad color-map processing (internal error)"); 3313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now read the rows. Do this here if it is possible to read directly into 3316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the output buffer, otherwise allocate a local row buffer of the maximum 3317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * size libpng requires and call the relevant processing routine safely. 3318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidp first_row = display->buffer; 3321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t row_bytes = display->row_stride; 3322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following expression is designed to work correctly whether it gives 3324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * a signed or an unsigned result. 3325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (row_bytes < 0) 3327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char *ptr = png_voidcast(char*, first_row); 3329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptr += (image->height-1) * (-row_bytes); 3330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik first_row = png_voidcast(png_voidp, ptr); 3331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->first_row = first_row; 3334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->row_bytes = row_bytes; 3335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (passes == 0) 3338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result; 3340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); 3341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->local_row = row; 3343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = png_safe_execute(image, png_image_read_and_map, display); 3344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->local_row = NULL; 3345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, row); 3346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return result; 3348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_alloc_size_t row_bytes = display->row_bytes; 3353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (--passes >= 0) 3355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y = image->height; 3357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep row = png_voidcast(png_bytep, display->first_row); 3358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (y-- > 0) 3360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_row(png_ptr, row, NULL); 3362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row += row_bytes; 3363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 3367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Just the row reading part of png_image_read. */ 3371b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 3372b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_read_composite(png_voidp argument) 3373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_read_control *display = png_voidcast(png_image_read_control*, 3375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik argument); 3376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = display->image; 3377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = image->opaque->png_ptr; 3378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int passes; 3379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (png_ptr->interlaced) 3381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_INTERLACE_NONE: 3383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik passes = 1; 3384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_INTERLACE_ADAM7: 3387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik passes = PNG_INTERLACE_ADAM7_PASSES; 3388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 3391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "unknown interlace type"); 3392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 height = image->height; 3396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 width = image->width; 3397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t step_row = display->row_bytes; 3398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int channels = (image->format & PNG_FORMAT_FLAG_COLOR) ? 3 : 1; 3399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int pass; 3400b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (pass = 0; pass < passes; ++pass) 3402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int startx, stepx, stepy; 3404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y; 3405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) 3407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The row may be empty for a short image: */ 3409b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_PASS_COLS(width, pass) == 0) 3410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik continue; 3411b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik startx = PNG_PASS_START_COL(pass) * channels; 3413b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepx = PNG_PASS_COL_OFFSET(pass) * channels; 3414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y = PNG_PASS_START_ROW(pass); 3415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepy = PNG_PASS_ROW_OFFSET(pass); 3416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3419b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y = 0; 3421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik startx = 0; 3422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepx = channels; 3423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepy = 1; 3424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; y<height; y += stepy) 3427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep inrow = png_voidcast(png_bytep, display->local_row); 3429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep outrow; 3430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep end_row; 3431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Read the row, which is packed: */ 3433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_row(png_ptr, inrow, NULL); 3434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow = png_voidcast(png_bytep, display->first_row); 3436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow += y * step_row; 3437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik end_row = outrow + width * channels; 3438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3439b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now do the composition on each pixel in this row. */ 3440b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow += startx; 3441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; outrow < end_row; outrow += stepx) 3442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte alpha = inrow[channels]; 3444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha > 0) /* else no change to the output */ 3446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int c; 3448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (c=0; c<channels; ++c) 3450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 component = inrow[c]; 3452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha < 255) /* else just use component */ 3454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is PNG_OPTIMIZED_ALPHA, the component value 3456b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is a linear 8-bit value. Combine this with the 3457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * current outrow[c] value which is sRGB encoded. 3458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Arithmetic here is 16-bits to preserve the output 3459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * values correctly. 3460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component *= 257*255; /* =65535 */ 3462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component += (255-alpha)*png_sRGB_table[outrow[c]]; 3463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* So 'component' is scaled by 255*65535 and is 3465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * therefore appropriate for the sRGB to linear 3466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * conversion table. 3467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component = PNG_sRGB_FROM_LINEAR(component); 3469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow[c] = (png_byte)component; 3472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik inrow += channels+1; /* components and alpha channel */ 3476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 3482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The do_local_background case; called when all the following transforms are to 3485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be done: 3486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG_RGB_TO_GRAY 3488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG_COMPOSITE 3489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG_GAMMA 3490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * This is a work-round for the fact that both the PNG_RGB_TO_GRAY and 3492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG_COMPOSITE code performs gamma correction, so we get double gamma 3493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * correction. The fix-up is to prevent the PNG_COMPOSITE operation happening 3494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * inside libpng, so this routine sees an 8 or 16-bit gray+alpha row and handles 3495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the removal or pre-multiplication of the alpha channel. 3496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3497b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 3498b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_read_background(png_voidp argument) 3499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_read_control *display = png_voidcast(png_image_read_control*, 3501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik argument); 3502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = display->image; 3503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = image->opaque->png_ptr; 3504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_inforp info_ptr = image->opaque->info_ptr; 3505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 height = image->height; 3506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 width = image->width; 3507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int pass, passes; 3508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Double check the convoluted logic below. We expect to get here with 3510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * libpng doing rgb to gray and gamma correction but background processing 3511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * left to the png_image_read_background function. The rows libpng produce 3512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * might be 8 or 16-bit but should always have two channels; gray plus alpha. 3513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0) 3515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "lost rgb to gray"); 3516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((png_ptr->transformations & PNG_COMPOSE) != 0) 3518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "unexpected compose"); 3519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_get_channels(png_ptr, info_ptr) != 2) 3521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "lost/gained channels"); 3522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Expect the 8-bit case to always remove the alpha channel */ 3524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 && 3525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (image->format & PNG_FORMAT_FLAG_ALPHA) != 0) 3526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "unexpected 8-bit transformation"); 3527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (png_ptr->interlaced) 3529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_INTERLACE_NONE: 3531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik passes = 1; 3532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_INTERLACE_ADAM7: 3535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik passes = PNG_INTERLACE_ADAM7_PASSES; 3536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 3539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "unknown interlace type"); 3540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3542b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Use direct access to info_ptr here because otherwise the simplified API 3543b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * would require PNG_EASY_ACCESS_SUPPORTED (just for this.) Note this is 3544b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * checking the value after libpng expansions, not the original value in the 3545b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * PNG. 3546b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 3547b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari switch (info_ptr->bit_depth) 3548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 3550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "unexpected bit depth"); 3551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 8: 3554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 8-bit sRGB gray values with an alpha channel; the alpha channel is 3555b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * to be removed by composing on a background: either the row if 3556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * display->background is NULL or display->background->green if not. 3557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Unlike the code above ALPHA_OPTIMIZED has *not* been done. 3558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep first_row = png_voidcast(png_bytep, display->first_row); 3561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t step_row = display->row_bytes; 3562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (pass = 0; pass < passes; ++pass) 3564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep row = png_voidcast(png_bytep, 3566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->first_row); 3567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int startx, stepx, stepy; 3568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y; 3569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) 3571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The row may be empty for a short image: */ 3573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_PASS_COLS(width, pass) == 0) 3574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik continue; 3575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik startx = PNG_PASS_START_COL(pass); 3577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepx = PNG_PASS_COL_OFFSET(pass); 3578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y = PNG_PASS_START_ROW(pass); 3579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepy = PNG_PASS_ROW_OFFSET(pass); 3580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y = 0; 3585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik startx = 0; 3586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepx = stepy = 1; 3587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (display->background == NULL) 3590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; y<height; y += stepy) 3592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep inrow = png_voidcast(png_bytep, 3594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->local_row); 3595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep outrow = first_row + y * step_row; 3596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep end_row = outrow + width; 3597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Read the row, which is packed: */ 3599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_row(png_ptr, inrow, NULL); 3600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now do the composition on each pixel in this row. */ 3602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow += startx; 3603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; outrow < end_row; outrow += stepx) 3604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte alpha = inrow[1]; 3606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha > 0) /* else no change to the output */ 3608b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 component = inrow[0]; 3610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha < 255) /* else just use component */ 3612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Since PNG_OPTIMIZED_ALPHA was not set it is 3614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * necessary to invert the sRGB transfer 3615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * function and multiply the alpha out. 3616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component = png_sRGB_table[component] * alpha; 3618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component += png_sRGB_table[outrow[0]] * 3619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (255-alpha); 3620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component = PNG_sRGB_FROM_LINEAR(component); 3621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow[0] = (png_byte)component; 3624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik inrow += 2; /* gray and alpha channel */ 3627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* constant background value */ 3632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte background8 = display->background->green; 3634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16 background = png_sRGB_table[background8]; 3635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; y<height; y += stepy) 3637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep inrow = png_voidcast(png_bytep, 3639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->local_row); 3640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep outrow = first_row + y * step_row; 3641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep end_row = outrow + width; 3642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Read the row, which is packed: */ 3644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_row(png_ptr, inrow, NULL); 3645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now do the composition on each pixel in this row. */ 3647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow += startx; 3648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; outrow < end_row; outrow += stepx) 3649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte alpha = inrow[1]; 3651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha > 0) /* else use background */ 3653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 component = inrow[0]; 3655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha < 255) /* else just use component */ 3657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component = png_sRGB_table[component] * alpha; 3659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component += background * (255-alpha); 3660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component = PNG_sRGB_FROM_LINEAR(component); 3661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow[0] = (png_byte)component; 3664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow[0] = background8; 3668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik inrow += 2; /* gray and alpha channel */ 3670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3671b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row += display->row_bytes; 3673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 16: 3680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must 3681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * still be done and, maybe, the alpha channel removed. This code also 3682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * handles the alpha-first option. 3683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16p first_row = png_voidcast(png_uint_16p, 3686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->first_row); 3687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The division by two is safe because the caller passed in a 3688b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * stride which was multiplied by 2 (below) to get row_bytes. 3689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t step_row = display->row_bytes / 2; 3691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0; 3692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int outchannels = 1+preserve_alpha; 3693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int swap_alpha = 0; 3694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3695b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED 3696b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (preserve_alpha && (image->format & PNG_FORMAT_FLAG_AFIRST)) 3697b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari swap_alpha = 1; 3698b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari# endif 3699b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (pass = 0; pass < passes; ++pass) 3701b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3702b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int startx, stepx, stepy; 3703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y; 3704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The 'x' start and step are adjusted to output components here. 3706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->interlaced == PNG_INTERLACE_ADAM7) 3708b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The row may be empty for a short image: */ 3710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (PNG_PASS_COLS(width, pass) == 0) 3711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik continue; 3712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik startx = PNG_PASS_START_COL(pass) * outchannels; 3714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepx = PNG_PASS_COL_OFFSET(pass) * outchannels; 3715b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y = PNG_PASS_START_ROW(pass); 3716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepy = PNG_PASS_ROW_OFFSET(pass); 3717b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik y = 0; 3722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik startx = 0; 3723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepx = outchannels; 3724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik stepy = 1; 3725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3726b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; y<height; y += stepy) 3728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p inrow; 3730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16p outrow = first_row + y*step_row; 3731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16p end_row = outrow + width * outchannels; 3732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3733b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Read the row, which is packed: */ 3734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_row(png_ptr, png_voidcast(png_bytep, 3735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->local_row), NULL); 3736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik inrow = png_voidcast(png_const_uint_16p, display->local_row); 3737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now do the pre-multiplication on each pixel in this row. 3739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow += startx; 3741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (; outrow < end_row; outrow += stepx) 3742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 component = inrow[0]; 3744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16 alpha = inrow[1]; 3745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha > 0) /* else 0 */ 3747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha < 65535) /* else just use component */ 3749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component *= alpha; 3751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component += 32767; 3752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component /= 65535; 3753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component = 0; 3758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow[swap_alpha] = (png_uint_16)component; 3760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (preserve_alpha) 3761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik outrow[1 ^ swap_alpha] = alpha; 3762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3763b50c217251b086440efcdb273c22f86a06c80cbaChris Craik inrow += 2; /* components and alpha channel */ 3764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 3769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 3772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 3773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The guts of png_image_finish_read as a png_safe_execute callback. */ 3775b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 3776b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_read_direct(png_voidp argument) 3777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 3778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_read_control *display = png_voidcast(png_image_read_control*, 3779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik argument); 3780b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = display->image; 3781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = image->opaque->png_ptr; 3782b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_inforp info_ptr = image->opaque->info_ptr; 3783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 format = image->format; 3785b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0; 3786b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int do_local_compose = 0; 3787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int do_local_background = 0; /* to avoid double gamma correction bug */ 3788b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int passes = 0; 3789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Add transforms to ensure the correct output format is produced then check 3791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * that the required implementation support is there. Always expand; always 3792b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * need 8 bits minimum, no palette and expanded tRNS. 3793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3794b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_expand(png_ptr); 3795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now check the format to see if it was modified. */ 3797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 base_format = png_image_format(png_ptr) & 3799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */; 3800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 change = format ^ base_format; 3801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point output_gamma; 3802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int mode; /* alpha mode */ 3803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Do this first so that we have a record if rgb to gray is happening. */ 3805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (change & PNG_FORMAT_FLAG_COLOR) 3806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* gray<->color transformation required. */ 3808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_COLOR) 3809b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_gray_to_rgb(png_ptr); 3810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3812b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* libpng can't do both rgb to gray and 3814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * background/pre-multiplication if there is also significant gamma 3815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * correction, because both operations require linear colors and 3816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the code only supports one transform doing the gamma correction. 3817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Handle this by doing the pre-multiplication or background 3818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * operation in this code, if necessary. 3819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * TODO: fix this by rewriting pngrtran.c (!) 3821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * For the moment (given that fixing this in pngrtran.c is an 3823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * enormous change) 'do_local_background' is used to indicate that 3824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the problem exists. 3825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (base_format & PNG_FORMAT_FLAG_ALPHA) 3827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do_local_background = 1/*maybe*/; 3828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, 3830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT); 3831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik change &= ~PNG_FORMAT_FLAG_COLOR; 3834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise. 3837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point input_gamma_default; 3840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((base_format & PNG_FORMAT_FLAG_LINEAR) && 3842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0) 3843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik input_gamma_default = PNG_GAMMA_LINEAR; 3844b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik input_gamma_default = PNG_DEFAULT_sRGB; 3846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3847b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Call png_set_alpha_mode to set the default for the input gamma; the 3848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * output gamma is set by a second call below. 3849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default); 3851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (linear) 3854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3855b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If there *is* an alpha channel in the input it must be multiplied 3856b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG. 3857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (base_format & PNG_FORMAT_FLAG_ALPHA) 3859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik mode = PNG_ALPHA_STANDARD; /* associated alpha */ 3860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik mode = PNG_ALPHA_PNG; 3863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_gamma = PNG_GAMMA_LINEAR; 3865b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3868b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik mode = PNG_ALPHA_PNG; 3870b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_gamma = PNG_DEFAULT_sRGB; 3871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If 'do_local_background' is set check for the presence of gamma 3874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * correction; this is part of the work-round for the libpng bug 3875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * described above. 3876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * TODO: fix libpng and remove this. 3878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (do_local_background) 3880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_fixed_point gtest; 3882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is 'png_gamma_threshold' from pngrtran.c; the test used for 3884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * gamma correction, the screen gamma hasn't been set on png_struct 3885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * yet; it's set below. png_struct::gamma, however, is set to the 3886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * final value. 3887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_muldiv(>est, output_gamma, png_ptr->colorspace.gamma, 3889b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_FP_1) && !png_gamma_significant(gtest)) 3890b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do_local_background = 0; 3891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (mode == PNG_ALPHA_STANDARD) 3893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3894b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do_local_background = 2/*required*/; 3895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik mode = PNG_ALPHA_PNG; /* prevent libpng doing it */ 3896b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* else leave as 1 for the checks below */ 3899b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3901b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If the bit-depth changes then handle that here. */ 3902b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (change & PNG_FORMAT_FLAG_LINEAR) 3903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (linear /*16-bit output*/) 3905b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_expand_16(png_ptr); 3906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3907b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* 8-bit output */ 3908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_scale_16(png_ptr); 3909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik change &= ~PNG_FORMAT_FLAG_LINEAR; 3911b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3912b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now the background/alpha channel changes. */ 3914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (change & PNG_FORMAT_FLAG_ALPHA) 3915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3916b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Removing an alpha channel requires composition for the 8-bit 3917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * formats; for the 16-bit it is already done, above, by the 3918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pre-multiplication and the channel just needs to be stripped. 3919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (base_format & PNG_FORMAT_FLAG_ALPHA) 3921b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If RGB->gray is happening the alpha channel must be left and the 3923b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * operation completed locally. 3924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 3925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * TODO: fix libpng and remove this. 3926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3927b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (do_local_background) 3928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do_local_background = 2/*required*/; 3929b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 16-bit output: just remove the channel */ 3931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (linear) /* compose on black (well, pre-multiply) */ 3932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_strip_alpha(png_ptr); 3933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 8-bit output: do an appropriate compose */ 3935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (display->background != NULL) 3936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_color_16 c; 3938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.index = 0; /*unused*/ 3940b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.red = display->background->red; 3941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.green = display->background->green; 3942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.blue = display->background->blue; 3943b50c217251b086440efcdb273c22f86a06c80cbaChris Craik c.gray = display->background->green; 3944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is always an 8-bit sRGB value, using the 'green' channel 3946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * for gray is much better than calculating the luminance here; 3947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * we can get off-by-one errors in that calculation relative to 3948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the app expectations and that will show up in transparent 3949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pixels. 3950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_background_fixed(png_ptr, &c, 3952b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/, 3953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 0/*gamma: not used*/); 3954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* compose on row: implemented below. */ 3957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do_local_compose = 1; 3959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This leaves the alpha channel in the output, so it has to be 3960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * removed by the code below. Set the encoding to the 'OPTIMIZE' 3961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * one so the code only has to hack on the pixels that require 3962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * composition. 3963b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik mode = PNG_ALPHA_OPTIMIZED; 3965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* output needs an alpha channel */ 3969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is tricky because it happens before the swap operation has 3971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * been accomplished; however, the swap does *not* swap the added 3972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * alpha channel (weird API), so it must be added in the correct 3973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * place. 3974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 3975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 filler; /* opaque filler */ 3976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int where; 3977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (linear) 3979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik filler = 65535; 3980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik filler = 255; 3983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_FORMAT_AFIRST_SUPPORTED 3985b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_AFIRST) 3986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 3987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik where = PNG_FILLER_BEFORE; 3988b50c217251b086440efcdb273c22f86a06c80cbaChris Craik change &= ~PNG_FORMAT_FLAG_AFIRST; 3989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 3992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 3993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik where = PNG_FILLER_AFTER; 3994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_add_alpha(png_ptr, filler, where); 3996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 3997b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This stops the (irrelevant) call to swap_alpha below. */ 3999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik change &= ~PNG_FORMAT_FLAG_ALPHA; 4000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now set the alpha mode correctly; this is always done, even if there is 4003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * no alpha channel in either the input or the output because it correctly 4004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * sets the output gamma. 4005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_alpha_mode_fixed(png_ptr, mode, output_gamma); 4007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_FORMAT_BGR_SUPPORTED 4009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (change & PNG_FORMAT_FLAG_BGR) 4010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check only the output format; PNG is never BGR; don't do this if 4012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the output is gray, but fix up the 'format' value in that case. 4013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_COLOR) 4015b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_bgr(png_ptr); 4016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 4018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format &= ~PNG_FORMAT_FLAG_BGR; 4019b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik change &= ~PNG_FORMAT_FLAG_BGR; 4021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 4023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_FORMAT_AFIRST_SUPPORTED 4025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (change & PNG_FORMAT_FLAG_AFIRST) 4026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Only relevant if there is an alpha channel - it's particularly 4028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * important to handle this correctly because do_local_compose may 4029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be set above and then libpng will keep the alpha channel for this 4030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * code to remove. 4031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_ALPHA) 4033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Disable this if doing a local background, 4035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * TODO: remove this when local background is no longer required. 4036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (do_local_background != 2) 4038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_swap_alpha(png_ptr); 4039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 4042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format &= ~PNG_FORMAT_FLAG_AFIRST; 4043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4044b50c217251b086440efcdb273c22f86a06c80cbaChris Craik change &= ~PNG_FORMAT_FLAG_AFIRST; 4045b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 4047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If the *output* is 16-bit then we need to check for a byte-swap on this 4049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * architecture. 4050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (linear) 4052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_CONST png_uint_16 le = 0x0001; 4054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (*(png_const_bytep)&le) 4056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_swap(png_ptr); 4057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If change is not now 0 some transformation is missing - error out. */ 4060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (change) 4061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "png_read_image: unsupported transformation"); 4062b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4064b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_SKIP_CHUNKS(png_ptr); 4065b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Update the 'info' structure and make sure the result is as required; first 4067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * make sure to turn on the interlace handling if it will be required 4068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * (because it can't be turned on *after* the call to png_read_update_info!) 4069b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 4070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * TODO: remove the do_local_background fixup below. 4071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!do_local_compose && do_local_background != 2) 4073b50c217251b086440efcdb273c22f86a06c80cbaChris Craik passes = png_set_interlace_handling(png_ptr); 4074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_update_info(png_ptr, info_ptr); 4076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 info_format = 0; 4079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) 4081b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_format |= PNG_FORMAT_FLAG_COLOR; 4082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) 4084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* do_local_compose removes this channel below. */ 4086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (!do_local_compose) 4087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* do_local_background does the same if required. */ 4089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (do_local_background != 2 || 4090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (format & PNG_FORMAT_FLAG_ALPHA) != 0) 4091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_format |= PNG_FORMAT_FLAG_ALPHA; 4092b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (do_local_compose) /* internal error */ 4096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "png_image_read: alpha channel lost"); 4097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (info_ptr->bit_depth == 16) 4099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_format |= PNG_FORMAT_FLAG_LINEAR; 4100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_FORMAT_BGR_SUPPORTED 4102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->transformations & PNG_BGR) 4103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_format |= PNG_FORMAT_FLAG_BGR; 4104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 4105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_FORMAT_AFIRST_SUPPORTED 4107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (do_local_background == 2) 4108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (format & PNG_FORMAT_FLAG_AFIRST) 4110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_format |= PNG_FORMAT_FLAG_AFIRST; 4111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 || 4114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 && 4115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0)) 4116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (do_local_background == 2) 4118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "unexpected alpha swap transformation"); 4119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_format |= PNG_FORMAT_FLAG_AFIRST; 4121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 4123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is actually an internal error. */ 4125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (info_format != format) 4126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "png_read_image: invalid transformations"); 4127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now read the rows. If do_local_compose is set then it is necessary to use 4130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * a local row buffer. The output will be GA, RGBA or BGRA and must be 4131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * converted to G, RGB or BGR as appropriate. The 'local_row' member of the 4132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * display acts as a flag. 4133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidp first_row = display->buffer; 4136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t row_bytes = display->row_stride; 4137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (linear) 4139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_bytes *= 2; 4140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following expression is designed to work correctly whether it gives 4142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * a signed or an unsigned result. 4143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (row_bytes < 0) 4145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char *ptr = png_voidcast(char*, first_row); 4147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptr += (image->height-1) * (-row_bytes); 4148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik first_row = png_voidcast(png_voidp, ptr); 4149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4150b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4151b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->first_row = first_row; 4152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->row_bytes = row_bytes; 4153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (do_local_compose) 4156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result; 4158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); 4159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->local_row = row; 4161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = png_safe_execute(image, png_image_read_composite, display); 4162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->local_row = NULL; 4163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, row); 4164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4165b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return result; 4166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (do_local_background == 2) 4169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result; 4171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr)); 4172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->local_row = row; 4174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = png_safe_execute(image, png_image_read_background, display); 4175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->local_row = NULL; 4176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, row); 4177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return result; 4179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4181b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 4182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_alloc_size_t row_bytes = display->row_bytes; 4184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (--passes >= 0) 4186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y = image->height; 4188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep row = png_voidcast(png_bytep, display->first_row); 4189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (y-- > 0) 4191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4192b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_read_row(png_ptr, row, NULL); 4193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row += row_bytes; 4194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 4198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 4200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4201b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint PNGAPI 4202b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_finish_read(png_imagep image, png_const_colorp background, 4203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik void *buffer, png_int_32 row_stride, void *colormap) 4204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 4205b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image != NULL && image->version == PNG_IMAGE_VERSION) 4206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 check; 4208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (row_stride == 0) 4210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_stride = PNG_IMAGE_ROW_STRIDE(*image); 4211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (row_stride < 0) 4213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik check = -row_stride; 4214b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 4216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik check = row_stride; 4217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->opaque != NULL && buffer != NULL && 4219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik check >= PNG_IMAGE_ROW_STRIDE(*image)) 4220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 || 4222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (image->colormap_entries > 0 && colormap != NULL)) 4223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 4224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result; 4225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_read_control display; 4226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(&display, 0, (sizeof display)); 4228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display.image = image; 4229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display.buffer = buffer; 4230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display.row_stride = row_stride; 4231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display.colormap = colormap; 4232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display.background = background; 4233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display.local_row = NULL; 4234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Choose the correct 'end' routine; for the color-map case all the 4236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * setup has already been done. 4237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image->format & PNG_FORMAT_FLAG_COLORMAP) 4239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = 4240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_safe_execute(image, png_image_read_colormap, &display) && 4241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_safe_execute(image, png_image_read_colormapped, &display); 4242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 4244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = 4245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_safe_execute(image, png_image_read_direct, &display); 4246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_free(image); 4248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return result; 4249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 4252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 4253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_image_finish_read[color-map]: no color-map"); 4254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 4257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 4258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_image_finish_read: invalid argument"); 4259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 4260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (image != NULL) 4262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 4263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_image_finish_read: damaged PNG_IMAGE_VERSION"); 4264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 4266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 4267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 4268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* PNG_SIMPLIFIED_READ_SUPPORTED */ 4269893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif /* PNG_READ_SUPPORTED */ 4270