1893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* pngwutil.c - utilities to write a PNG file 3893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 4851c67770f9cebece9c79e914a54c348f539a512Matt Sarett * Last changed in libpng 1.6.24 [August 4, 2016] 57a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * Copyright (c) 1998-2002,2004,2006-2016 Glenn Randers-Pehrson 6893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 7893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 8a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * 9a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * This code is released under the libpng license. 10a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * For conditions of distribution and use, see the disclaimer 11a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * and license in png.h 12893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 13893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 14b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#include "pngpriv.h" 15b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 16893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_WRITE_SUPPORTED 17893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 18b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED 19893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Place a 32-bit number into a buffer in PNG byte order. We work 20893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * with unsigned numbers for convenience, although one supported 21893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * ancillary chunk uses signed (two's complement) numbers. 22893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 23893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 24893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_save_uint_32(png_bytep buf, png_uint_32 i) 25893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 26114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett buf[0] = (png_byte)((i >> 24) & 0xffU); 27114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett buf[1] = (png_byte)((i >> 16) & 0xffU); 28114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett buf[2] = (png_byte)((i >> 8) & 0xffU); 29114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett buf[3] = (png_byte)( i & 0xffU); 30893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 31893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 32893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Place a 16-bit number into a buffer in PNG byte order. 33893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * The parameter is declared unsigned int, not png_uint_16, 34893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * just to avoid potential problems on pre-ANSI C compilers. 35893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 36893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 37893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_save_uint_16(png_bytep buf, unsigned int i) 38893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 39114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett buf[0] = (png_byte)((i >> 8) & 0xffU); 40114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett buf[1] = (png_byte)( i & 0xffU); 41893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 42b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 43893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 444215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project/* Simple function to write the signature. If we have already written 454215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project * the magic bytes of the signature, or more likely, the PNG stream is 464215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project * being embedded into another stream and doesn't need its own signature, 474215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project * we should call png_set_sig_bytes() to tell libpng how many of the 484215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project * bytes have already been written. 494215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project */ 50b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 51b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_sig(png_structrp png_ptr) 524215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project{ 534215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; 544215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project 55b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_IO_STATE_SUPPORTED 56b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Inform the I/O callback that the signature is being written */ 57b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE; 58b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 59b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 60a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write the rest of the 8 byte signature */ 614215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], 627a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis (png_size_t)(8 - png_ptr->sig_bytes)); 63b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 644215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project if (png_ptr->sig_bytes < 3) 654215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; 664215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project} 674215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project 68893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Write the start of a PNG chunk. The type is the chunk type. 69893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * The total_length is the sum of the lengths of all the data you will be 70893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * passing in png_write_chunk_data(). 71893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 72b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 73b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name, 74b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 length) 75893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 764215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_byte buf[8]; 77893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 78b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#if defined(PNG_DEBUG) && (PNG_DEBUG > 0) 79b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_CSTRING_FROM_CHUNK(buf, chunk_name); 80b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length); 81b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 825f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 83a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 84a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 85893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 86b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_IO_STATE_SUPPORTED 87b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Inform the I/O callback that the chunk header is being written. 88b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG_IO_CHUNK_HDR requires a single I/O call. 89b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 90b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR; 91b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 925f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 93a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write the length and the chunk name */ 944215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_save_uint_32(buf, length); 95b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_32(buf + 4, chunk_name); 96b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_data(png_ptr, buf, 8); 97b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 98a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Put the chunk name into png_ptr->chunk_name */ 99b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->chunk_name = chunk_name; 100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 101a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Reset the crc and run it over the chunk name */ 102893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_reset_crc(png_ptr); 103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_calculate_crc(png_ptr, buf + 4, 4); 105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_IO_STATE_SUPPORTED 107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Inform the I/O callback that chunk data will (possibly) be written. 108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls. 109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA; 111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 112893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 113893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 114b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 115b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string, 116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 length) 117b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length); 119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Write the data of a PNG chunk started with png_write_chunk_header(). 122893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * Note that multiple calls to this function are allowed, and that the 123893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * sum of the lengths from these calls *must* add up to the total_length 124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * given to png_write_chunk_header(). 125893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 126893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 127b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_chunk_data(png_structrp png_ptr, png_const_bytep data, 128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t length) 129893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 130a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write the data, and run the CRC over it */ 131a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott if (png_ptr == NULL) 132a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 134893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (data != NULL && length > 0) 135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 136893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_data(png_ptr, data, length); 137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 138a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Update the CRC after writing the data, 1399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * in case the user I/O routine alters it. 1404215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project */ 1414215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_calculate_crc(png_ptr, data, length); 142893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 143893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 144893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Finish a chunk started with png_write_chunk_header(). */ 146893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 147b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_chunk_end(png_structrp png_ptr) 148893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 149893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[4]; 150893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1514215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project if (png_ptr == NULL) return; 152893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_IO_STATE_SUPPORTED 154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Inform the I/O callback that the chunk CRC is being written. 155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG_IO_CHUNK_CRC requires a single I/O function call. 156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC; 158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 160a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write the crc in a single operation */ 161893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_uint_32(buf, png_ptr->crc); 162893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 163893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_data(png_ptr, buf, (png_size_t)4); 164893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 165893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Write a PNG chunk all at once. The type is an array of ASCII characters 167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * representing the chunk name. The array must be at least 4 bytes in 168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * length, and does not need to be null terminated. To be safe, pass the 169b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pre-defined chunk names here, and if you need a new one, define it 170b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * where the others are defined. The length is the length of the data. 171b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * All the data must be present. If that is not possible, use the 172b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() 173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * functions instead. 174893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 175b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 176b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, 1777a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_const_bytep data, png_size_t length) 178893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 179b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr == NULL) 180b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* On 64-bit architectures 'length' may not fit in a png_uint_32. */ 183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (length > PNG_UINT_31_MAX) 1849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_error(png_ptr, "length exceeds PNG maximum"); 185b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length); 187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, data, length); 188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_end(png_ptr); 189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 191b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* This is the API that calls the internal function above. */ 192b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 193b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string, 1947a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_const_bytep data, png_size_t length) 195893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data, 1977a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis length); 198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 199893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* This is used below to find the size of an image to pass to png_deflate_claim, 201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * so it only needs to be accurate if the size is less than 16384 bytes (the 202b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * point at which a lower LZ window size can be used.) 203b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 204b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_alloc_size_t 205b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_size(png_structrp png_ptr) 206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Only return sizes up to the maximum of a png_uint_32; do this by limiting 208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the width and height used to 15 bits. 209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 h = png_ptr->height; 211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->rowbytes < 32768 && h < 32768) 213893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->interlaced != 0) 215b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Interlacing makes the image larger because of the replication of 217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * both the filter byte and the padding to a byte boundary. 218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 w = png_ptr->width; 220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int pd = png_ptr->pixel_depth; 221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_alloc_size_t cb_base; 222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int pass; 223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 224b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (cb_base=0, pass=0; pass<=6; ++pass) 225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 226b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 pw = PNG_PASS_COLS(w, pass); 227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (pw > 0) 229b50c217251b086440efcdb273c22f86a06c80cbaChris Craik cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass); 230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return cb_base; 233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_ptr->rowbytes+1) * h; 237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 238893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0xffffffffU; 241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED 244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is the code to hack the first two bytes of the deflate stream (the 245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * deflate header) to correct the windowBits value to match the actual data 246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * size. Note that the second argument is the *uncompressed* size but the 247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * first argument is the *compressed* data (and it must be deflate 248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * compressed.) 249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 250b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 251b50c217251b086440efcdb273c22f86a06c80cbaChris Craikoptimize_cmf(png_bytep data, png_alloc_size_t data_size) 252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Optimize the CMF field in the zlib stream. The resultant zlib stream is 254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * still compliant to the stream specification. 255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (data_size <= 16384) /* else windowBits must be 15 */ 257893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int z_cmf = data[0]; /* zlib compression method and flags */ 259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) 261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int z_cinfo; 263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int half_z_window_size; 264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik z_cinfo = z_cmf >> 4; 266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik half_z_window_size = 1U << (z_cinfo + 7); 267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 268b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (data_size <= half_z_window_size) /* else no change */ 269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int tmp; 271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do 273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik half_z_window_size >>= 1; 275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik --z_cinfo; 276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (z_cinfo > 0 && data_size <= half_z_window_size); 278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); 280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik data[0] = (png_byte)z_cmf; 282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tmp = data[1] & 0xe0; 283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f; 284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik data[1] = (png_byte)tmp; 285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 287893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_OPTIMIZE_CMF */ 290893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Initialize the compressor for the appropriate type of compression. */ 292b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 293b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_deflate_claim(png_structrp png_ptr, png_uint_32 owner, 2947a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_alloc_size_t data_size) 295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->zowner != 0) 297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2989b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED) 299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik char msg[64]; 300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_STRING_FROM_CHUNK(msg, owner); 302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik msg[4] = ':'; 303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik msg[5] = ' '; 304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner); 305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* So the message that results is "<chunk> using zstream"; this is an 306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * internal error, but is very useful for debugging. i18n requirements 307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * are minimal. 308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)png_safecat(msg, (sizeof msg), 10, " using zstream"); 3109b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 3119b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#if PNG_RELEASE_BUILD 312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, msg); 313893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Attempt sane error recovery */ 315b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */ 316b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT"); 318b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return Z_STREAM_ERROR; 319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zowner = 0; 3229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#else 323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, msg); 3249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 326893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 327893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int level = png_ptr->zlib_level; 329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int method = png_ptr->zlib_method; 330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int windowBits = png_ptr->zlib_window_bits; 331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int memLevel = png_ptr->zlib_mem_level; 332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int strategy; /* set below */ 333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int ret; /* zlib return code */ 334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (owner == png_IDAT) 336893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 3379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) != 0) 338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik strategy = png_ptr->zlib_strategy; 339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (png_ptr->do_filter != PNG_FILTER_NONE) 341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik strategy = PNG_Z_DEFAULT_STRATEGY; 342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 343893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY; 345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 348893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 3499b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED 350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik level = png_ptr->zlib_text_level; 351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik method = png_ptr->zlib_text_method; 352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik windowBits = png_ptr->zlib_text_window_bits; 353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memLevel = png_ptr->zlib_text_mem_level; 354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik strategy = png_ptr->zlib_text_strategy; 3559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#else 356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If customization is not supported the values all come from the 357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * IDAT values except for the strategy, which is fixed to the 358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * default. (This is the pre-1.6.0 behavior too, although it was 359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * implemented in a very different way.) 360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik strategy = Z_DEFAULT_STRATEGY; 3629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Adjust 'windowBits' down if larger than 'data_size'; to stop this 366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * happening just pass 32768 as the data_size parameter. Notice that zlib 367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * requires an extra 262 bytes in the window in addition to the data to be 368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * able to see the whole of the data, so if data_size+262 takes us to the 369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * next windowBits size we need to fix up the value later. (Because even 370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * though deflate needs the extra window, inflate does not!) 371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (data_size <= 16384) 373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to 375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * work round a Microsoft Visual C misbehavior which, contrary to C-90, 376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * widens the result of the following shift to 64-bits if (and, 377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * apparently, only if) it is used in a test. 378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik unsigned int half_window_size = 1U << (windowBits-1); 380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 381b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (data_size + 262 <= half_window_size) 382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 383b50c217251b086440efcdb273c22f86a06c80cbaChris Craik half_window_size >>= 1; 384b50c217251b086440efcdb273c22f86a06c80cbaChris Craik --windowBits; 385893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 386b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 387893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 388b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check against the previous initialized values, if any. */ 3899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0 && 390b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_ptr->zlib_set_level != level || 391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_set_method != method || 392b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_set_window_bits != windowBits || 393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_set_mem_level != memLevel || 394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_set_strategy != strategy)) 395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (deflateEnd(&png_ptr->zstream) != Z_OK) 397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "deflateEnd failed (ignored)"); 398893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 399b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED; 400893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 401893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 402b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* For safety clear out the input and output pointers (currently zlib 403b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * doesn't use them on Init, but it might in the future). 404b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 405b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.next_in = NULL; 406b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_in = 0; 407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.next_out = NULL; 408b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_out = 0; 409893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 410b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now initialize if required, setting the new parameters, otherwise just 411851c67770f9cebece9c79e914a54c348f539a512Matt Sarett * to a simple reset to the previous parameters. 412b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 4139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0) 414b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ret = deflateReset(&png_ptr->zstream); 415b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 416b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 417b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 418b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ret = deflateInit2(&png_ptr->zstream, level, method, windowBits, 4197a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis memLevel, strategy); 420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 421b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ret == Z_OK) 422b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED; 423b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The return code is from either deflateReset or deflateInit2; they have 426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pretty much the same set of error codes. 427b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 428893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (ret == Z_OK) 429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zowner = owner; 430b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 431b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 432b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_zstream_error(png_ptr, ret); 433b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return ret; 435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 438b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Clean up (or trim) a linked list of compression buffers. */ 439b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 440b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp) 441b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 442b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_compression_bufferp list = *listp; 443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 444b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (list != NULL) 445b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 446b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *listp = NULL; 447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 448b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do 449893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_compression_bufferp next = list->next; 451b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, list); 453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik list = next; 454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (list != NULL); 456b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED 460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* This pair of functions encapsulates the operation of (a) compressing a 461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * text string, and (b) issuing it later as a series of chunk data writes. 462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The compression_state structure is shared context for these functions 463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * set up by the caller to allow access to the relevant local variables. 464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size 466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * temporary buffers. From 1.6.0 it is retained in png_struct so that it will 467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be correctly freed in the event of a write error (previous implementations 468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * just leaked memory.) 469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 470b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef struct 471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep input; /* The uncompressed input data */ 473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_alloc_size_t input_len; /* Its length */ 474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 output_len; /* Final compressed length */ 475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte output[1024]; /* First block of output */ 476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} compression_state; 477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 478b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 479b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_text_compress_init(compression_state *comp, png_const_bytep input, 4807a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_alloc_size_t input_len) 481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik comp->input = input; 483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik comp->input_len = input_len; 484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik comp->output_len = 0; 485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Compress the data in the compression state input */ 488b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 489b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_text_compress(png_structrp png_ptr, png_uint_32 chunk_name, 4907a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis compression_state *comp, png_uint_32 prefix_len) 491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int ret; 493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* To find the length of the output it is necessary to first compress the 4959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * input. The result is buffered rather than using the two-pass algorithm 496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * that is used on the inflate side; deflate is assumed to be slower and a 497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * PNG writer is assumed to have more memory available than a PNG reader. 498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an 500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * upper limit on the output size, but it is always bigger than the input 501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * size so it is likely to be more efficient to use this linked-list 502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * approach. 503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len); 505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ret != Z_OK) 507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return ret; 508b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Set up the compression buffers, we need a loop here to avoid overflowing a 510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited 511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * by the output buffer size, so there is no need to check that. Since this 512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits 513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * in size. 514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_compression_bufferp *end = &png_ptr->zbuffer_list; 517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_alloc_size_t input_len = comp->input_len; /* may be zero! */ 518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 output_len; 519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* zlib updates these for us: */ 521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input); 522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_in = 0; /* Set below */ 523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.next_out = comp->output; 524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_out = (sizeof comp->output); 525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_len = png_ptr->zstream.avail_out; 527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do 529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik uInt avail_in = ZLIB_IO_MAX; 531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (avail_in > input_len) 533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik avail_in = (uInt)input_len; 534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik input_len -= avail_in; 536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_in = avail_in; 538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->zstream.avail_out == 0) 540893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 541b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_compression_buffer *next; 542b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 543b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Chunk data is limited to 2^31 bytes in length, so the prefix 544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * length must be counted here. 545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (output_len + prefix_len > PNG_UINT_31_MAX) 547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ret = Z_MEM_ERROR; 549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Need a new (malloc'ed) buffer, but there may be one present 553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * already. 554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik next = *end; 556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (next == NULL) 557893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik next = png_voidcast(png_compression_bufferp, png_malloc_base 559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); 560893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (next == NULL) 562893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ret = Z_MEM_ERROR; 564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 565893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Link in this buffer (so that it will be freed later) */ 568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik next->next = NULL; 569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *end = next; 570893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 571893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.next_out = next->output; 573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_out = png_ptr->zbuffer_size; 574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_len += png_ptr->zstream.avail_out; 575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Move 'end' to the next buffer pointer. */ 577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik end = &next->next; 578893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Compress the data */ 581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ret = deflate(&png_ptr->zstream, 5827a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis input_len > 0 ? Z_NO_FLUSH : Z_FINISH); 583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Claw back input data that was not consumed (because avail_in is 585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * reset above every time round the loop). 586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik input_len += png_ptr->zstream.avail_in; 588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_in = 0; /* safety */ 589893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (ret == Z_OK); 591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 5929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* There may be some space left in the last output buffer. This needs to 593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be subtracted from output_len. 594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_len -= png_ptr->zstream.avail_out; 596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_out = 0; /* safety */ 597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik comp->output_len = output_len; 598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now double check the output length, put in a custom message if it is 600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * too long. Otherwise ensure the z_stream::msg pointer is set to 601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * something. 602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (output_len + prefix_len >= PNG_UINT_31_MAX) 604893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long"); 606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ret = Z_MEM_ERROR; 607893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 608893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_zstream_error(png_ptr, ret); 611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Reset zlib for another zTXt/iTXt or image data */ 613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zowner = 0; 614893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 6159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* The only success case is Z_STREAM_END, input_len must be 0; if not this 616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is an internal error. 617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ret == Z_STREAM_END && input_len == 0) 619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 6209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED 621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Fix up the deflate header, if required */ 622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik optimize_cmf(comp->output, comp->input_len); 6239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* But Z_OK is returned, not Z_STREAM_END; this allows the claim 625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * function above to return Z_STREAM_END on an error (though it never 626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * does in the current versions of zlib.) 627b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return Z_OK; 629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return ret; 633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 634893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 635893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 636a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Ship the compressed text out via chunk writes */ 637b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 638b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_compressed_data_out(png_structrp png_ptr, compression_state *comp) 639893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 output_len = comp->output_len; 641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep output = comp->output; 642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 avail = (sizeof comp->output); 643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_compression_buffer *next = png_ptr->zbuffer_list; 644893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (;;) 646893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (avail > output_len) 648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik avail = output_len; 649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, output, avail); 651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output_len -= avail; 653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (output_len == 0 || next == NULL) 655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik avail = png_ptr->zbuffer_size; 658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik output = next->output; 659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik next = next->next; 660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is an internal error; 'next' must have been NULL! */ 663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (output_len > 0) 664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "error writing ancillary chunked compressed data"); 665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 6669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_COMPRESSED_TEXT */ 667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 668893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Write the IHDR chunk, and update the png_struct with the necessary 669893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * information. Note that the rest of this code depends upon this 670893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * information being correct. 671893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 672893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 673b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height, 674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int bit_depth, int color_type, int compression_type, int filter_type, 675b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int interlace_type) 676893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 677a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_byte buf[13]; /* Buffer to store the IHDR info */ 678893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 6794215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_IHDR"); 6805f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 681893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Check that we have valid input data from the application info */ 682893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project switch (color_type) 683893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 684893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case PNG_COLOR_TYPE_GRAY: 685893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project switch (bit_depth) 686893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 687893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 1: 688893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 2: 689893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 4: 690893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 8: 691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_16BIT_SUPPORTED 692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 16: 693b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 694b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->channels = 1; break; 695b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 696b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 697b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, 698b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "Invalid bit depth for grayscale image"); 699893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 700893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 701b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 702893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case PNG_COLOR_TYPE_RGB: 703b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_16BIT_SUPPORTED 704893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (bit_depth != 8 && bit_depth != 16) 705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else 706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (bit_depth != 8) 707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 708893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_error(png_ptr, "Invalid bit depth for RGB image"); 709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 710893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->channels = 3; 711893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 713893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case PNG_COLOR_TYPE_PALETTE: 714893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project switch (bit_depth) 715893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 716893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 1: 717893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 2: 718893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 4: 719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 8: 720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->channels = 1; 721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "Invalid bit depth for paletted image"); 725893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 726893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 728893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case PNG_COLOR_TYPE_GRAY_ALPHA: 729893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (bit_depth != 8 && bit_depth != 16) 730893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); 731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 732893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->channels = 2; 733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 735893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case PNG_COLOR_TYPE_RGB_ALPHA: 736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_16BIT_SUPPORTED 737893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (bit_depth != 8 && bit_depth != 16) 738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else 739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (bit_depth != 8) 740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 741893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_error(png_ptr, "Invalid bit depth for RGBA image"); 742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 743893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->channels = 4; 744893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 746893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project default: 747893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_error(png_ptr, "Invalid image color type specified"); 748893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 749893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 750893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (compression_type != PNG_COMPRESSION_TYPE_BASE) 751893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 752893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Invalid compression type specified"); 753893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project compression_type = PNG_COMPRESSION_TYPE_BASE; 754893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 755893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 756893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Write filter_method 64 (intrapixel differencing) only if 757893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and 758893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 2. Libpng did not write a PNG signature (this filter_method is only 759893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * used in PNG datastreams that are embedded in MNG datastreams) and 760893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 3. The application called png_permit_mng_features with a mask that 761893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * included PNG_FLAG_MNG_FILTER_64 and 762893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 4. The filter_method is 64 and 763893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 5. The color_type is RGB or RGBA 764893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 765893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ( 7665f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_MNG_FEATURES_SUPPORTED 7679b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 && 7689b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) && 769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (color_type == PNG_COLOR_TYPE_RGB || 770b50c217251b086440efcdb273c22f86a06c80cbaChris Craik color_type == PNG_COLOR_TYPE_RGB_ALPHA) && 771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && 772893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik filter_type != PNG_FILTER_TYPE_BASE) 774893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 775893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Invalid filter type specified"); 776893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project filter_type = PNG_FILTER_TYPE_BASE; 777893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 778893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 779893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_WRITE_INTERLACING_SUPPORTED 780893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (interlace_type != PNG_INTERLACE_NONE && 781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik interlace_type != PNG_INTERLACE_ADAM7) 782893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 783893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Invalid interlace type specified"); 784893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project interlace_type = PNG_INTERLACE_ADAM7; 785893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 786893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 787893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project interlace_type=PNG_INTERLACE_NONE; 788893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 789893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 7909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Save the relevant information */ 791893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->bit_depth = (png_byte)bit_depth; 792893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->color_type = (png_byte)color_type; 793893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->interlaced = (png_byte)interlace_type; 7945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_MNG_FEATURES_SUPPORTED 795893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->filter_type = (png_byte)filter_type; 796893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 797893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->compression_type = (png_byte)compression_type; 798893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->width = width; 799893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->height = height; 800893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 801893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); 802893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); 803a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Set the usr info, so any transformations can modify it */ 804893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->usr_width = png_ptr->width; 805893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->usr_bit_depth = png_ptr->bit_depth; 806893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->usr_channels = png_ptr->channels; 807893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 808a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Pack the header information into the buffer */ 809893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_uint_32(buf, width); 810893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_uint_32(buf + 4, height); 811893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[8] = (png_byte)bit_depth; 812893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[9] = (png_byte)color_type; 813893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[10] = (png_byte)compression_type; 814893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[11] = (png_byte)filter_type; 815893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[12] = (png_byte)interlace_type; 816893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 817a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write the chunk */ 818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13); 819893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 8209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->do_filter) == PNG_NO_FILTERS) 821893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 822893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || 823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->bit_depth < 8) 824893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->do_filter = PNG_FILTER_NONE; 825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 826893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 827893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->do_filter = PNG_ALL_FILTERS; 828893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */ 831893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 832893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 833a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write the palette. We are careful not to trust png_color to be in the 834893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * correct order for PNG, so people can redefine it to any convenient 835893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * structure. 836893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 837893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 838b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_PLTE(png_structrp png_ptr, png_const_colorp palette, 839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 num_pal) 840893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 8419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_uint_32 max_palette_length, i; 842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_colorp pal_ptr; 843893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[3]; 844893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 8454215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_PLTE"); 8465f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 8479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? 8489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; 8499b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 850893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (( 8515f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_MNG_FEATURES_SUPPORTED 8529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 && 853893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 8549b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett num_pal == 0) || num_pal > max_palette_length) 855893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 856b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "Invalid number of colors in palette"); 859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 860b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Invalid number of colors in palette"); 864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 865b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 866893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 867893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 8689b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) 869893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 870893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, 871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "Ignoring request to write a PLTE chunk in grayscale PNG"); 872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 873893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 874893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 875893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 876893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->num_palette = (png_uint_16)num_pal; 8774215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug1(3, "num_palette = %d", png_ptr->num_palette); 878893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3)); 8805f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_POINTER_INDEXING_SUPPORTED 881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 882893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) 883893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 884893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[0] = pal_ptr->red; 885893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[1] = pal_ptr->green; 886893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[2] = pal_ptr->blue; 887893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_chunk_data(png_ptr, buf, (png_size_t)3); 888893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 889b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 890893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 8915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott /* This is a little slower but some buggy compilers need to do this 8925f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott * instead 8935f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott */ 894893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project pal_ptr=palette; 895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 896893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0; i < num_pal; i++) 897893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 898893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[0] = pal_ptr[i].red; 899893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[1] = pal_ptr[i].green; 900893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[2] = pal_ptr[i].blue; 901893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_chunk_data(png_ptr, buf, (png_size_t)3); 902893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 904893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 905893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_chunk_end(png_ptr); 906893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->mode |= PNG_HAVE_PLTE; 907893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 908893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* This is similar to png_text_compress, above, except that it does not require 910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * all of the data at once and, instead of buffering the compressed result, 911b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out 912b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * because it calls the write interface. As a result it does its own error 913b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * reporting and does not return an error code. In the event of error it will 914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * just call png_error. The input data length may exceed 32-bits. The 'flush' 915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * parameter is exactly the same as that to deflate, with the following 916b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * meanings: 917b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Z_NO_FLUSH: normal incremental output of compressed data 919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush 920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up 921b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The routine manages the acquire and release of the png_ptr->zstream by 9239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * checking and (at the end) clearing png_ptr->zowner; it does some sanity 924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * checks on the 'mode' flags while doing this. 925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 926893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 927b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_compress_IDAT(png_structrp png_ptr, png_const_bytep input, 9287a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_alloc_size_t input_len, int flush) 929893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->zowner != png_IDAT) 931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 932b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* First time. Ensure we have a temporary buffer for compression and 933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * trim the buffer list if it has more than one entry to free memory. 934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been 935b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * created at this point, but the check here is quick and safe. 936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->zbuffer_list == NULL) 938b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 939b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp, 9407a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr))); 941b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zbuffer_list->next = NULL; 942b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 9435f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 944b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 945b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next); 946b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 947b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* It is a terminal error if we can't claim the zstream. */ 948b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK) 949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, png_ptr->zstream.msg); 950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 951b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The output state is maintained in png_ptr->zstream, so it must be 952b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * initialized here after the claim. 953b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.next_out = png_ptr->zbuffer_list->output; 955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_out = png_ptr->zbuffer_size; 956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 957893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now loop reading and writing until all the input is consumed or an error 959b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * terminates the operation. The _out values are maintained across calls to 960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this function, but the input must be reset each time. 961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input); 963b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_in = 0; /* set below */ 964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (;;) 965893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int ret; 967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 968b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* INPUT: from the row data */ 969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik uInt avail = ZLIB_IO_MAX; 970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 971b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (avail > input_len) 972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik avail = (uInt)input_len; /* safe because of the check */ 973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_in = avail; 975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik input_len -= avail; 976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush); 978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Include as-yet unconsumed input */ 980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik input_len += png_ptr->zstream.avail_in; 981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_in = 0; 982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* OUTPUT: write complete IDAT chunks when avail_out drops to zero. Note 984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * that these two zstream fields are preserved across the calls, therefore 985b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * there is no need to set these up on entry to the loop. 986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->zstream.avail_out == 0) 988b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep data = png_ptr->zbuffer_list->output; 990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik uInt size = png_ptr->zbuffer_size; 991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 992b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Write an IDAT containing the data then reset the buffer. The 993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * first IDAT may need deflate header optimization. 994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 9959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED 9969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 && 9979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) 998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik optimize_cmf(data, png_image_size(png_ptr)); 9999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 1000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_IDAT, data, size); 1002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->mode |= PNG_HAVE_IDAT; 1003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.next_out = data; 1005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_out = size; 1006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with 1008b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the same flush parameter until it has finished output, for NO_FLUSH 1009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it doesn't matter. 1010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ret == Z_OK && flush != Z_NO_FLUSH) 1012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik continue; 1013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* The order of these checks doesn't matter much; it just affects which 1016b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * possible error might be detected if multiple things go wrong at once. 1017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (ret == Z_OK) /* most likely return code! */ 1019893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If all the input has been consumed then just return. If Z_FINISH 1021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * was used as the flush parameter something has gone wrong if we get 1022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * here. 1023a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott */ 1024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (input_len == 0) 1025893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (flush == Z_FINISH) 1027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "Z_OK on Z_FINISH with output space"); 1028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1030893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1031893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (ret == Z_STREAM_END && flush == Z_FINISH) 1034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is the end of the IDAT data; any pending output must be 1036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * flushed. For small PNG files we may still be at the beginning. 1037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1038b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep data = png_ptr->zbuffer_list->output; 1039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out; 1040b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED 10429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 && 10439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) 10449b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett optimize_cmf(data, png_image_size(png_ptr)); 10459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 1046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_IDAT, data, size); 1048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.avail_out = 0; 1049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zstream.next_out = NULL; 1050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT; 1051b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zowner = 0; /* Release the stream */ 1053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1055b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1056893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 1057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1058b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is an error condition. */ 1059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_zstream_error(png_ptr, ret); 1060b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, png_ptr->zstream.msg); 1061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1062893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1063893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1064893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1065a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write an IEND chunk */ 1066893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1067b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_IEND(png_structrp png_ptr) 1068893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 10694215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_IEND"); 10705f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0); 1072893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->mode |= PNG_HAVE_IEND; 1073893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1074893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10755f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_gAMA_SUPPORTED 1076a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write a gAMA chunk */ 1077893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1078b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma) 1079893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1080893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[4]; 1081893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10824215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_gAMA"); 10835f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1084893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* file_gamma is saved in 1/100,000ths */ 1085893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_uint_32(buf, (png_uint_32)file_gamma); 1086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4); 1087893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1088893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1089893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10905f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_sRGB_SUPPORTED 1091a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write a sRGB chunk */ 1092893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1093b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_sRGB(png_structrp png_ptr, int srgb_intent) 1094893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1095893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[1]; 1096893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10974215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_sRGB"); 10985f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 10994215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project if (srgb_intent >= PNG_sRGB_INTENT_LAST) 1100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, 1101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "Invalid sRGB rendering intent specified"); 1102b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1103893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[0]=(png_byte)srgb_intent; 1104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1); 1105893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1107893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 11085f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_iCCP_SUPPORTED 1109a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write an iCCP chunk */ 1110893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1111b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_iCCP(png_structrp png_ptr, png_const_charp name, 1112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep profile) 1113893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 name_len; 1115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 profile_len; 1116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte new_name[81]; /* 1 byte for the compression byte */ 1117893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project compression_state comp; 11189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_uint_32 temp; 1119893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 11204215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_iCCP"); 1121893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* These are all internal problems: the profile should have been checked 1123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * before when it was stored. 1124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (profile == NULL) 1126b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */ 1127893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik profile_len = png_get_uint_32(profile); 1129893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (profile_len < 132) 1131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "ICC profile too short"); 1132893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 11339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett temp = (png_uint_32) (*(profile+8)); 11349b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (temp > 3 && (profile_len & 0x03)) 1135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)"); 1136893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 11375f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 1138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 embedded_profile_len = png_get_uint_32(profile); 11395f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (profile_len != embedded_profile_len) 1141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "Profile length does not match profile"); 11424215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project } 1143893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik name_len = png_check_keyword(png_ptr, name, new_name); 1145893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (name_len == 0) 1147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "iCCP: invalid keyword"); 1148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE; 1150893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1151a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Make sure we include the NULL after the name and the compression type */ 1152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++name_len; 1153893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1154b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_text_compress_init(&comp, profile, profile_len); 1155b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1156b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Allow for keyword terminator and compression byte */ 1157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK) 1158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, png_ptr->zstream.msg); 1159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len); 1161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, new_name, name_len); 1163b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_compressed_data_out(png_ptr, &comp); 1165893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1166893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_chunk_end(png_ptr); 1167893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1168893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1169893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 11705f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_sPLT_SUPPORTED 1171a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write a sPLT chunk */ 1172893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1173b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette) 1174893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 name_len; 1176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte new_name[80]; 1177893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte entrybuf[10]; 1178b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t entry_size = (spalette->depth == 8 ? 6 : 10); 1179851c67770f9cebece9c79e914a54c348f539a512Matt Sarett png_size_t palette_size = entry_size * spalette->nentries; 1180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_sPLT_entryp ep; 11815f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifndef PNG_POINTER_INDEXING_SUPPORTED 1182893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int i; 1183893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1184893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 11854215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_sPLT"); 11865f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1187b50c217251b086440efcdb273c22f86a06c80cbaChris Craik name_len = png_check_keyword(png_ptr, spalette->name, new_name); 1188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1189b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (name_len == 0) 1190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "sPLT: invalid keyword"); 1191893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1192a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Make sure we include the NULL after the name */ 1193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_header(png_ptr, png_sPLT, 1194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_uint_32)(name_len + 2 + palette_size)); 1195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 11964215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_write_chunk_data(png_ptr, (png_bytep)new_name, 1197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_size_t)(name_len + 1)); 1198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1199b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1); 1200893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1201a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Loop through each palette entry, writing appropriately */ 12025f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_POINTER_INDEXING_SUPPORTED 12034215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++) 12044215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project { 12054215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project if (spalette->depth == 8) 12064215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project { 1207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entrybuf[0] = (png_byte)ep->red; 1208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entrybuf[1] = (png_byte)ep->green; 1209b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entrybuf[2] = (png_byte)ep->blue; 1210b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entrybuf[3] = (png_byte)ep->alpha; 1211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 4, ep->frequency); 12124215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project } 1213b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 12144215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project else 12154215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project { 1216b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 0, ep->red); 1217b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 2, ep->green); 1218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 4, ep->blue); 1219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 6, ep->alpha); 1220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 8, ep->frequency); 12214215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project } 1222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1223b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, entrybuf, entry_size); 1224893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1225893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 1226893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project ep=spalette->entries; 1227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i = 0; i>spalette->nentries; i++) 1228893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 12294215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project if (spalette->depth == 8) 12304215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project { 1231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entrybuf[0] = (png_byte)ep[i].red; 1232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entrybuf[1] = (png_byte)ep[i].green; 1233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entrybuf[2] = (png_byte)ep[i].blue; 1234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entrybuf[3] = (png_byte)ep[i].alpha; 1235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 4, ep[i].frequency); 12364215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project } 1237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 12384215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project else 12394215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project { 1240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 0, ep[i].red); 1241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 2, ep[i].green); 1242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 4, ep[i].blue); 1243b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 6, ep[i].alpha); 1244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(entrybuf + 8, ep[i].frequency); 12454215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project } 1246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, entrybuf, entry_size); 1248893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1249893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1250893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1251893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_chunk_end(png_ptr); 1252893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1254893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 12555f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_sBIT_SUPPORTED 1256a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write the sBIT chunk */ 1257893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1258b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type) 1259893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1260893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[4]; 1261893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_size_t size; 1262893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 12634215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_sBIT"); 12645f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1265a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Make sure we don't depend upon the order of PNG_COLOR_8 */ 12669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((color_type & PNG_COLOR_MASK_COLOR) != 0) 1267893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1268893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte maxbits; 1269893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1270893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : 1271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->usr_bit_depth); 1272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1273893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (sbit->red == 0 || sbit->red > maxbits || 1274893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project sbit->green == 0 || sbit->green > maxbits || 1275893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project sbit->blue == 0 || sbit->blue > maxbits) 1276893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1277893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Invalid sBIT depth specified"); 1278893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1279893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1281893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[0] = sbit->red; 1282893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[1] = sbit->green; 1283893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[2] = sbit->blue; 1284893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project size = 3; 1285893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1287893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 1288893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1289893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) 1290893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1291893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Invalid sBIT depth specified"); 1292893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1293893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1295893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[0] = sbit->gray; 1296893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project size = 1; 1297893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1298893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 12999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((color_type & PNG_COLOR_MASK_ALPHA) != 0) 1300893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1301893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) 1302893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1303893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Invalid sBIT depth specified"); 1304893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1305893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1307893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[size++] = sbit->alpha; 1308893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1309893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_sBIT, buf, size); 1311893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1312893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1313893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 13145f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_cHRM_SUPPORTED 1315a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write the cHRM chunk */ 1316893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1317b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy) 1318893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1319893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[32]; 1320893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 13214215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_cHRM"); 13225f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1323a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Each value is saved in 1/100,000ths */ 1324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_int_32(buf, xy->whitex); 1325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_int_32(buf + 4, xy->whitey); 1326893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_int_32(buf + 8, xy->redx); 1328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_int_32(buf + 12, xy->redy); 1329893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_int_32(buf + 16, xy->greenx); 1331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_int_32(buf + 20, xy->greeny); 1332893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_int_32(buf + 24, xy->bluex); 1334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_int_32(buf + 28, xy->bluey); 1335893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_cHRM, buf, 32); 1337893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1338893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1339893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 13405f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_tRNS_SUPPORTED 1341a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write the tRNS chunk */ 1342893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1343b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, 1344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_color_16p tran, int num_trans, int color_type) 1345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[6]; 1347893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 13484215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_tRNS"); 13495f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1350893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (color_type == PNG_COLOR_TYPE_PALETTE) 1351893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1352893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) 1353893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_app_warning(png_ptr, 1355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "Invalid number of transparent colors specified"); 1356893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1357893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1359a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write the chunk out as it is */ 1360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, 13617a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis (png_size_t)num_trans); 1362893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1364893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else if (color_type == PNG_COLOR_TYPE_GRAY) 1365893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 13669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* One 16-bit value */ 13674215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project if (tran->gray >= (1 << png_ptr->bit_depth)) 1368893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_app_warning(png_ptr, 1370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); 1371b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1372893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1373893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1375893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_uint_16(buf, tran->gray); 1376b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2); 1377893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1379893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else if (color_type == PNG_COLOR_TYPE_RGB) 1380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 13819b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Three 16-bit values */ 1382893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_uint_16(buf, tran->red); 1383893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_uint_16(buf + 2, tran->green); 1384893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_uint_16(buf + 4, tran->blue); 1385b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_16BIT_SUPPORTED 13869b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0) 1387b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else 13889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((buf[0] | buf[2] | buf[4]) != 0) 1389b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 13904215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project { 1391b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_app_warning(png_ptr, 13927a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); 13934215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project return; 13944215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project } 1395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6); 1397893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1398b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1399893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 1400893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1401b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_app_warning(png_ptr, "Can't write tRNS with an alpha channel"); 1402893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1403893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1404893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1405893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 14065f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_bKGD_SUPPORTED 1407a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write the background chunk */ 1408893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1409b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type) 1410893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1411893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[6]; 1412893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 14134215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_bKGD"); 14145f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1415893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (color_type == PNG_COLOR_TYPE_PALETTE) 1416893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1417893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ( 14185f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_MNG_FEATURES_SUPPORTED 14199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (png_ptr->num_palette != 0 || 14209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) && 1421893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 14224215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project back->index >= png_ptr->num_palette) 1423893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1424b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Invalid background palette index"); 1425b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1427893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1428b50c217251b086440efcdb273c22f86a06c80cbaChris Craik buf[0] = back->index; 1429b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1); 1430893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1431893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 14329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else if ((color_type & PNG_COLOR_MASK_COLOR) != 0) 1433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1434b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(buf, back->red); 1435b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(buf + 2, back->green); 1436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(buf + 4, back->blue); 1437b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_16BIT_SUPPORTED 14389b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0) 1439893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 14409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((buf[0] | buf[2] | buf[4]) != 0) 1441893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1442893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1443b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, 14447a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "Ignoring attempt to write 16-bit bKGD chunk " 14457a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "when bit_depth is 8"); 1446893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1447b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1448893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1450b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6); 1451893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1452893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1454893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (back->gray >= (1 << png_ptr->bit_depth)) 1456893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1457b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, 1458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); 1459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1460b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1461893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(buf, back->gray); 1464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2); 1465893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 1468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1469b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_hIST_SUPPORTED 1470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Write the histogram */ 1471b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid /* PRIVATE */ 1472b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist) 1473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i; 1475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte buf[3]; 1476893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug(1, "in png_write_hIST"); 1478893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (num_hist > (int)png_ptr->num_palette) 1480893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, 1482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->num_palette); 1483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Invalid number of histogram entries specified"); 1485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1486893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1487893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2)); 1489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i = 0; i < num_hist; i++) 1491893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_save_uint_16(buf, hist[i]); 1493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, buf, (png_size_t)2); 1494893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1495893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_end(png_ptr); 1497893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1498893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1499893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 15005f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_tEXt_SUPPORTED 1501a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write a tEXt chunk */ 1502893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1503b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, 1504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t text_len) 1505893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1506b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 key_len; 1507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte new_key[80]; 1508893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 15094215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_tEXt"); 15105f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik key_len = png_check_keyword(png_ptr, key, new_key); 1512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (key_len == 0) 1514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "tEXt: invalid keyword"); 1515893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1516893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (text == NULL || *text == '\0') 1517893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project text_len = 0; 1518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1519893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 1520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik text_len = strlen(text); 1521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (text_len > PNG_UINT_31_MAX - (key_len+1)) 1523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "tEXt: text too long"); 1524893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1525a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Make sure we include the 0 after the key */ 1526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_header(png_ptr, png_tEXt, 1527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_uint_32)/*checked above*/(key_len + text_len + 1)); 1528893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* 1529893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * We leave it to the application to meet PNG-1.0 requirements on the 1530893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of 1531893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. 1532893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. 1533893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, new_key, key_len + 1); 1535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 15369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (text_len != 0) 1537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len); 1538893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1539893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_chunk_end(png_ptr); 1540893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1541893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1542893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 15435f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_zTXt_SUPPORTED 1544a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write a compressed text chunk */ 1545893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1546b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text, 15479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int compression) 1548893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 key_len; 1550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte new_key[81]; 1551893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project compression_state comp; 1552893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 15534215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_zTXt"); 1554893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (compression == PNG_TEXT_COMPRESSION_NONE) 1556893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_tEXt(png_ptr, key, text, 0); 1558893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1559893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1560893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (compression != PNG_TEXT_COMPRESSION_zTXt) 1562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "zTXt: invalid compression type"); 1563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik key_len = png_check_keyword(png_ptr, key, new_key); 1565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (key_len == 0) 1567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "zTXt: invalid keyword"); 1568893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Add the compression method and 1 for the keyword separator. */ 1570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; 1571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++key_len; 1572893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1573a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Compute the compressed data; do it now for the length */ 1574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_text_compress_init(&comp, (png_const_bytep)text, 15757a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis text == NULL ? 0 : strlen(text)); 1576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK) 1578b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, png_ptr->zstream.msg); 1579893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1580a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write start of chunk */ 1581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len); 1582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1583a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write key */ 1584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, new_key, key_len); 1585893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1586a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write the compressed data */ 1587893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_compressed_data_out(png_ptr, &comp); 1588893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1589a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Close the chunk */ 1590893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_chunk_end(png_ptr); 1591893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1592893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1593893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 15945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_iTXt_SUPPORTED 1595a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write an iTXt chunk */ 1596893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1597b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key, 1598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_charp lang, png_const_charp lang_key, png_const_charp text) 1599893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 key_len, prefix_len; 1601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t lang_len, lang_key_len; 1602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte new_key[82]; 1603893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project compression_state comp; 1604893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 16054215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_iTXt"); 1606893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik key_len = png_check_keyword(png_ptr, key, new_key); 1608893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (key_len == 0) 1610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "iTXt: invalid keyword"); 16114215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project 1612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Set the compression flag */ 1613b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (compression) 1614893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_ITXT_COMPRESSION_NONE: 1616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_TEXT_COMPRESSION_NONE: 1617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik compression = new_key[++key_len] = 0; /* no compression */ 1618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_TEXT_COMPRESSION_zTXt: 1621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case PNG_ITXT_COMPRESSION_zTXt: 1622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik compression = new_key[++key_len] = 1; /* compressed */ 1623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 1626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "iTXt: invalid compression"); 1627893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1628893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1629b50c217251b086440efcdb273c22f86a06c80cbaChris Craik new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE; 1630b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++key_len; /* for the keywod separator */ 1631b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* We leave it to the application to meet PNG-1.0 requirements on the 1633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of 1634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * any non-Latin-1 characters except for NEWLINE. ISO PNG, however, 1635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * specifies that the text is UTF-8 and this really doesn't require any 1636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * checking. 1637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. 1639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * TODO: validate the language tag correctly (see the spec.) 1641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (lang == NULL) lang = ""; /* empty language is valid */ 1643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lang_len = strlen(lang)+1; 1644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (lang_key == NULL) lang_key = ""; /* may be empty */ 1645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik lang_key_len = strlen(lang_key)+1; 1646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (text == NULL) text = ""; /* may be empty */ 1647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik prefix_len = key_len; 1649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (lang_len > PNG_UINT_31_MAX-prefix_len) 1650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik prefix_len = PNG_UINT_31_MAX; 1651893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 1652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik prefix_len = (png_uint_32)(prefix_len + lang_len); 1653893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (lang_key_len > PNG_UINT_31_MAX-prefix_len) 1655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik prefix_len = PNG_UINT_31_MAX; 1656893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 1657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik prefix_len = (png_uint_32)(prefix_len + lang_key_len); 1658893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_text_compress_init(&comp, (png_const_bytep)text, strlen(text)); 1660893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 16619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (compression != 0) 1662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK) 1664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, png_ptr->zstream.msg); 1665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1666893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (comp.input_len > PNG_UINT_31_MAX-prefix_len) 1670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "iTXt: uncompressed text too long"); 1671893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* So the string will fit in a chunk: */ 1673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik comp.output_len = (png_uint_32)/*SAFE*/comp.input_len; 1674b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1675893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len); 1677893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1678b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, new_key, key_len); 1679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len); 1681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len); 1683b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 16849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (compression != 0) 1685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_compressed_data_out(png_ptr, &comp); 1686b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 16889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.output_len); 1689893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1690893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_chunk_end(png_ptr); 1691893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1692893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1693893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 16945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_oFFs_SUPPORTED 1695a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write the oFFs chunk */ 1696893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1697b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset, 1698b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int unit_type) 1699893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1700893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[9]; 1701893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 17024215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_oFFs"); 17035f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1704893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (unit_type >= PNG_OFFSET_LAST) 1705893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); 1706893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1707893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_int_32(buf, x_offset); 1708893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_int_32(buf + 4, y_offset); 1709893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[8] = (png_byte)unit_type; 1710893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9); 1712893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1713893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 17145f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_pCAL_SUPPORTED 1715a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write the pCAL chunk (described in the PNG extensions document) */ 1716893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1717b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0, 1718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_int_32 X1, int type, int nparams, png_const_charp units, 1719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_charpp params) 1720893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 purpose_len; 1722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t units_len, total_len; 1723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_tp params_len; 1724893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[10]; 1725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte new_purpose[80]; 1726893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int i; 1727893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 17284215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); 17295f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1730893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (type >= PNG_EQUATION_LAST) 1731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "Unrecognized equation type for pCAL chunk"); 1732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1733b50c217251b086440efcdb273c22f86a06c80cbaChris Craik purpose_len = png_check_keyword(png_ptr, purpose, new_purpose); 1734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (purpose_len == 0) 1736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "pCAL: invalid keyword"); 1737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1738b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++purpose_len; /* terminator */ 1739893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 17404215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); 1741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik units_len = strlen(units) + (nparams == 0 ? 0 : 1); 17424215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug1(3, "pCAL units length = %d", (int)units_len); 1743893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project total_len = purpose_len + units_len + 10; 1744893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik params_len = (png_size_tp)png_malloc(png_ptr, 1746851c67770f9cebece9c79e914a54c348f539a512Matt Sarett (png_alloc_size_t)(nparams * (sizeof (png_size_t)))); 1747893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1748893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Find the length of each parameter, making sure we don't count the 1749b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * null terminator for the last parameter. 1750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1751893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0; i < nparams; i++) 1752893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1); 17544215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug2(3, "pCAL parameter %d length = %lu", i, 1755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (unsigned long)params_len[i]); 1756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik total_len += params_len[i]; 1757893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1758893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 17594215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug1(3, "pCAL total length = %d", (int)total_len); 1760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len); 1761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, new_purpose, purpose_len); 1762893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_int_32(buf, X0); 1763893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_int_32(buf + 4, X1); 1764893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[8] = (png_byte)type; 1765893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[9] = (png_byte)nparams; 1766893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_chunk_data(png_ptr, buf, (png_size_t)10); 1767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len); 1768893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1769893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0; i < nparams; i++) 1770893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1771b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]); 1772893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1773893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1774893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_free(png_ptr, params_len); 1775893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_chunk_end(png_ptr); 1776893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1777893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1778893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 17795f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_sCAL_SUPPORTED 1780a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write the sCAL chunk */ 1781893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1782b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width, 1783b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_charp height) 1784893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1785893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[64]; 1786893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_size_t wlen, hlen, total_len; 1787893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 17884215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_sCAL_s"); 1789893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1790b50c217251b086440efcdb273c22f86a06c80cbaChris Craik wlen = strlen(width); 1791b50c217251b086440efcdb273c22f86a06c80cbaChris Craik hlen = strlen(height); 1792893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project total_len = wlen + hlen + 2; 1793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1794893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (total_len > 64) 1795893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1796893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Can't write sCAL (buffer too small)"); 1797893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1798893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1799893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1800893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[0] = (png_byte)unit; 1801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ 1802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ 1803893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 18044215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); 1805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len); 1806893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1807893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1808893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 18095f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_pHYs_SUPPORTED 1810a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Write the pHYs chunk */ 1811893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1812b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit, 1813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y_pixels_per_unit, 1814b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int unit_type) 1815893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1816893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[9]; 1817893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 18184215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_pHYs"); 18195f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1820893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (unit_type >= PNG_RESOLUTION_LAST) 1821893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); 1822893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1823893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_uint_32(buf, x_pixels_per_unit); 1824893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_uint_32(buf + 4, y_pixels_per_unit); 1825893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[8] = (png_byte)unit_type; 1826893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9); 1828893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1829893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1830893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 18315f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_tIME_SUPPORTED 1832893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Write the tIME chunk. Use either png_convert_from_struct_tm() 1833893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * or png_convert_from_time_t(), or fill in the structure yourself. 1834893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1835893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1836b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_tIME(png_structrp png_ptr, png_const_timep mod_time) 1837893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1838893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_byte buf[7]; 1839893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 18404215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_tIME"); 18415f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1842893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (mod_time->month > 12 || mod_time->month < 1 || 1843893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project mod_time->day > 31 || mod_time->day < 1 || 1844893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project mod_time->hour > 23 || mod_time->second > 60) 1845893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1846893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Invalid time specified for tIME chunk"); 1847893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1848893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1849893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1850893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_save_uint_16(buf, mod_time->year); 1851893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[2] = mod_time->month; 1852893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[3] = mod_time->day; 1853893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[4] = mod_time->hour; 1854893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[5] = mod_time->minute; 1855893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project buf[6] = mod_time->second; 1856893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7); 1858893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1859893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1860893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1861a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Initializes the row writing capability of libpng */ 1862893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1863b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_start_row(png_structrp png_ptr) 1864893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1865893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1866a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 1867893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1868a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Start of interlace block */ 1869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 1870893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1871a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Offset to next interlace block */ 1872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 1873893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1874a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Start of interlace block in the y direction */ 1875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; 1876893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1877a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Offset to next interlace block in the y direction */ 1878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; 1879893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1880893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_alloc_size_t buf_size; 1882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int usr_pixel_depth; 1883893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 18849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_WRITE_FILTER_SUPPORTED 18859b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_byte filters; 18869b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 18879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 18884215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_start_row"); 18895f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1890b50c217251b086440efcdb273c22f86a06c80cbaChris Craik usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth; 1891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1; 1892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 1.5.6: added to allow checking in the row write code. */ 1894b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->transformed_pixel_depth = png_ptr->pixel_depth; 1895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth; 1896893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1897a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Set up row buffer */ 18989b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->row_buf = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); 1899b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1900893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; 1901893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 19025f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_FILTER_SUPPORTED 19039b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett filters = png_ptr->do_filter; 1904b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 19059b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->height == 1) 19069b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett filters &= 0xff & ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); 1907893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 19089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->width == 1) 19099b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett filters &= 0xff & ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH); 19109b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 19119b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (filters == 0) 19129b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett filters = PNG_FILTER_NONE; 19139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 19149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->do_filter = filters; 19159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 19169b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (((filters & (PNG_FILTER_SUB | PNG_FILTER_UP | PNG_FILTER_AVG | 19179b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_FILTER_PAETH)) != 0) && png_ptr->try_row == NULL) 1918893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 19199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int num_filters = 0; 1920893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 19219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->try_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); 1922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 19239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (filters & PNG_FILTER_SUB) 19249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett num_filters++; 1925893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 19269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (filters & PNG_FILTER_UP) 19279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett num_filters++; 1928b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 19299b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (filters & PNG_FILTER_AVG) 19309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett num_filters++; 1931893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 19329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (filters & PNG_FILTER_PAETH) 19339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett num_filters++; 1934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 19359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (num_filters > 1) 19369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->tst_row = png_voidcast(png_bytep, png_malloc(png_ptr, 19379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett buf_size)); 1938893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 19399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 19409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* We only need to keep the previous row if we are using one of the following 19419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * filters. 19429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett */ 19439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0) 19449b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->prev_row = png_voidcast(png_bytep, 19457a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_calloc(png_ptr, buf_size)); 19469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_FILTER */ 1947893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1948893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1949a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* If interlaced, we need to set up width and height of pass */ 19509b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->interlaced != 0) 1951893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 19529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->transformations & PNG_INTERLACE) == 0) 1953893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1954893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - 1955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_pass_ystart[0]) / png_pass_yinc[0]; 1956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1957893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - 1958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_pass_start[0]) / png_pass_inc[0]; 1959893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1961893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 1962893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1963893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->num_rows = png_ptr->height; 1964893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->usr_width = png_ptr->width; 1965893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1966893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1967b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1968893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 1969893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1970893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1971893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->num_rows = png_ptr->height; 1972893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->usr_width = png_ptr->width; 1973893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1974893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1975893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1976893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Internal use only. Called when finished processing a row of data. */ 1977893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 1978b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_finish_row(png_structrp png_ptr) 1979893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1980893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1981a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 1982893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1983a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Start of interlace block */ 1984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 1985893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1986a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Offset to next interlace block */ 1987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 1988893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1989a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Start of interlace block in the y direction */ 1990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; 1991893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1992a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Offset to next interlace block in the y direction */ 1993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; 1994893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1995893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 19964215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_finish_row"); 19975f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1998a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Next row */ 1999893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->row_number++; 2000893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2001a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* See if we are done */ 2002893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->row_number < png_ptr->num_rows) 2003893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 2004893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2005893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_WRITE_INTERLACING_SUPPORTED 2006a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* If interlaced, go to next pass */ 20079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->interlaced != 0) 2008893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2009893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->row_number = 0; 20109b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->transformations & PNG_INTERLACE) != 0) 2011893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2012893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->pass++; 2013893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2015893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 2016893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2017a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Loop until we find a non-zero width or height pass */ 2018893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project do 2019893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2020893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->pass++; 2021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2022893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->pass >= 7) 2023893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 2024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2025893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->usr_width = (png_ptr->width + 2026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_pass_inc[png_ptr->pass] - 1 - 2027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_pass_start[png_ptr->pass]) / 2028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_pass_inc[png_ptr->pass]; 2029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2030893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->num_rows = (png_ptr->height + 2031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_pass_yinc[png_ptr->pass] - 1 - 2032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_pass_ystart[png_ptr->pass]) / 2033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_pass_yinc[png_ptr->pass]; 2034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->transformations & PNG_INTERLACE) != 0) 2036893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 2037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2038893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); 2039893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2040893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2041893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2042a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Reset the row above the image for the next pass */ 2043893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->pass < 7) 2044893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2045893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->prev_row != NULL) 2046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(png_ptr->prev_row, 0, 2047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* 2048b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->usr_bit_depth, png_ptr->width)) + 1); 2049b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2050893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 2051893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2052893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2053893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 2054893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2055a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* If we get here, we've just written the last row, so we need 2056893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project to flush the compressor */ 2057b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH); 2058893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 2059893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 20605f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_INTERLACING_SUPPORTED 2061893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Pick out the correct pixels for the interlace pass. 2062893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * The basic idea here is to go through the row with a source 2063893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * pointer and a destination pointer (sp and dp), and copy the 2064893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * correct pixels for the pass. As the row gets compacted, 2065893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * sp will always be >= dp, so we should never overwrite anything. 2066893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * See the default: case for the easiest code to understand. 2067893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 2068893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 2069893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) 2070893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 2071a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 2072893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2073a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Start of interlace block */ 2074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 2075893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2076a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Offset to next interlace block */ 2077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 2078893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 20794215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_do_write_interlace"); 20805f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 2081a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* We don't have to do anything on the last pass (6) */ 2082893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (pass < 6) 2083893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2084a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Each pixel depth is handled separately */ 2085893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project switch (row_info->pixel_depth) 2086893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2087893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 1: 2088893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2089893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep sp; 2090893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep dp; 20919b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett unsigned int shift; 2092893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int d; 2093893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int value; 2094893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_uint_32 i; 2095893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_uint_32 row_width = row_info->width; 2096893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2097893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project dp = row; 2098893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project d = 0; 2099893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project shift = 7; 2100b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2101893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = png_pass_start[pass]; i < row_width; 2102893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project i += png_pass_inc[pass]) 2103893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project sp = row + (png_size_t)(i >> 3); 2105893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; 2106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project d |= (value << shift); 2107893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2108893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (shift == 0) 2109893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2110893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project shift = 7; 2111893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *dp++ = (png_byte)d; 2112893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project d = 0; 2113893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2115893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 2116893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project shift--; 2117893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2118893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2119893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (shift != 7) 2120893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *dp = (png_byte)d; 2121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2122893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 2123893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2125893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 2: 2126893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2127893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep sp; 2128893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep dp; 21299b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett unsigned int shift; 2130893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int d; 2131893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int value; 2132893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_uint_32 i; 2133893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_uint_32 row_width = row_info->width; 2134893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2135893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project dp = row; 2136893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project shift = 6; 2137893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project d = 0; 2138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2139893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = png_pass_start[pass]; i < row_width; 2140893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project i += png_pass_inc[pass]) 2141893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2142893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project sp = row + (png_size_t)(i >> 2); 2143893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; 2144893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project d |= (value << shift); 2145893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2146893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (shift == 0) 2147893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2148893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project shift = 6; 2149893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *dp++ = (png_byte)d; 2150893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project d = 0; 2151893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2152b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2153893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 2154893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project shift -= 2; 2155893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2156893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (shift != 6) 2157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *dp = (png_byte)d; 2158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2159893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 2160893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2162893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 4: 2163893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2164893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep sp; 2165893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep dp; 21669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett unsigned int shift; 2167893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int d; 2168893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int value; 2169893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_uint_32 i; 2170893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_uint_32 row_width = row_info->width; 2171893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2172893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project dp = row; 2173893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project shift = 4; 2174893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project d = 0; 2175893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = png_pass_start[pass]; i < row_width; 2176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik i += png_pass_inc[pass]) 2177893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2178893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project sp = row + (png_size_t)(i >> 1); 2179893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; 2180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project d |= (value << shift); 2181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2182893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (shift == 0) 2183893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2184893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project shift = 4; 2185893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *dp++ = (png_byte)d; 2186893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project d = 0; 2187893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2188b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2189893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else 2190893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project shift -= 4; 2191893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2192893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (shift != 4) 2193893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project *dp = (png_byte)d; 2194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2195893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 2196893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2197b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2198893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project default: 2199893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2200893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep sp; 2201893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep dp; 2202893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_uint_32 i; 2203893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_uint_32 row_width = row_info->width; 2204893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_size_t pixel_bytes; 2205893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2206a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Start at the beginning */ 2207893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project dp = row; 2208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2209a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Find out how many bytes each pixel takes up */ 2210893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project pixel_bytes = (row_info->pixel_depth >> 3); 2211b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2212b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Loop through the row, only looking at the pixels that matter */ 2213893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = png_pass_start[pass]; i < row_width; 2214893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project i += png_pass_inc[pass]) 2215893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2216a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Find out where the original pixel is */ 2217893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project sp = row + (png_size_t)i * pixel_bytes; 2218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2219a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Move the pixel */ 2220893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (dp != sp) 2221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memcpy(dp, sp, pixel_bytes); 2222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2223a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Next pixel */ 2224893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project dp += pixel_bytes; 2225893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2226893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 2227893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2228893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2229a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Set new row width */ 2230893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project row_info->width = (row_info->width + 2231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_pass_inc[pass] - 1 - 2232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_pass_start[pass]) / 2233b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_pass_inc[pass]; 2234b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 2236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info->width); 2237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2238893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 2239893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 2240893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 22419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 2242893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* This filters the row, chooses which filter to use, if it has not already 2243893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * been specified by the application, and then writes the row out with the 2244893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * chosen filter. 2245893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 22469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarettstatic void /* PRIVATE */ 2247b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, 22487a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_size_t row_bytes); 2249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 22509b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_WRITE_FILTER_SUPPORTED 22519b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarettstatic png_size_t /* PRIVATE */ 22529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarettpng_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, 22539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett const png_size_t row_bytes, const png_size_t lmins) 22549b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett{ 22559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_bytep rp, dp, lp; 22569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t i; 22579b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t sum = 0; 2258851c67770f9cebece9c79e914a54c348f539a512Matt Sarett int v; 22599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 22609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; 22619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 22629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp; 22639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett i++, rp++, dp++) 22649b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 22659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett v = *dp = *rp; 22667a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#ifdef PNG_USE_ABS 2267851c67770f9cebece9c79e914a54c348f539a512Matt Sarett sum += 128 - abs(v - 128); 22687a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#else 22699b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett sum += (v < 128) ? v : 256 - v; 22707a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif 22719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 22729b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 22739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (lp = png_ptr->row_buf + 1; i < row_bytes; 22749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett i++, rp++, lp++, dp++) 22759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 22769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); 22777a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#ifdef PNG_USE_ABS 2278851c67770f9cebece9c79e914a54c348f539a512Matt Sarett sum += 128 - abs(v - 128); 22797a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#else 22809b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett sum += (v < 128) ? v : 256 - v; 22817a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif 22829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 22839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (sum > lmins) /* We are already worse, don't continue. */ 22849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett break; 22859b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 22869b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 22879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return (sum); 22889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett} 22899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 22907a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidisstatic void /* PRIVATE */ 22917a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidispng_setup_sub_row_only(png_structrp png_ptr, const png_uint_32 bpp, 22927a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis const png_size_t row_bytes) 22937a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis{ 22947a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_bytep rp, dp, lp; 22957a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_size_t i; 22967a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 22977a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; 22987a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 22997a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp; 23007a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis i++, rp++, dp++) 23017a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 23027a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis *dp = *rp; 23037a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 23047a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 23057a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis for (lp = png_ptr->row_buf + 1; i < row_bytes; 23067a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis i++, rp++, lp++, dp++) 23077a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 23087a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); 23097a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 23107a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis} 23117a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 23129b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarettstatic png_size_t /* PRIVATE */ 23139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarettpng_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, 23149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett const png_size_t lmins) 23159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett{ 23169b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_bytep rp, dp, pp; 23179b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t i; 23189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t sum = 0; 2319851c67770f9cebece9c79e914a54c348f539a512Matt Sarett int v; 23209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; 23229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, 23249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pp = png_ptr->prev_row + 1; i < row_bytes; 23259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett i++, rp++, pp++, dp++) 23269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 23279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); 23287a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#ifdef PNG_USE_ABS 2329851c67770f9cebece9c79e914a54c348f539a512Matt Sarett sum += 128 - abs(v - 128); 23307a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#else 23319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett sum += (v < 128) ? v : 256 - v; 23327a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif 23339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23349b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (sum > lmins) /* We are already worse, don't continue. */ 23359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett break; 23369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 23379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23389b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return (sum); 23399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett} 23407a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidisstatic void /* PRIVATE */ 23417a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidispng_setup_up_row_only(png_structrp png_ptr, const png_size_t row_bytes) 23427a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis{ 23437a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_bytep rp, dp, pp; 23447a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_size_t i; 23457a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 23467a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; 23477a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 23487a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, 23497a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis pp = png_ptr->prev_row + 1; i < row_bytes; 23507a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis i++, rp++, pp++, dp++) 23517a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 23527a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); 23537a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 23547a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis} 23559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarettstatic png_size_t /* PRIVATE */ 23579b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarettpng_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, 23587a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis const png_size_t row_bytes, const png_size_t lmins) 23599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett{ 23609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_bytep rp, dp, pp, lp; 23619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_uint_32 i; 23629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t sum = 0; 2363851c67770f9cebece9c79e914a54c348f539a512Matt Sarett int v; 23649b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; 23669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23679b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, 23687a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis pp = png_ptr->prev_row + 1; i < bpp; i++) 23699b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 23709b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); 23719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23727a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#ifdef PNG_USE_ABS 2373851c67770f9cebece9c79e914a54c348f539a512Matt Sarett sum += 128 - abs(v - 128); 23747a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#else 23759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett sum += (v < 128) ? v : 256 - v; 23767a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif 23779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 23789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23799b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (lp = png_ptr->row_buf + 1; i < row_bytes; i++) 23809b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 23819b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) 23829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett & 0xff); 23839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23847a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#ifdef PNG_USE_ABS 2385851c67770f9cebece9c79e914a54c348f539a512Matt Sarett sum += 128 - abs(v - 128); 23867a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#else 23879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett sum += (v < 128) ? v : 256 - v; 23887a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif 23899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (sum > lmins) /* We are already worse, don't continue. */ 23919b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett break; 23929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 23939b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 23949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return (sum); 23959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett} 23967a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidisstatic void /* PRIVATE */ 23977a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidispng_setup_avg_row_only(png_structrp png_ptr, const png_uint_32 bpp, 23987a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis const png_size_t row_bytes) 23997a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis{ 24007a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_bytep rp, dp, pp, lp; 24017a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_uint_32 i; 24027a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 24037a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; 24047a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 24057a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, 24067a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis pp = png_ptr->prev_row + 1; i < bpp; i++) 24077a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 24087a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); 24097a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 24107a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 24117a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis for (lp = png_ptr->row_buf + 1; i < row_bytes; i++) 24127a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 24137a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) 24147a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis & 0xff); 24157a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 24167a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis} 24179b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarettstatic png_size_t /* PRIVATE */ 24199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarettpng_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, 24209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett const png_size_t row_bytes, const png_size_t lmins) 24219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett{ 24229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_bytep rp, dp, pp, cp, lp; 24239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t i; 24249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t sum = 0; 2425851c67770f9cebece9c79e914a54c348f539a512Matt Sarett int v; 24269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; 24289b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24299b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, 24309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pp = png_ptr->prev_row + 1; i < bpp; i++) 24319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 24329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); 24339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24347a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#ifdef PNG_USE_ABS 2435851c67770f9cebece9c79e914a54c348f539a512Matt Sarett sum += 128 - abs(v - 128); 24367a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#else 24379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett sum += (v < 128) ? v : 256 - v; 24387a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif 24399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 24409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; 24429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett i++) 24439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 24449b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int a, b, c, pa, pb, pc, p; 24459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett b = *pp++; 24479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett c = *cp++; 24489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett a = *lp++; 24499b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24509b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett p = b - c; 24519b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pc = a - c; 24529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_USE_ABS 24549b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pa = abs(p); 24559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pb = abs(pc); 24569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pc = abs(p + pc); 24579b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#else 24589b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pa = p < 0 ? -p : p; 24599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pb = pc < 0 ? -pc : pc; 24609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett pc = (p + pc) < 0 ? -(p + pc) : p + pc; 24619b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 24629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; 24649b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); 24669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24677a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#ifdef PNG_USE_ABS 2468851c67770f9cebece9c79e914a54c348f539a512Matt Sarett sum += 128 - abs(v - 128); 24697a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#else 24709b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett sum += (v < 128) ? v : 256 - v; 24717a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif 24729b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (sum > lmins) /* We are already worse, don't continue. */ 24749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett break; 24759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 24769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 24779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett return (sum); 24789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett} 24797a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidisstatic void /* PRIVATE */ 24807a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidispng_setup_paeth_row_only(png_structrp png_ptr, const png_uint_32 bpp, 24817a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis const png_size_t row_bytes) 24827a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis{ 24837a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_bytep rp, dp, pp, cp, lp; 24847a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_size_t i; 24857a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 24867a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; 24877a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 24887a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, 24897a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis pp = png_ptr->prev_row + 1; i < bpp; i++) 24907a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 24917a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); 24927a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 24937a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 24947a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; 24957a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis i++) 24967a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 24977a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis int a, b, c, pa, pb, pc, p; 24987a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 24997a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis b = *pp++; 25007a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis c = *cp++; 25017a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis a = *lp++; 25027a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 25037a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis p = b - c; 25047a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis pc = a - c; 25057a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 25067a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#ifdef PNG_USE_ABS 25077a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis pa = abs(p); 25087a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis pb = abs(pc); 25097a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis pc = abs(p + pc); 25107a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#else 25117a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis pa = p < 0 ? -p : p; 25127a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis pb = pc < 0 ? -pc : pc; 25137a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis pc = (p + pc) < 0 ? -(p + pc) : p + pc; 25147a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif 25157a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 25167a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; 25177a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis 25187a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); 25197a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 25207a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis} 25219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_FILTER */ 25229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 2523893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid /* PRIVATE */ 2524b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_find_filter(png_structrp png_ptr, png_row_infop row_info) 2525893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 25269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifndef PNG_WRITE_FILTER_SUPPORTED 25279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1); 25289b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#else 25297a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis unsigned int filter_to_do = png_ptr->do_filter; 25309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_bytep row_buf; 25319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_bytep best_row; 25329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_uint_32 bpp; 25339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t mins; 2534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t row_bytes = row_info->rowbytes; 2535893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 25364215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_find_filter"); 25375f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 2538a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Find out how many bytes offset each pixel is */ 2539893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project bpp = (row_info->pixel_depth + 7) >> 3; 2540893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 25419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett row_buf = png_ptr->row_buf; 25429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett mins = PNG_SIZE_MAX - 256/* so we can detect potential overflow of the 25439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett running sum */; 2544893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2545893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* The prediction method we use is to find which method provides the 2546893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * smallest value when summing the absolute values of the distances 2547893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * from zero, using anything >= 128 as negative numbers. This is known 2548893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * as the "minimum sum of absolute differences" heuristic. Other 2549893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * heuristics are the "weighted minimum sum of absolute differences" 2550893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (experimental and can in theory improve compression), and the "zlib 2551893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * predictive" method (not implemented yet), which does test compressions 2552893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * of lines using different filter methods, and then chooses the 2553893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (series of) filter(s) that give minimum compressed data size (VERY 2554893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * computationally expensive). 2555893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 2556893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * GRR 980525: consider also 2557b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2558893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (1) minimum sum of absolute differences from running average (i.e., 2559893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * keep running sum of non-absolute differences & count of bytes) 2560893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * [track dispersion, too? restart average if dispersion too large?] 2561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2562893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (1b) minimum sum of absolute differences from sliding average, probably 2563893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * with window size <= deflate window (usually 32K) 2564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 2565893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (2) minimum sum of squared differences from zero or running average 2566893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * (i.e., ~ root-mean-square approach) 2567893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 2568893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2569893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2570893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* We don't need to test the 'no filter' case if this is the only filter 2571893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * that has been chosen, as it doesn't actually do anything to the data. 2572893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 25739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett best_row = png_ptr->row_buf; 25749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 25757a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (PNG_SIZE_MAX/128 <= row_bytes) 2576893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 25777a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* Overflow can occur in the calculation, just select the lowest set 25787a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * filter. 25797a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis */ 25807a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis filter_to_do &= 0U-filter_to_do; 25817a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis } 25827a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis else if ((filter_to_do & PNG_FILTER_NONE) != 0 && 25837a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis filter_to_do != PNG_FILTER_NONE) 25847a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis { 25857a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* Overflow not possible and multiple filters in the list, including the 25867a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis * 'none' filter. 25877a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis */ 2588893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep rp; 25899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t sum = 0; 2590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_size_t i; 2591851c67770f9cebece9c79e914a54c348f539a512Matt Sarett int v; 2592893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2593893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 25949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) 2595893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 25969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett v = *rp; 25977a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#ifdef PNG_USE_ABS 2598851c67770f9cebece9c79e914a54c348f539a512Matt Sarett sum += 128 - abs(v - 128); 25997a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#else 26009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett sum += (v < 128) ? v : 256 - v; 26017a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis#endif 2602893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2603893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 26049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 2605893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project mins = sum; 2606893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2607893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2608a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Sub filter */ 2609893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (filter_to_do == PNG_FILTER_SUB) 2610a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* It's the only filter so no testing is needed */ 2611893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 26127a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_setup_sub_row_only(png_ptr, bpp, row_bytes); 26139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett best_row = png_ptr->try_row; 2614893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2615893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 26169b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else if ((filter_to_do & PNG_FILTER_SUB) != 0) 2617893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 26189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t sum; 26199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t lmins = mins; 2620893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 262106f1087a94f1e48298e89d77ccc51a0ced871958Matt Sarett sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); 2622893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2623893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (sum < mins) 2624893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2625893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project mins = sum; 26269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett best_row = png_ptr->try_row; 26279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->tst_row != NULL) 26289b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 26299b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->try_row = png_ptr->tst_row; 26309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->tst_row = best_row; 26319b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 2632893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2633893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2634893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2635a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Up filter */ 2636893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (filter_to_do == PNG_FILTER_UP) 2637893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 26387a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_setup_up_row_only(png_ptr, row_bytes); 26399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett best_row = png_ptr->try_row; 2640893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2641893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 26429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else if ((filter_to_do & PNG_FILTER_UP) != 0) 2643893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 26449b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t sum; 26459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t lmins = mins; 2646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 264706f1087a94f1e48298e89d77ccc51a0ced871958Matt Sarett sum = png_setup_up_row(png_ptr, row_bytes, lmins); 2648893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2649893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (sum < mins) 2650893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2651893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project mins = sum; 26529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett best_row = png_ptr->try_row; 26539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->tst_row != NULL) 26549b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 26559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->try_row = png_ptr->tst_row; 26569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->tst_row = best_row; 26579b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 2658893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2659893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2660893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2661a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Avg filter */ 2662893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (filter_to_do == PNG_FILTER_AVG) 2663893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 26647a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_setup_avg_row_only(png_ptr, bpp, row_bytes); 26659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett best_row = png_ptr->try_row; 2666893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2667893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 26689b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else if ((filter_to_do & PNG_FILTER_AVG) != 0) 2669893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 26709b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t sum; 26719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t lmins = mins; 2672893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 26739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); 2674893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2675893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (sum < mins) 2676893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2677893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project mins = sum; 26789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett best_row = png_ptr->try_row; 26799b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->tst_row != NULL) 26809b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 26819b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->try_row = png_ptr->tst_row; 26829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->tst_row = best_row; 26839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 2684893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2685893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2686893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2687893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Paeth filter */ 26887a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis if (filter_to_do == PNG_FILTER_PAETH) 2689893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 26907a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_setup_paeth_row_only(png_ptr, bpp, row_bytes); 26919b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett best_row = png_ptr->try_row; 2692893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2693893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 26949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else if ((filter_to_do & PNG_FILTER_PAETH) != 0) 2695893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 26969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t sum; 26979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_size_t lmins = mins; 2698b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 26999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); 2700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 27019b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (sum < mins) 2702893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 27039b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett best_row = png_ptr->try_row; 27049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->tst_row != NULL) 2705893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 27069b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->try_row = png_ptr->tst_row; 27079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->tst_row = best_row; 2708893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2709893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2710893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 2711893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Do the actual writing of the filtered row data from the chosen filter. */ 2713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1); 2714893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 27159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_FILTER */ 2716893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 2717893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2718893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2719893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Do the actual writing of a previously filtered row. */ 2720b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 2721b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, 27227a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_size_t full_row_length/*includes filter byte*/) 2723893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 27244215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_filtered_row"); 27255f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 27264215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug1(2, "filter = %d", filtered_row[0]); 2727893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH); 2729893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 27309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_WRITE_FILTER_SUPPORTED 2731a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Swap the current and previous rows */ 2732893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->prev_row != NULL) 2733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2734893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_bytep tptr; 2735893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2736893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project tptr = png_ptr->prev_row; 2737893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->prev_row = png_ptr->row_buf; 2738893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->row_buf = tptr; 2739893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 27409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_FILTER */ 2741893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2742a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Finish row - updates counters and flushes zlib if last row */ 2743893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_finish_row(png_ptr); 2744893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 27455f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_FLUSH_SUPPORTED 2746893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->flush_rows++; 2747893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2748893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->flush_dist > 0 && 2749893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->flush_rows >= png_ptr->flush_dist) 2750893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2751893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_flush(png_ptr); 2752893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 27539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_FLUSH */ 2754893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 27559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE */ 2756