1893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* pngwrite.c - general routines 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" 15114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED 16b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# include <errno.h> 17114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett#endif /* SIMPLIFIED_WRITE_STDIO */ 18b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 19893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#ifdef PNG_WRITE_SUPPORTED 20893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 21b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 22b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Write out all the unknown chunks for the current given location */ 23b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 24b50c217251b086440efcdb273c22f86a06c80cbaChris Craikwrite_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr, 257a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis unsigned int where) 26b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (info_ptr->unknown_chunks_num != 0) 28b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 29b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_unknown_chunkp up; 30b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 31b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug(5, "writing extra chunks"); 32b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 33b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (up = info_ptr->unknown_chunks; 34b50c217251b086440efcdb273c22f86a06c80cbaChris Craik up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num; 35b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++up) 369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((up->location & where) != 0) 37b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 38b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If per-chunk unknown chunk handling is enabled use it, otherwise 39b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * just write the chunks the application has set. 40b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 41b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED 42b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int keep = png_handle_as_unknown(png_ptr, up->name); 43b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 44b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* NOTE: this code is radically different from the read side in the 45b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * matter of handling an ancillary unknown chunk. In the read side 46b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the default behavior is to discard it, in the code below the default 47b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * behavior is to write it. Critical chunks are, however, only 48b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * written if explicitly listed or if the default is set to write all 49b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * unknown chunks. 50b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 51b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * The default handling is also slightly weird - it is not possible to 52b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * stop the writing of all unsafe-to-copy chunks! 53b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 54b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * TODO: REVIEW: this would seem to be a bug. 55b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 56b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (keep != PNG_HANDLE_CHUNK_NEVER && 57b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ || 58b50c217251b086440efcdb273c22f86a06c80cbaChris Craik keep == PNG_HANDLE_CHUNK_ALWAYS || 59b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (keep == PNG_HANDLE_CHUNK_AS_DEFAULT && 60b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS))) 61b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 62b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 63b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* TODO: review, what is wrong with a zero length unknown chunk? */ 64b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (up->size == 0) 65b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Writing zero-length unknown chunk"); 66b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 67b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_chunk(png_ptr, up->name, up->data, up->size); 68b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 69b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 70b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 71b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 729b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_UNKNOWN_CHUNKS */ 73b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 74893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Writes all the PNG information. This is the suggested way to use the 75893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * library. If you have a new chunk to add, make a function to write it, 76893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * and put it in the correct location here. If you want the chunk written 77893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * after the image data, put it in png_write_end(). I strongly encourage 78893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing 79893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * the chunk, as that will keep the code from breaking if you want to just 80893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * write a plain PNG file. If you have long comments, I suggest writing 81893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * them in png_write_end(), and compressing them. 82893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 83893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 84b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) 85893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 864215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_info_before_PLTE"); 875f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 88893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL || info_ptr == NULL) 89893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 90b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 919b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0) 92893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 939b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Write PNG signature */ 949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_write_sig(png_ptr); 95b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 965f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_MNG_FEATURES_SUPPORTED 979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \ 989b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->mng_features_permitted != 0) 999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 1009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_warning(png_ptr, 1019b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett "MNG features are not allowed in a PNG datastream"); 1029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->mng_features_permitted = 0; 1039b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 104893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1069b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Write IHDR information. */ 1079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, 1089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, 1099b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->filter_type, 1105f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_INTERLACING_SUPPORTED 1119b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->interlace_type 112893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 1139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 0 114893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett ); 116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1179b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* The rest of these check to see if the valid field has the appropriate 1189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * flag set, and if it does, writes the chunk. 1199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 1209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 1.6.0: COLORSPACE support controls the writing of these chunks too, and 1219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * the chunks will be written if the WRITE routine is there and 1229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * information * is available in the COLORSPACE. (See 1239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * png_colorspace_sync_info in png.c for where the valid flags get set.) 1249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 1259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * Under certain circumstances the colorspace can be invalidated without 1269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * syncing the info_struct 'valid' flags; this happens if libpng detects 1279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * an error and calls png_error while the color space is being set, yet 1289b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * the application continues writing the PNG. So check the 'invalid' 1299b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * flag here too. 1309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett */ 131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_GAMMA_SUPPORTED 132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_WRITE_gAMA_SUPPORTED 1339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && 1349b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 && 1359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (info_ptr->valid & PNG_INFO_gAMA) != 0) 136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma); 137893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project# endif 138893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 139b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_COLORSPACE_SUPPORTED 1419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Write only one of sRGB or an ICC profile. If a profile was supplied 1429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * and it matches one of the known sRGB ones issue a warning. 1439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett */ 144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_WRITE_iCCP_SUPPORTED 1459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && 1469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (info_ptr->valid & PNG_INFO_iCCP) != 0) 1479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 1489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef PNG_WRITE_sRGB_SUPPORTED 1499b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_sRGB) != 0) 1509b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_app_warning(png_ptr, 1517a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "profile matches sRGB but writing iCCP instead"); 1529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 1539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 1549b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_write_iCCP(png_ptr, info_ptr->iccp_name, 1557a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis info_ptr->iccp_profile); 1569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 157b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_WRITE_sRGB_SUPPORTED 158b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 159b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 160b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif 161b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 162b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_WRITE_sRGB_SUPPORTED 1639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && 1649b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (info_ptr->valid & PNG_INFO_sRGB) != 0) 1659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent); 166b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# endif /* WRITE_sRGB */ 167b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* COLORSPACE */ 168b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1695f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_sBIT_SUPPORTED 1709b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_sBIT) != 0) 1719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); 172893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 173b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 174b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_COLORSPACE_SUPPORTED 175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# ifdef PNG_WRITE_cHRM_SUPPORTED 1769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && 1779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 && 1789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (info_ptr->valid & PNG_INFO_cHRM) != 0) 1799b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy); 180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project# endif 181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 182893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 1849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); 185893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 186b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 187893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; 188893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 189893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 190893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 191893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 192b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_info(png_structrp png_ptr, png_const_inforp info_ptr) 193893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 194893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) 195893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project int i; 196893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 197893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1984215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_info"); 199893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 200893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL || info_ptr == NULL) 201893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 202893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 203893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_info_before_PLTE(png_ptr, info_ptr); 204893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2059b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_PLTE) != 0) 206893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_PLTE(png_ptr, info_ptr->palette, 207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_uint_32)info_ptr->num_palette); 208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 209893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 210893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_error(png_ptr, "Valid palette required for paletted images"); 211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 2125f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_tRNS_SUPPORTED 2139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_tRNS) !=0) 214a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 2155f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED 216a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Invert the alpha channel (in tRNS) */ 2179b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 && 218b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 219a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott { 2209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int j, jend; 2219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 2229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett jend = info_ptr->num_trans; 2239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (jend > PNG_MAX_PALETTE_LENGTH) 2249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett jend = PNG_MAX_PALETTE_LENGTH; 2259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 2269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett for (j = 0; j<jend; ++j) 227b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->trans_alpha[j] = 228b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_byte)(255 - info_ptr->trans_alpha[j]); 229a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 230893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_tRNS(png_ptr, info_ptr->trans_alpha, &(info_ptr->trans_color), 232b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->num_trans, info_ptr->color_type); 233a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott } 234893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 2355f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_bKGD_SUPPORTED 2369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_bKGD) != 0) 237893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type); 238893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2405f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_hIST_SUPPORTED 2419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_hIST) != 0) 242893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette); 243893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 244b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2455f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_oFFs_SUPPORTED 2469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_oFFs) != 0) 247893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset, 248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->offset_unit_type); 249893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2515f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_pCAL_SUPPORTED 2529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_pCAL) != 0) 253893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0, 254b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams, 255b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->pcal_units, info_ptr->pcal_params); 256893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 257a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott 2585f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_sCAL_SUPPORTED 2599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_sCAL) != 0) 260893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit, 261893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project info_ptr->scal_s_width, info_ptr->scal_s_height); 262a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott#endif /* sCAL */ 263a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott 2645f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_pHYs_SUPPORTED 2659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_pHYs) != 0) 266893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit, 267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type); 268a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott#endif /* pHYs */ 269a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott 2705f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_tIME_SUPPORTED 2719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_tIME) != 0) 272893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 273893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_tIME(png_ptr, &(info_ptr->mod_time)); 274893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->mode |= PNG_WROTE_tIME; 275893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 276a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott#endif /* tIME */ 277a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott 2785f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_sPLT_SUPPORTED 2799b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_sPLT) != 0) 280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i = 0; i < (int)info_ptr->splt_palettes_num; i++) 281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_sPLT(png_ptr, info_ptr->splt_palettes + i); 282a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott#endif /* sPLT */ 283a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott 2845f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_TEXT_SUPPORTED 285893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Check to see if we need to write text chunks */ 286893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0; i < info_ptr->num_text; i++) 287893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2884215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug2(2, "Writing header text chunk %d, type %d", i, 289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].compression); 290a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* An internationalized chunk? */ 291893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (info_ptr->text[i].compression > 0) 292893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 2935f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_iTXt_SUPPORTED 294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Write international chunk */ 295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_iTXt(png_ptr, 296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].compression, 297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].key, 298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].lang, 299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].lang_key, 300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].text); 3019b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Mark this chunk as written */ 3029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 3039b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 3049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else 3059b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; 306893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 3079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_warning(png_ptr, "Unable to write international text"); 308893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 309893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 311893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* If we want a compressed text chunk */ 312893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_zTXt) 313893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 3145f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_zTXt_SUPPORTED 315a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write compressed chunk */ 316893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_zTXt(png_ptr, info_ptr->text[i].key, 3179b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->text[i].text, info_ptr->text[i].compression); 3189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Mark this chunk as written */ 3199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; 320893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 321893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Unable to write compressed text"); 322893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 323893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 325893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 326893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 3275f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_tEXt_SUPPORTED 328a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write uncompressed chunk */ 329893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_tEXt(png_ptr, info_ptr->text[i].key, 330b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].text, 331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 0); 332a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Mark this chunk as written */ 333a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 334893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 335a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Can't get here */ 336893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Unable to write uncompressed text"); 337893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 338893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 339893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 340a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott#endif /* tEXt */ 341a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott 3425f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE); 344893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 347893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Writes the end of the PNG file. If you don't want to write comments or 348893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * time information, you can pass NULL for info. If you already wrote these 349893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * in png_write_info(), do not write them again here. If you have long 350893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * comments, I suggest writing them here, and compressing them. 351893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 352893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 353b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_end(png_structrp png_ptr, png_inforp info_ptr) 354893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 3554215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_end"); 3565f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 357893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 358893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 3609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->mode & PNG_HAVE_IDAT) == 0) 361893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_error(png_ptr, "No IDATs written into file"); 362893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED 364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr->num_palette_max > png_ptr->num_palette) 365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_benign_error(png_ptr, "Wrote palette index exceeding num_palette"); 366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 368a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* See if user wants us to write information chunks */ 369893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (info_ptr != NULL) 370893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 3715f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_TEXT_SUPPORTED 3725f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott int i; /* local index variable */ 373893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 3745f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_tIME_SUPPORTED 375a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Check to see if user has supplied a time chunk */ 3769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_tIME) != 0 && 3779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (png_ptr->mode & PNG_WROTE_tIME) == 0) 378893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_tIME(png_ptr, &(info_ptr->mod_time)); 379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 380893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 3815f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_TEXT_SUPPORTED 382a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Loop through comment chunks */ 383893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0; i < info_ptr->num_text; i++) 384893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 3854215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug2(2, "Writing trailer text chunk %d, type %d", i, 3867a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis info_ptr->text[i].compression); 387a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* An internationalized chunk? */ 388893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (info_ptr->text[i].compression > 0) 389893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 3905f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_iTXt_SUPPORTED 3915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott /* Write international chunk */ 3925f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_write_iTXt(png_ptr, 393b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].compression, 394b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].key, 395b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].lang, 396b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].lang_key, 397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].text); 3989b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Mark this chunk as written */ 3999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 4009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 4019b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else 4029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; 403893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 4045f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_warning(png_ptr, "Unable to write international text"); 405893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 406893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 407b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 408893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt) 409893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 4105f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_zTXt_SUPPORTED 411a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write compressed chunk */ 412893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_zTXt(png_ptr, info_ptr->text[i].key, 4139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->text[i].text, info_ptr->text[i].compression); 4149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Mark this chunk as written */ 4159b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR; 416893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 417893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Unable to write compressed text"); 418893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 419893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 420b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 421893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE) 422893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 4235f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_tEXt_SUPPORTED 424a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write uncompressed chunk */ 425893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_tEXt(png_ptr, info_ptr->text[i].key, 426b50c217251b086440efcdb273c22f86a06c80cbaChris Craik info_ptr->text[i].text, 0); 4279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Mark this chunk as written */ 4289b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR; 429893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 430893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Unable to write uncompressed text"); 431893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 432893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 433893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 434893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 4355f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED 436b50c217251b086440efcdb273c22f86a06c80cbaChris Craik write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT); 437893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 438893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 439893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 440893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->mode |= PNG_AFTER_IDAT; 441893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 442a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write end of PNG file */ 443893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_IEND(png_ptr); 4449b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett 4454215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project /* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03, 4464215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project * and restored again in libpng-1.2.30, may cause some applications that 4474215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project * do not set png_ptr->output_flush_fn to crash. If your application 4484215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project * experiences a problem, please try building libpng with 4494215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project * PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED defined, and report the event to 4505f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott * png-mng-implement at lists.sf.net . 4514215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project */ 4525f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_FLUSH_SUPPORTED 4535f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED 4544215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_flush(png_ptr); 4555f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott# endif 4564215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project#endif 457893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 458893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 4595f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_CONVERT_tIME_SUPPORTED 460893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 461b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime) 462893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 4634215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_convert_from_struct_tm"); 4645f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 465893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project ptime->year = (png_uint_16)(1900 + ttime->tm_year); 466893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project ptime->month = (png_byte)(ttime->tm_mon + 1); 467893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project ptime->day = (png_byte)ttime->tm_mday; 468893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project ptime->hour = (png_byte)ttime->tm_hour; 469893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project ptime->minute = (png_byte)ttime->tm_min; 470893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project ptime->second = (png_byte)ttime->tm_sec; 471893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 472893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 473893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 474893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectpng_convert_from_time_t(png_timep ptime, time_t ttime) 475893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 476893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project struct tm *tbuf; 477893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 4784215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_convert_from_time_t"); 4795f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 480893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project tbuf = gmtime(&ttime); 481893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_convert_from_struct_tm(ptime, tbuf); 482893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 483893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 484893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 485893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Initialize png_ptr structure, and allocate any memory needed */ 486b50c217251b086440efcdb273c22f86a06c80cbaChris CraikPNG_FUNCTION(png_structp,PNGAPI 487b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr, 488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED) 489893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifndef PNG_USER_MEM_SUPPORTED 491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, 4929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett error_fn, warn_fn, NULL, NULL, NULL); 493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#else 494b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_create_write_struct_2(user_png_ver, error_ptr, error_fn, 495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik warn_fn, NULL, NULL, NULL); 496893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 497893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 498893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Alternate initialize png_ptr structure, and allocate any memory needed */ 499b50c217251b086440efcdb273c22f86a06c80cbaChris CraikPNG_FUNCTION(png_structp,PNGAPI 500b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, 501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr, 502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED) 503893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr, 5059b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett error_fn, warn_fn, mem_ptr, malloc_fn, free_fn); 5069b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* USER_MEM */ 507b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr != NULL) 5085f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott { 509b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Set the zlib control values to defaults; they can be overridden by the 510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * application after the struct has been created. 511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zbuffer_size = PNG_ZBUF_SIZE; 513893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The 'zlib_strategy' setting is irrelevant because png_default_claim in 515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pngwutil.c defaults it according to whether or not filters will be 516b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * used, and ignores this setting. 517b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY; 519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION; 520b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_mem_level = 8; 521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_window_bits = 15; 522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_method = 8; 523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED 525b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY; 526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION; 527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_text_mem_level = 8; 528b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_text_window_bits = 15; 529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_text_method = 8; 5309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_COMPRESSED_TEXT */ 531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 532b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is a highly dubious configuration option; by default it is off, 533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * but it may be appropriate for private builds that are testing 534b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * extensions not conformant to the current specification, or of 535b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * applications that must not fail to write at all costs! 536b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 537b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED 538b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* In stable builds only warn if an application error can be completely 539b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * handled. 540b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 5419b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN; 542893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 543893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 544b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* App warnings are warnings in release (or release candidate) builds but 545b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * are errors during development. 546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 5479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#if PNG_RELEASE_BUILD 548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; 549893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 550893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* TODO: delay this, it can be done in png_init_io() (if the app doesn't 552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * do it itself) avoiding setting the default function if it is not 553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * required. 554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_write_fn(png_ptr, NULL, NULL, NULL); 5565f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott } 557893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_ptr; 559893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 560893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 562893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Write a few rows of image data. If the image is interlaced, 563893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * either you will have to write the 7 sub images, or, if you 564893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * have called png_set_interlace_handling(), you will have to 565893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * "write" the image seven times. 566893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 567893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 568b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_rows(png_structrp png_ptr, png_bytepp row, 569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 num_rows) 570893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 5715f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_uint_32 i; /* row counter */ 5725f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_bytepp rp; /* row pointer */ 573893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 5744215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_rows"); 575893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 576893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 577893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 578893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 579a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Loop through the rows */ 580893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0, rp = row; i < num_rows; i++, rp++) 581893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 582893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_row(png_ptr, *rp); 583893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 584893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 585893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 586893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Write the image. You only need to call this function once, even 587893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * if you are writing an interlaced image. 588893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 589893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 590b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_image(png_structrp png_ptr, png_bytepp image) 591893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 5925f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_uint_32 i; /* row index */ 5935f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott int pass, num_pass; /* pass variables */ 5945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_bytepp rp; /* points to current row */ 595893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 596893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 597893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 598893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 5994215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_image"); 6005f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 6015f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_INTERLACING_SUPPORTED 602a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Initialize interlace handling. If image is not interlaced, 603a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott * this will set pass to 1 604a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott */ 605893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project num_pass = png_set_interlace_handling(png_ptr); 606893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 607893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project num_pass = 1; 608893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 609a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Loop through passes */ 610893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (pass = 0; pass < num_pass; pass++) 611893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 612a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Loop through image */ 613893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project for (i = 0, rp = image; i < png_ptr->height; i++, rp++) 614893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 615893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_row(png_ptr, *rp); 616893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 617893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 618893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 619893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 620b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_MNG_FEATURES_SUPPORTED 621b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari/* Performs intrapixel differencing */ 622b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraristatic void 623b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripuraripng_do_write_intrapixel(png_row_infop row_info, png_bytep row) 624b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari{ 625b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_debug(1, "in png_do_write_intrapixel"); 626b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 6279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0) 628b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 629b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari int bytes_per_pixel; 630b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 row_width = row_info->width; 631b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (row_info->bit_depth == 8) 632b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 633b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_bytep rp; 634b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 i; 635b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 636b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (row_info->color_type == PNG_COLOR_TYPE_RGB) 637b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bytes_per_pixel = 3; 638b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 639b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 640b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bytes_per_pixel = 4; 641b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 642b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 643b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return; 644b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 645b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 646b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 6479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett *(rp) = (png_byte)(*rp - *(rp + 1)); 6489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett *(rp + 2) = (png_byte)(*(rp + 2) - *(rp + 1)); 649b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 650b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 651b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 652b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_16BIT_SUPPORTED 653b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (row_info->bit_depth == 16) 654b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 655b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_bytep rp; 656b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 i; 657b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 658b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if (row_info->color_type == PNG_COLOR_TYPE_RGB) 659b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bytes_per_pixel = 6; 660b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 661b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA) 662b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari bytes_per_pixel = 8; 663b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 664b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 665b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return; 666b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 667b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel) 668b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 669851c67770f9cebece9c79e914a54c348f539a512Matt Sarett png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1); 670851c67770f9cebece9c79e914a54c348f539a512Matt Sarett png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3); 671851c67770f9cebece9c79e914a54c348f539a512Matt Sarett png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5); 672b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL); 673b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL); 6749b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett *(rp ) = (png_byte)(red >> 8); 6759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett *(rp + 1) = (png_byte)red; 6769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett *(rp + 4) = (png_byte)(blue >> 8); 6779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett *(rp + 5) = (png_byte)blue; 678b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 679b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 6809b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_16BIT */ 681b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 682b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari} 6839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* MNG_FEATURES */ 684b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 685a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Called by user to write a row of image data */ 686893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 687b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_row(png_structrp png_ptr, png_const_bytep row) 688893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* 1.5.6: moved from png_struct to be a local structure: */ 690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_row_info row_info; 691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 692893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 693893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 6945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 695b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug2(1, "in png_write_row (row %u, pass %d)", 6967a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->row_number, png_ptr->pass); 697893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 698a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Initialize transformations and other stuff if first time */ 699893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->row_number == 0 && png_ptr->pass == 0) 700893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 701a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Make sure we wrote the header info */ 7029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0) 703a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_error(png_ptr, 704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "png_write_info was never called before png_write_row"); 705893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 706a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Check for transforms that have been set but were defined out */ 707893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED) 7089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->transformations & PNG_INVERT_MONO) != 0) 709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined"); 710893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 712893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED) 7139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->transformations & PNG_FILLER) != 0) 714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined"); 715893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 7165f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \ 7175f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott defined(PNG_READ_PACKSWAP_SUPPORTED) 7189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->transformations & PNG_PACKSWAP) != 0) 7195f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_warning(png_ptr, 720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik "PNG_WRITE_PACKSWAP_SUPPORTED is not defined"); 721893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 723893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED) 7249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->transformations & PNG_PACK) != 0) 725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined"); 726893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 728893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED) 7299b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->transformations & PNG_SHIFT) != 0) 730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined"); 731893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 733893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED) 7349b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->transformations & PNG_BGR) != 0) 735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined"); 736893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 737b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 738893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED) 7399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0) 740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined"); 741893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 742893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 743893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_start_row(png_ptr); 744893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 745893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 7465f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_INTERLACING_SUPPORTED 747a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* If interlaced and not interested in row, return */ 7489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->interlaced != 0 && 7499b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (png_ptr->transformations & PNG_INTERLACE) != 0) 750893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 751893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project switch (png_ptr->pass) 752893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 753893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 0: 7549b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->row_number & 0x07) != 0) 755893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 756893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_finish_row(png_ptr); 757893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 758893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 759893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 761893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 1: 7629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->row_number & 0x07) != 0 || png_ptr->width < 5) 763893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 764893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_finish_row(png_ptr); 765893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 766893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 767893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 769893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 2: 770893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ((png_ptr->row_number & 0x07) != 4) 771893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 772893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_finish_row(png_ptr); 773893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 774893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 775893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 776b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 777893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 3: 7789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->row_number & 0x03) != 0 || png_ptr->width < 3) 779893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 780893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_finish_row(png_ptr); 781893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 782893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 783893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 785893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 4: 786893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if ((png_ptr->row_number & 0x03) != 2) 787893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 788893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_finish_row(png_ptr); 789893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 790893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 791893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 792b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 793893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 5: 7949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->row_number & 0x01) != 0 || png_ptr->width < 2) 795893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 796893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_finish_row(png_ptr); 797893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 798893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 799893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 801893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 6: 8029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->row_number & 0x01) == 0) 803893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 804893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_finish_row(png_ptr); 805893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 806893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 807893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project break; 808b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 809b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: /* error: ignore it */ 810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 811893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 812893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 813893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 814893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 815a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Set up row info for transformations */ 816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.color_type = png_ptr->color_type; 817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.width = png_ptr->usr_width; 818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.channels = png_ptr->usr_channels; 819b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.bit_depth = png_ptr->usr_bit_depth; 820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.pixel_depth = (png_byte)(row_info.bit_depth * row_info.channels); 821b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width); 822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 823b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug1(3, "row_info->color_type = %d", row_info.color_type); 824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug1(3, "row_info->width = %u", row_info.width); 825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug1(3, "row_info->channels = %d", row_info.channels); 826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug1(3, "row_info->bit_depth = %d", row_info.bit_depth); 827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug1(3, "row_info->pixel_depth = %d", row_info.pixel_depth); 828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes); 829893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 830893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Copy user's row into buffer, leaving room for filter byte. */ 831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes); 832893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 8335f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_INTERLACING_SUPPORTED 834a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Handle interlacing */ 835893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->interlaced && png_ptr->pass < 6 && 8369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (png_ptr->transformations & PNG_INTERLACE) != 0) 837893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass); 839a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* This should always get caught above, but still ... */ 8409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (row_info.width == 0) 841893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 842893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_finish_row(png_ptr); 843893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 844893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 845893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 846893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 847893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED 849a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Handle other transformations */ 8509b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->transformations != 0) 851b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_do_write_transformations(png_ptr, &row_info); 852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 853b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* At this point the row_info pixel depth must match the 'transformed' depth, 855b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * which is also the output depth. 856b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (row_info.pixel_depth != png_ptr->pixel_depth || 8589b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett row_info.pixel_depth != png_ptr->transformed_pixel_depth) 859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "internal write transform logic error"); 860893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 8615f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_MNG_FEATURES_SUPPORTED 862893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Write filter_method 64 (intrapixel differencing) only if 863893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and 864893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 2. Libpng did not write a PNG signature (this filter_method is only 865893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * used in PNG datastreams that are embedded in MNG datastreams) and 866893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 3. The application called png_permit_mng_features with a mask that 867893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * included PNG_FLAG_MNG_FILTER_64 and 868893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 4. The filter_method is 64 and 869893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * 5. The color_type is RGB or RGBA 870893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 8719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 && 872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING)) 873893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 874893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Intrapixel differencing */ 875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_do_write_intrapixel(&row_info, png_ptr->row_buf + 1); 876893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 877893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 878893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Added at libpng-1.5.10 */ 880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED 881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check for out-of-range palette index */ 882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (row_info.color_type == PNG_COLOR_TYPE_PALETTE && 883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->num_palette_max >= 0) 884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_do_check_palette_indexes(png_ptr, &row_info); 885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif 886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 887893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Find a filter if necessary, filter the row and write it out. */ 888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_find_filter(png_ptr, &row_info); 889893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 890893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->write_row_fn != NULL) 891893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project (*(png_ptr->write_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass); 892893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 893893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 8945f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_FLUSH_SUPPORTED 895893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Set the automatic flush interval or 0 to turn flushing off */ 896893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 897b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_flush(png_structrp png_ptr, int nrows) 898893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 8994215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_set_flush"); 9005f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 901893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 902893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 904851c67770f9cebece9c79e914a54c348f539a512Matt Sarett png_ptr->flush_dist = (nrows < 0 ? 0 : nrows); 905893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 906893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 907a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott/* Flush the current output buffers now */ 908893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 909b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_flush(png_structrp png_ptr) 910893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 9114215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_write_flush"); 9125f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 913893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 914893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 916893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* We have already written out all of the data */ 917893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->row_number >= png_ptr->num_rows) 918a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott return; 919893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 920b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH); 921893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->flush_rows = 0; 922893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_flush(png_ptr); 923893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 9249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_FLUSH */ 925893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 926b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Free any memory used in png_ptr struct without freeing the struct itself. */ 927b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 928b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_destroy(png_structrp png_ptr) 929b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 930b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug(1, "in png_write_destroy"); 9315f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 932a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Free any memory zlib uses */ 9339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0) 934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik deflateEnd(&png_ptr->zstream); 935893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 936a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Free our memory. png_free checks NULL for us. */ 937b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list); 938893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_free(png_ptr, png_ptr->row_buf); 9399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->row_buf = NULL; 9405f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_FILTER_SUPPORTED 941893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_free(png_ptr, png_ptr->prev_row); 9429b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, png_ptr->try_row); 9439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_free(png_ptr, png_ptr->tst_row); 9449b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->prev_row = NULL; 9459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->try_row = NULL; 9469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->tst_row = NULL; 947893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 948893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 949b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED 950b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, png_ptr->chunk_list); 9519b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->chunk_list = NULL; 952893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 953893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 954b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The error handling and memory handling information is left intact at this 955b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * point: the jmp_buf may still have to be freed. See png_destroy_png_struct 956b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * for how this happens. 957b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 958b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 959893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 960b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Free all memory used by the write. 961b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for 962b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free 963b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * the passed in info_structs but it would quietly fail to free any of the data 964b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it 965b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * has no png_ptr.) 966b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 967b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 968b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr) 969b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 970b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug(1, "in png_destroy_write_struct"); 971893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 972b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr_ptr != NULL) 973b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = *png_ptr_ptr; 975893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 976b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr != NULL) /* added in libpng 1.6.0 */ 977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_info_struct(png_ptr, info_ptr_ptr); 979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *png_ptr_ptr = NULL; 981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_destroy(png_ptr); 982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_png_struct(png_ptr); 983b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 984b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 985893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 986893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 987893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project/* Allow the application to select one or more row filters to use. */ 988893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 989b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_filter(png_structrp png_ptr, int method, int filters) 990893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 9914215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_set_filter"); 9925f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 993893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 994893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 9965f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_MNG_FEATURES_SUPPORTED 9979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 && 998b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (method == PNG_INTRAPIXEL_DIFFERENCING)) 999b50c217251b086440efcdb273c22f86a06c80cbaChris Craik method = PNG_FILTER_TYPE_BASE; 1000b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1001893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1002893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (method == PNG_FILTER_TYPE_BASE) 1003893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 1004893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project switch (filters & (PNG_ALL_FILTERS | 0x07)) 1005893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 10065f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_FILTER_SUPPORTED 1007893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 5: 1008893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case 6: 1009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 7: png_app_error(png_ptr, "Unknown row filter for method 0"); 1010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* FALL THROUGH */ 10119b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_FILTER */ 1012893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case PNG_FILTER_VALUE_NONE: 1013b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->do_filter = PNG_FILTER_NONE; break; 1014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10155f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_FILTER_SUPPORTED 1016893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case PNG_FILTER_VALUE_SUB: 1017b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->do_filter = PNG_FILTER_SUB; break; 1018b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1019893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case PNG_FILTER_VALUE_UP: 1020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->do_filter = PNG_FILTER_UP; break; 1021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1022893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case PNG_FILTER_VALUE_AVG: 1023b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->do_filter = PNG_FILTER_AVG; break; 1024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1025893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project case PNG_FILTER_VALUE_PAETH: 1026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->do_filter = PNG_FILTER_PAETH; break; 1027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 1029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->do_filter = (png_byte)filters; break; 1030893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#else 1031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 1032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_app_error(png_ptr, "Unknown row filter for method 0"); 10339b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_FILTER */ 1034893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1035893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_WRITE_FILTER_SUPPORTED 1037893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* If we have allocated the row_buf, this means we have already started 1038893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * with the image and we should have allocated all of the filter buffers 1039893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * that have been selected. If prev_row isn't already allocated, then 1040893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * it is too late to start using the filters that need it, since we 1041893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * will be missing the data in the previous row. If an application 1042893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * wants to start and stop using particular filters during compression, 10439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * it should start out with all of the filters, and then remove them 10449b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * or add them back after the start of compression. 10459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 10469b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * NOTE: this is a nasty constraint on the code, because it means that the 10479b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * prev_row buffer must be maintained even if there are currently no 10489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * 'prev_row' requiring filters active. 1049893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 1050893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr->row_buf != NULL) 1051893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 10529b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int num_filters; 10539b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_alloc_size_t buf_size; 1054893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Repeat the checks in png_write_start_row; 1 pixel high or wide 10569b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * images cannot benefit from certain filters. If this isn't done here 10579b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * the check below will fire on 1 pixel high images. 10589b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett */ 10599b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->height == 1) 10609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); 1061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->width == 1) 10639b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH); 1064893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10659b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((filters & (PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH)) != 0 10669b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett && png_ptr->prev_row == NULL) 1067893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 10689b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* This is the error case, however it is benign - the previous row 10699b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * is not available so the filter can't be used. Just warn here. 10709b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett */ 10719b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_app_warning(png_ptr, 10727a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "png_set_filter: UP/AVG/PAETH cannot be added after start"); 10739b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); 1074893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1075893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett num_filters = 0; 1077893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (filters & PNG_FILTER_SUB) 10799b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett num_filters++; 1080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10819b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (filters & PNG_FILTER_UP) 10829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett num_filters++; 1083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 10849b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (filters & PNG_FILTER_AVG) 10859b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett num_filters++; 1086893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10879b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (filters & PNG_FILTER_PAETH) 10889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett num_filters++; 1089893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Allocate needed row buffers if they have not already been 10919b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * allocated. 10929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett */ 10939b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett buf_size = PNG_ROWBYTES(png_ptr->usr_channels * png_ptr->usr_bit_depth, 10949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->width) + 1; 1095893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 10969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->try_row == NULL) 10979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->try_row = png_voidcast(png_bytep, 10987a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_malloc(png_ptr, buf_size)); 1099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 11009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (num_filters > 1) 1101893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project { 11029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_ptr->tst_row == NULL) 11039b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->tst_row = png_voidcast(png_bytep, 11047a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_malloc(png_ptr, buf_size)); 1105893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 1106893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project } 11079b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_ptr->do_filter = (png_byte)filters; 11089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif 1109b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1110b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 11119b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_error(png_ptr, "Unknown custom filter method"); 1112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1113b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 11149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ 1115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Provide floating and fixed point APIs */ 1116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_FLOATING_POINT_SUPPORTED 1117b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 1118b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_filter_heuristics(png_structrp png_ptr, int heuristic_method, 1119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int num_weights, png_const_doublep filter_weights, 1120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_doublep filter_costs) 1121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 11229b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(png_ptr) 11239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(heuristic_method) 11249b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(num_weights) 11259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(filter_weights) 11269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(filter_costs) 1127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* FLOATING_POINT */ 1129893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_FIXED_POINT_SUPPORTED 1131b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 1132b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method, 1133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int num_weights, png_const_fixed_point_p filter_weights, 1134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_fixed_point_p filter_costs) 1135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 11369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(png_ptr) 11379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(heuristic_method) 11389b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(num_weights) 11399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(filter_weights) 11409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_UNUSED(filter_costs) 1141893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* FIXED_POINT */ 11439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_WEIGHTED_FILTER */ 1144893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 11459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED 1146893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 1147b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_compression_level(png_structrp png_ptr, int level) 1148893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 11494215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_set_compression_level"); 11505f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1151893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 1152893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1153b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1154893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->zlib_level = level; 1155893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1156893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1157893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 1158b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_compression_mem_level(png_structrp png_ptr, int mem_level) 1159893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 11604215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_set_compression_mem_level"); 11615f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1162893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 1163893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1164b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1165893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->zlib_mem_level = mem_level; 1166893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1167893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1168893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 1169b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_compression_strategy(png_structrp png_ptr, int strategy) 1170893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 11714215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_set_compression_strategy"); 11725f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1173893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 1174893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1175b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1176b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The flag setting here prevents the libpng dynamic selection of strategy. 1177b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1178893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY; 1179893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->zlib_strategy = strategy; 1180893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1181893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1182b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a 1183b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * smaller value of window_bits if it can do so safely. 1184b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1185893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 1186b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_compression_window_bits(png_structrp png_ptr, int window_bits) 1187893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1188893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 1189893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1190b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 11919b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Prior to 1.6.0 this would warn but then set the window_bits value. This 11929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * meant that negative window bits values could be selected that would cause 1193b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * libpng to write a non-standard PNG file with raw deflate or gzip 1194b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * compressed IDAT or ancillary chunks. Such files can be read and there is 1195b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * no warning on read, so this seems like a very bad idea. 1196b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1197893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (window_bits > 15) 1198b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1199893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); 1200b50c217251b086440efcdb273c22f86a06c80cbaChris Craik window_bits = 15; 1201b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1202b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1203893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project else if (window_bits < 8) 1204b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1205893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); 1206b50c217251b086440efcdb273c22f86a06c80cbaChris Craik window_bits = 8; 1207b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1208b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1209893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->zlib_window_bits = window_bits; 1210893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1211893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1212893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 1213b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_compression_method(png_structrp png_ptr, int method) 1214893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 12154215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_set_compression_method"); 12165f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1217893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 1218893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1219b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1220b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This would produce an invalid PNG file if it worked, but it doesn't and 1221b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * deflate will fault it, so it is harmless to just warn here. 1222b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1223893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (method != 8) 1224893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_warning(png_ptr, "Only compression method 8 is supported by PNG"); 1225b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1226893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->zlib_method = method; 1227893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 12289b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_CUSTOMIZE_COMPRESSION */ 1229893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1230b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* The following were added to libpng-1.5.4 */ 1231b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED 1232893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 1233b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_text_compression_level(png_structrp png_ptr, int level) 1234893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1235b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug(1, "in png_set_text_compression_level"); 1236b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1237b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr == NULL) 1238b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1239b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1240b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_text_level = level; 1241b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1242b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1243b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 1244b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_text_compression_mem_level(png_structrp png_ptr, int mem_level) 1245b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1246b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug(1, "in png_set_text_compression_mem_level"); 1247b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1248b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr == NULL) 1249b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1250b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1251b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_text_mem_level = mem_level; 1252b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1253b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1254b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 1255b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_text_compression_strategy(png_structrp png_ptr, int strategy) 1256b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1257b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug(1, "in png_set_text_compression_strategy"); 1258b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1259b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr == NULL) 1260b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1261b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1262b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_text_strategy = strategy; 1263b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1264b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1265b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a 1266b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * smaller value of window_bits if it can do so safely. 1267b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1268b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 1269b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_text_compression_window_bits(png_structrp png_ptr, int window_bits) 1270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr == NULL) 1272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1273b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (window_bits > 15) 1275b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); 1277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik window_bits = 15; 1278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (window_bits < 8) 1281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); 1283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik window_bits = 8; 1284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_text_window_bits = window_bits; 1287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1289b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 1290b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_text_compression_method(png_structrp png_ptr, int method) 1291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_debug(1, "in png_set_text_compression_method"); 1293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1294893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 1295893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (method != 8) 1298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_warning(png_ptr, "Only compression method 8 is supported by PNG"); 1299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_ptr->zlib_text_method = method; 1301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 13029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ 1303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* end of API added to libpng-1.5.4 */ 1304b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1305b50c217251b086440efcdb273c22f86a06c80cbaChris Craikvoid PNGAPI 1306b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn) 1307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr == NULL) 1309b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return; 1310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1311893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->write_row_fn = write_row_fn; 1312893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1313893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 13145f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED 1315893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 1316b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr 1317b50c217251b086440efcdb273c22f86a06c80cbaChris Craik write_user_transform_fn) 1318893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 13194215dd1533c56e1a89ae6f1d6ea68677fac27fdaThe Android Open Source Project png_debug(1, "in png_set_write_user_transform_fn"); 13205f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1321893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL) 1322893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1323b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1324893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->transformations |= PNG_USER_TRANSFORM; 1325893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_ptr->write_user_transform_fn = write_user_transform_fn; 1326893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1327893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1328893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1329893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 13305f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_INFO_IMAGE_SUPPORTED 1331893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Projectvoid PNGAPI 1332b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_png(png_structrp png_ptr, png_inforp info_ptr, 1333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int transforms, voidp params) 1334893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project{ 1335893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project if (png_ptr == NULL || info_ptr == NULL) 1336893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project return; 1337893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1338b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari if ((info_ptr->valid & PNG_INFO_IDAT) == 0) 1339b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 1340b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "no rows for png_write_image to write"); 1341b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari return; 1342b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1343b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 1344893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Write the file header information. */ 1345893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_info(png_ptr, info_ptr); 1346893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1347893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* ------ these transformations don't touch the info structure ------- */ 1348893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1349a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Invert monochrome pixels */ 13509b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0) 1351b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_INVERT_SUPPORTED 1352a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_invert_mono(png_ptr); 1353b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1354b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported"); 1355893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1356893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1357893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* Shift the pixels up to a legal bit depth and fill in 1358893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project * as appropriate to correctly scale the image. 1359893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project */ 13609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((transforms & PNG_TRANSFORM_SHIFT) != 0) 1361b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_SHIFT_SUPPORTED 13629b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((info_ptr->valid & PNG_INFO_sBIT) != 0) 1363b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_set_shift(png_ptr, &info_ptr->sig_bit); 1364b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1365b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported"); 1366893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1367893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1368a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Pack pixels into bytes */ 13699b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((transforms & PNG_TRANSFORM_PACKING) != 0) 1370b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_PACK_SUPPORTED 1371b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_set_packing(png_ptr); 1372b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1373b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported"); 1374893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1375893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1376a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Swap location of alpha bytes from ARGB to RGBA */ 13779b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0) 1378b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED 1379a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_swap_alpha(png_ptr); 1380b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1381b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported"); 1382893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1383893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1384b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into 1385b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * RGB, note that the code expects the input color type to be G or RGB; no 1386b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari * alpha channel. 1387b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari */ 13889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER| 13899b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0) 1390b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 13915f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#ifdef PNG_WRITE_FILLER_SUPPORTED 13929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0) 1393b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari { 13949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0) 1395b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, 13969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported"); 1397b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1398b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari /* Continue if ignored - this is the pre-1.6.10 behavior */ 1399b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); 1400b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1401b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari 14029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0) 1403b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE); 1404b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1405b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported"); 1406893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1407b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari } 1408893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1409a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Flip BGR pixels to RGB */ 14109b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((transforms & PNG_TRANSFORM_BGR) != 0) 1411b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_BGR_SUPPORTED 1412a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_bgr(png_ptr); 1413b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1414b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported"); 1415893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1416893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1417a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Swap bytes of 16-bit files to most significant byte first */ 14189b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0) 1419b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_SWAP_SUPPORTED 1420a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_swap(png_ptr); 1421b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1422b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported"); 1423893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1424893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 14259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats */ 14269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0) 1427b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_PACKSWAP_SUPPORTED 1428a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott png_set_packswap(png_ptr); 1429b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1430b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported"); 1431893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1432893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 14335f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott /* Invert the alpha channel from opacity to transparency */ 14349b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0) 1435b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED 14365f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott png_set_invert_alpha(png_ptr); 1437b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari#else 1438b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported"); 14395f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott#endif 14405f6bd84e375226bf228fc8ac90318957ec9e1e7fPatrick Scott 1441893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* ----------------------- end of transformations ------------------- */ 1442893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1443a0bb96c34e65378853ee518bac502842d26c2d1aPatrick Scott /* Write the bits */ 1444b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari png_write_image(png_ptr, info_ptr->row_pointers); 1445893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1446893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project /* It is REQUIRED to call this to finish writing the rest of the file */ 1447893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project png_write_end(png_ptr, info_ptr); 1448893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project 1449b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_UNUSED(params) 1450893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project} 1451893912bfc2683463dc3e2c445336752d012563d3The Android Open Source Project#endif 1452b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1453b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1454b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED 1455b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Initialize the write structure - general purpose utility. */ 1456b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1457b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_write_init(png_imagep image) 1458b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1459b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image, 14609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_safe_error, png_safe_warning); 1461b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1462b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_ptr != NULL) 1463b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1464b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_infop info_ptr = png_create_info_struct(png_ptr); 1465b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1466b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (info_ptr != NULL) 1467b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1468b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_controlp control = png_voidcast(png_controlp, 14699b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett png_malloc_warn(png_ptr, (sizeof *control))); 1470b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1471b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (control != NULL) 1472b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1473b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(control, 0, (sizeof *control)); 1474b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1475b50c217251b086440efcdb273c22f86a06c80cbaChris Craik control->png_ptr = png_ptr; 1476b50c217251b086440efcdb273c22f86a06c80cbaChris Craik control->info_ptr = info_ptr; 1477b50c217251b086440efcdb273c22f86a06c80cbaChris Craik control->for_write = 1; 1478b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1479b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque = control; 1480b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1481b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1482b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1483b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Error clean up */ 1484b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_info_struct(png_ptr, &info_ptr); 1485b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1486b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1487b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_destroy_write_struct(&png_ptr, NULL); 1488b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1489b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1490b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, "png_image_write_: out of memory"); 1491b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1492b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1493b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Arguments to png_image_write_main: */ 1494b50c217251b086440efcdb273c22f86a06c80cbaChris Craiktypedef struct 1495b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1496b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Arguments: */ 1497b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image; 1498b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_voidp buffer; 1499b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_int_32 row_stride; 1500b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_voidp colormap; 1501b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int convert_to_8bit; 1502b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Local variables: */ 1503b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_voidp first_row; 1504b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t row_bytes; 1505b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_voidp local_row; 1506114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett /* Byte count for memory writing */ 1507114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_bytep memory; 1508114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_alloc_size_t memory_bytes; /* not used for STDIO */ 1509114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_alloc_size_t output_bytes; /* running total */ 1510b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} png_image_write_control; 1511b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1512b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to 1513b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * do any necessary byte swapping. The component order is defined by the 1514b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * png_image format value. 1515b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1516b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1517b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_image_16bit(png_voidp argument) 1518b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1519b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_write_control *display = png_voidcast(png_image_write_control*, 15209b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett argument); 1521b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = display->image; 1522b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = image->opaque->png_ptr; 1523b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1524b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, 15259b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett display->first_row); 1526b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); 1527b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16p row_end; 1528851c67770f9cebece9c79e914a54c348f539a512Matt Sarett const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; 1529b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int aindex = 0; 1530b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y = image->height; 1531b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 15329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0) 1533b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 15349b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED 15359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0) 15369b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 15379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett aindex = -1; 15389b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett ++input_row; /* To point to the first component */ 15399b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett ++output_row; 15409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 1541b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari else 1542851c67770f9cebece9c79e914a54c348f539a512Matt Sarett aindex = channels; 15439b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# else 1544851c67770f9cebece9c79e914a54c348f539a512Matt Sarett aindex = channels; 15459b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 1546b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1547b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1548b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1549b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "png_write_image: internal call error"); 1550b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1551b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Work out the output row end and count over this, note that the increment 1552b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * above to 'row' means that row_end can actually be beyond the end of the 1553b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * row; this is correct. 1554b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1555b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_end = output_row + image->width * (channels+1); 1556b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1557851c67770f9cebece9c79e914a54c348f539a512Matt Sarett while (y-- > 0) 1558b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1559b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p in_ptr = input_row; 1560b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16p out_ptr = output_row; 1561b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1562b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (out_ptr < row_end) 1563b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1564b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_uint_16 alpha = in_ptr[aindex]; 1565b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 reciprocal = 0; 1566b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int c; 1567b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1568b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out_ptr[aindex] = alpha; 1569b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1570b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Calculate a reciprocal. The correct calculation is simply 1571b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * component/alpha*65535 << 15. (I.e. 15 bits of precision); this 1572b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * allows correct rounding by adding .5 before the shift. 'reciprocal' 1573b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is only initialized when required. 1574b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1575b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha > 0 && alpha < 65535) 1576b50c217251b086440efcdb273c22f86a06c80cbaChris Craik reciprocal = ((0xffff<<15)+(alpha>>1))/alpha; 1577b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1578851c67770f9cebece9c79e914a54c348f539a512Matt Sarett c = channels; 1579b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do /* always at least one channel */ 1580b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1581b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16 component = *in_ptr++; 1582b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1583b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following gives 65535 for an alpha of 0, which is fine, 1584b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * otherwise if 0/0 is represented as some other value there is more 1585b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * likely to be a discontinuity which will probably damage 1586b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * compression when moving from a fully transparent area to a 1587b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * nearly transparent one. (The assumption here is that opaque 1588b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * areas tend not to be 0 intensity.) 1589b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1590b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (component >= alpha) 1591b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component = 65535; 1592b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1593b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* component<alpha, so component/alpha is less than one and 1594b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * component*reciprocal is less than 2^31. 1595b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1596b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (component > 0 && alpha < 65535) 1597b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1598b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 calc = component * reciprocal; 1599b50c217251b086440efcdb273c22f86a06c80cbaChris Craik calc += 16384; /* round to nearest */ 1600b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component = (png_uint_16)(calc >> 15); 1601b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1602b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1603b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *out_ptr++ = component; 1604b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1605b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (--c > 0); 1606b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1607b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Skip to next component (skip the intervening alpha channel) */ 1608b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++in_ptr; 1609b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++out_ptr; 1610b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1611b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1612b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row)); 1613851c67770f9cebece9c79e914a54c348f539a512Matt Sarett input_row += display->row_bytes/(sizeof (png_uint_16)); 1614b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1615b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1616b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1617b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1618b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1619b50c217251b086440efcdb273c22f86a06c80cbaChris Craik/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel 1620b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is present it must be removed from the components, the components are then 1621b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * written in sRGB encoding. No components are added or removed. 1622b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1623b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * Calculate an alpha reciprocal to reverse pre-multiplication. As above the 1624b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * calculation can be done to 15 bits of accuracy; however, the output needs to 1625b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be scaled in the range 0..255*65535, so include that scaling here. 1626b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 16279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) 1628b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1629b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic png_byte 1630b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_unpremultiply(png_uint_32 component, png_uint_32 alpha, 16317a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_uint_32 reciprocal/*from the above macro*/) 1632b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1633b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0 1634b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is represented as some other value there is more likely to be a 1635b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * discontinuity which will probably damage compression when moving from a 1636b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * fully transparent area to a nearly transparent one. (The assumption here 1637b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is that opaque areas tend not to be 0 intensity.) 1638b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 1639b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * There is a rounding problem here; if alpha is less than 128 it will end up 1640b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * as 0 when scaled to 8 bits. To avoid introducing spurious colors into the 1641b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * output change for this too. 1642b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1643b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (component >= alpha || alpha < 128) 1644b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 255; 1645b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1646b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* component<alpha, so component/alpha is less than one and 1647b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * component*reciprocal is less than 2^31. 1648b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1649b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (component > 0) 1650b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1651b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The test is that alpha/257 (rounded) is less than 255, the first value 1652b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * that becomes 255 is 65407. 1653b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore, 1654b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * be exact!) [Could also test reciprocal != 0] 1655b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1656b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alpha < 65407) 1657b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1658b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component *= reciprocal; 1659b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component += 64; /* round to nearest */ 1660b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component >>= 7; 1661b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1662b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1663b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1664b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component *= 255; 1665b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1666b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Convert the component to sRGB. */ 1667b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return (png_byte)PNG_sRGB_FROM_LINEAR(component); 1668b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1669b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1670b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1671b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 1672b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1673b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1674b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1675b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_write_image_8bit(png_voidp argument) 1676b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1677b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_write_control *display = png_voidcast(png_image_write_control*, 16789b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett argument); 1679b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = display->image; 1680b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = image->opaque->png_ptr; 1681b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1682b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, 16839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett display->first_row); 1684b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep output_row = png_voidcast(png_bytep, display->local_row); 1685b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y = image->height; 1686851c67770f9cebece9c79e914a54c348f539a512Matt Sarett const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; 1687b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 16889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0) 1689b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1690b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep row_end; 1691b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int aindex; 1692b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 16939b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED 16949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0) 16959b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett { 16969b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett aindex = -1; 16979b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett ++input_row; /* To point to the first component */ 16989b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett ++output_row; 16999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett } 1700b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 17019b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else 17029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 1703851c67770f9cebece9c79e914a54c348f539a512Matt Sarett aindex = channels; 1704b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1705b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Use row_end in place of a loop counter: */ 1706b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_end = output_row + image->width * (channels+1); 1707b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1708851c67770f9cebece9c79e914a54c348f539a512Matt Sarett while (y-- > 0) 1709b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1710b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p in_ptr = input_row; 1711b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep out_ptr = output_row; 1712b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1713b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (out_ptr < row_end) 1714b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1715b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16 alpha = in_ptr[aindex]; 1716b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte alphabyte = (png_byte)PNG_DIV257(alpha); 1717b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 reciprocal = 0; 1718b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int c; 1719b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1720b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Scale and write the alpha channel. */ 1721b50c217251b086440efcdb273c22f86a06c80cbaChris Craik out_ptr[aindex] = alphabyte; 1722b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1723b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alphabyte > 0 && alphabyte < 255) 1724b50c217251b086440efcdb273c22f86a06c80cbaChris Craik reciprocal = UNP_RECIPROCAL(alpha); 1725b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1726851c67770f9cebece9c79e914a54c348f539a512Matt Sarett c = channels; 1727b50c217251b086440efcdb273c22f86a06c80cbaChris Craik do /* always at least one channel */ 1728b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal); 1729b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (--c > 0); 1730b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1731b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Skip to next component (skip the intervening alpha channel) */ 1732b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++in_ptr; 1733b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ++out_ptr; 1734b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } /* while out_ptr < row_end */ 1735b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1736b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_row(png_ptr, png_voidcast(png_const_bytep, 17379b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett display->local_row)); 1738851c67770f9cebece9c79e914a54c348f539a512Matt Sarett input_row += display->row_bytes/(sizeof (png_uint_16)); 1739b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } /* while y */ 1740b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1741b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1742b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1743b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1744b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* No alpha channel, so the row_end really is the end of the row and it 1745b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * is sufficient to loop over the components one by one. 1746b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1747b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep row_end = output_row + image->width * channels; 1748b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1749851c67770f9cebece9c79e914a54c348f539a512Matt Sarett while (y-- > 0) 1750b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1751b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p in_ptr = input_row; 1752b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep out_ptr = output_row; 1753b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1754b50c217251b086440efcdb273c22f86a06c80cbaChris Craik while (out_ptr < row_end) 1755b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1756b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 component = *in_ptr++; 1757b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1758b50c217251b086440efcdb273c22f86a06c80cbaChris Craik component *= 255; 1759b50c217251b086440efcdb273c22f86a06c80cbaChris Craik *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component); 1760b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1761b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1762b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_row(png_ptr, output_row); 1763851c67770f9cebece9c79e914a54c348f539a512Matt Sarett input_row += display->row_bytes/(sizeof (png_uint_16)); 1764b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1765b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1766b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1767b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 1768b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1769b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1770b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic void 1771b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_set_PLTE(png_image_write_control *display) 1772b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1773b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_imagep image = display->image; 1774b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const void *cmap = display->colormap; 1775b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const int entries = image->colormap_entries > 256 ? 256 : 17769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (int)image->colormap_entries; 1777b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1778b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* NOTE: the caller must check for cmap != NULL and entries != 0 */ 1779b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const png_uint_32 format = image->format; 1780851c67770f9cebece9c79e914a54c348f539a512Matt Sarett const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); 1781b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 17829b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\ 1783b478e66e7c2621eef5f465e4629ce642db00716bSireesh Tripurari defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED) 1784b50c217251b086440efcdb273c22f86a06c80cbaChris Craik const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && 17859b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (format & PNG_FORMAT_FLAG_ALPHA) != 0; 17869b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# else 1787b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define afirst 0 17889b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 1789b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 17909b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef PNG_FORMAT_BGR_SUPPORTED 17919b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; 17929b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# else 1793b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# define bgr 0 17949b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 1795b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1796b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int i, num_trans; 1797b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_color palette[256]; 1798b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte tRNS[256]; 1799b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1800b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(tRNS, 255, (sizeof tRNS)); 1801b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(palette, 0, (sizeof palette)); 1802b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1803b50c217251b086440efcdb273c22f86a06c80cbaChris Craik for (i=num_trans=0; i<entries; ++i) 1804b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1805b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This gets automatically converted to sRGB with reversal of the 1806b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * pre-multiplication if the color-map has an alpha channel. 1807b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 18089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((format & PNG_FORMAT_FLAG_LINEAR) != 0) 1809b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1810b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap); 1811b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1812851c67770f9cebece9c79e914a54c348f539a512Matt Sarett entry += i * channels; 1813b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 18149b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((channels & 1) != 0) /* no alpha */ 1815b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1816b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (channels >= 3) /* RGB */ 1817b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1818b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 * 18199b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett entry[(2 ^ bgr)]); 1820b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 * 18219b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett entry[1]); 1822b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 * 18239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett entry[bgr]); 1824b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1825b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1826b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* Gray */ 1827b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].blue = palette[i].red = palette[i].green = 1828b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry); 1829b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1830b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1831b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* alpha */ 1832b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1833b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_16 alpha = entry[afirst ? 0 : channels-1]; 1834b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_byte alphabyte = (png_byte)PNG_DIV257(alpha); 1835b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 reciprocal = 0; 1836b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1837b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Calculate a reciprocal, as in the png_write_image_8bit code above 1838b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this is designed to produce a value scaled to 255*65535 when 1839b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * divided by 128 (i.e. asr 7). 1840b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 1841b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alphabyte > 0 && alphabyte < 255) 1842b50c217251b086440efcdb273c22f86a06c80cbaChris Craik reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha; 1843b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1844b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tRNS[i] = alphabyte; 1845b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (alphabyte < 255) 1846b50c217251b086440efcdb273c22f86a06c80cbaChris Craik num_trans = i+1; 1847b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1848b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (channels >= 3) /* RGB */ 1849b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1850b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)], 18517a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis alpha, reciprocal); 1852b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].green = png_unpremultiply(entry[afirst + 1], alpha, 18537a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis reciprocal); 1854b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha, 18557a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis reciprocal); 1856b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1857b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1858b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* gray */ 1859b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].blue = palette[i].red = palette[i].green = 18607a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_unpremultiply(entry[afirst], alpha, reciprocal); 1861b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1862b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1863b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1864b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else /* Color-map has sRGB values */ 1865b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1866b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep entry = png_voidcast(png_const_bytep, cmap); 1867b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1868851c67770f9cebece9c79e914a54c348f539a512Matt Sarett entry += i * channels; 1869b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1870b50c217251b086440efcdb273c22f86a06c80cbaChris Craik switch (channels) 1871b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1872b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 4: 1873b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tRNS[i] = entry[afirst ? 0 : 3]; 1874b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (tRNS[i] < 255) 1875b50c217251b086440efcdb273c22f86a06c80cbaChris Craik num_trans = i+1; 1876b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* FALL THROUGH */ 1877b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 3: 1878b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].blue = entry[afirst + (2 ^ bgr)]; 1879b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].green = entry[afirst + 1]; 1880b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].red = entry[afirst + bgr]; 1881b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1882b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1883b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 2: 1884b50c217251b086440efcdb273c22f86a06c80cbaChris Craik tRNS[i] = entry[1 ^ afirst]; 1885b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (tRNS[i] < 255) 1886b50c217251b086440efcdb273c22f86a06c80cbaChris Craik num_trans = i+1; 1887b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* FALL THROUGH */ 1888b50c217251b086440efcdb273c22f86a06c80cbaChris Craik case 1: 1889b50c217251b086440efcdb273c22f86a06c80cbaChris Craik palette[i].blue = palette[i].red = palette[i].green = 1890b50c217251b086440efcdb273c22f86a06c80cbaChris Craik entry[afirst]; 1891b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1892b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1893b50c217251b086440efcdb273c22f86a06c80cbaChris Craik default: 1894b50c217251b086440efcdb273c22f86a06c80cbaChris Craik break; 1895b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1896b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1897b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1898b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 18999b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef afirst 1900b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# undef afirst 19019b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 19029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef bgr 1903b50c217251b086440efcdb273c22f86a06c80cbaChris Craik# undef bgr 19049b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 1905b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1906b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette, 19077a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis entries); 1908b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1909b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (num_trans > 0) 1910b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS, 19117a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis num_trans, NULL); 1912b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1913851c67770f9cebece9c79e914a54c348f539a512Matt Sarett image->colormap_entries = entries; 1914b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 1915b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1916b50c217251b086440efcdb273c22f86a06c80cbaChris Craikstatic int 1917b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_write_main(png_voidp argument) 1918b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 1919b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_write_control *display = png_voidcast(png_image_write_control*, 19207a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis argument); 1921b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_imagep image = display->image; 1922b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_structrp png_ptr = image->opaque->png_ptr; 1923b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_inforp info_ptr = image->opaque->info_ptr; 1924b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 format = image->format; 1925b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 19269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett /* The following four ints are actually booleans */ 19279b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int colormap = (format & PNG_FORMAT_FLAG_COLORMAP); 19289b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */ 19299b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA); 19309b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett int write_16bit = linear && !colormap && (display->convert_to_8bit == 0); 1931b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 19329b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef PNG_BENIGN_ERRORS_SUPPORTED 1933b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Make sure we error out on any bad situation */ 1934b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_benign_errors(png_ptr, 0/*error*/); 19359b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 1936b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1937114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett /* Default the 'row_stride' parameter if required, also check the row stride 1938114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett * and total image size to ensure that they are within the system limits. 1939114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett */ 1940114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett { 1941114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett const unsigned int channels = PNG_IMAGE_PIXEL_CHANNELS(image->format); 1942114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 1943851c67770f9cebece9c79e914a54c348f539a512Matt Sarett if (image->width <= 0x7FFFFFFFU/channels) /* no overflow */ 1944114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett { 1945114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_uint_32 check; 1946114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett const png_uint_32 png_row_stride = image->width * channels; 1947114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 1948114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (display->row_stride == 0) 1949114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett display->row_stride = (png_int_32)/*SAFE*/png_row_stride; 1950114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 1951114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (display->row_stride < 0) 1952851c67770f9cebece9c79e914a54c348f539a512Matt Sarett check = -display->row_stride; 1953114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 1954114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett else 1955851c67770f9cebece9c79e914a54c348f539a512Matt Sarett check = display->row_stride; 1956114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 1957114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (check >= png_row_stride) 1958114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett { 1959114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett /* Now check for overflow of the image buffer calculation; this 1960114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett * limits the whole image size to 32 bits for API compatibility with 1961114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett * the current, 32-bit, PNG_IMAGE_BUFFER_SIZE macro. 1962114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett */ 1963851c67770f9cebece9c79e914a54c348f539a512Matt Sarett if (image->height > 0xFFFFFFFF/png_row_stride) 1964114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_error(image->opaque->png_ptr, "memory image too large"); 1965114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett } 1966114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 1967114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett else 1968114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_error(image->opaque->png_ptr, "supplied row stride too small"); 1969114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett } 1970114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 1971114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett else 1972114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_error(image->opaque->png_ptr, "image row stride too large"); 1973114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett } 1974b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1975b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Set the required transforms then write the rows in the correct order. */ 19769b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0) 1977b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1978b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (display->colormap != NULL && image->colormap_entries > 0) 1979b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 1980b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 entries = image->colormap_entries; 1981b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1982b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_IHDR(png_ptr, info_ptr, image->width, image->height, 19837a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)), 19847a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE, 19857a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 1986b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1987b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_set_PLTE(display); 1988b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1989b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1990b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1991b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(image->opaque->png_ptr, 19927a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "no color-map for color-mapped image"); 1993b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 1994b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 1995b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 1996b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_IHDR(png_ptr, info_ptr, image->width, image->height, 19977a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis write_16bit ? 16 : 8, 19987a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) + 19997a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0), 20007a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); 2001b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2002b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Counter-intuitively the data transformations must be called *after* 2003b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * png_write_info, not before as in the read code, but the 'set' functions 2004b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * must still be called before. Just set the color space information, never 2005b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * write an interlaced image. 2006b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2007b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20089b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (write_16bit != 0) 2009b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2010b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */ 2011b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR); 2012b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20139b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0) 2014b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_cHRM_fixed(png_ptr, info_ptr, 20157a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* color x y */ 20167a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* white */ 31270, 32900, 20177a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* red */ 64000, 33000, 20187a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* green */ 30000, 60000, 20197a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis /* blue */ 15000, 6000 2020b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ); 2021b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2022b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20239b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett else if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0) 2024b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL); 2025b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2026b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit 2027b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * space must still be gamma encoded. 2028b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2029b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2030b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE); 2031b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2032b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Write the file header. */ 2033b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_info(png_ptr, info_ptr); 2034b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2035b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Now set up the data transformations (*after* the header is written), 2036b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * remove the handled transformations from the 'format' flags for checking. 2037b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * 20389b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett * First check for a little endian system if writing 16-bit files. 2039b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 20409b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (write_16bit != 0) 2041b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2042b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_CONST png_uint_16 le = 0x0001; 2043b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20449b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((*(png_const_bytep) & le) != 0) 2045b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_swap(png_ptr); 2046b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2047b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20489b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED 20499b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((format & PNG_FORMAT_FLAG_BGR) != 0) 2050b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 20519b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0) 2052b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_bgr(png_ptr); 2053b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format &= ~PNG_FORMAT_FLAG_BGR; 2054b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 20559b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 2056b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20579b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED 20589b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) 2059b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 20609b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0) 2061b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_swap_alpha(png_ptr); 2062b50c217251b086440efcdb273c22f86a06c80cbaChris Craik format &= ~PNG_FORMAT_FLAG_AFIRST; 2063b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 20649b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 2065b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2066b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* If there are 16 or fewer color-map entries we wrote a lower bit depth 2067b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * above, but the application data is still byte packed. 2068b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 20699b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (colormap != 0 && image->colormap_entries <= 16) 2070b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_packing(png_ptr); 2071b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2072b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* That should have handled all (both) the transforms. */ 2073b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR | 2074b50c217251b086440efcdb273c22f86a06c80cbaChris Craik PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0) 2075b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_error(png_ptr, "png_write_image: unsupported transformation"); 2076b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2077b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2078b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep row = png_voidcast(png_const_bytep, display->buffer); 2079b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t row_bytes = display->row_stride; 2080b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 20819b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (linear != 0) 2082b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row_bytes *= (sizeof (png_uint_16)); 2083b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2084b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (row_bytes < 0) 2085b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row += (image->height-1) * (-row_bytes); 2086b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2087b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->first_row = row; 2088b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->row_bytes = row_bytes; 2089b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2090b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2091b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Apply 'fast' options if the flag is set. */ 2092b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0) 2093b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2094b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS); 2095b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* NOTE: determined by experiment using pngstest, this reflects some 2096b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * balance between the time to write the image once and the time to read 2097b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * it about 50 times. The speed-up in pngstest was about 10-20% of the 2098b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * total (user) time on a heavily loaded system. 2099b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 21009b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED 2101b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_set_compression_level(png_ptr, 3); 21029b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett# endif 2103b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2104b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2105b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Check for the cases that currently require a pre-transform on the row 2106b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * before it is written. This only applies when the input is 16-bit and 2107b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * either there is an alpha channel or it is converted to 8-bit. 2108b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 21099b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if ((linear != 0 && alpha != 0 ) || 21109b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett (colormap == 0 && display->convert_to_8bit != 0)) 2111b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2112b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr, 21137a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_get_rowbytes(png_ptr, info_ptr))); 2114b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result; 2115b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2116b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->local_row = row; 21179b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (write_16bit != 0) 2118b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = png_safe_execute(image, png_write_image_16bit, display); 2119b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2120b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = png_safe_execute(image, png_write_image_8bit, display); 2121b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display->local_row = NULL; 2122b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2123b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_free(png_ptr, row); 2124b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2125b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Skip the 'write_end' on error: */ 21269b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (result == 0) 2127b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 2128b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2129b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2130b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Otherwise this is the case where the input is in a format currently 2131b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * supported by the rest of the libpng write code; call it directly. 2132b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2133b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2134b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2135b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_const_bytep row = png_voidcast(png_const_bytep, display->first_row); 2136b50c217251b086440efcdb273c22f86a06c80cbaChris Craik ptrdiff_t row_bytes = display->row_bytes; 2137b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_uint_32 y = image->height; 2138b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2139851c67770f9cebece9c79e914a54c348f539a512Matt Sarett while (y-- > 0) 2140b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2141b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_row(png_ptr, row); 2142b50c217251b086440efcdb273c22f86a06c80cbaChris Craik row += row_bytes; 2143b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2144b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2145b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2146b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_write_end(png_ptr, info_ptr); 2147b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 2148b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2149b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2150114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2151114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarettstatic void (PNGCBAPI 2152114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarettimage_memory_write)(png_structp png_ptr, png_bytep/*const*/ data, 21537a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_size_t size) 2154114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett{ 2155114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_image_write_control *display = png_voidcast(png_image_write_control*, 21567a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_ptr->io_ptr/*backdoor: png_get_io_ptr(png_ptr)*/); 2157114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett const png_alloc_size_t ob = display->output_bytes; 2158114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2159114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett /* Check for overflow; this should never happen: */ 2160114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (size <= ((png_alloc_size_t)-1) - ob) 2161114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett { 2162114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett /* I don't think libpng ever does this, but just in case: */ 2163114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (size > 0) 2164114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett { 2165114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (display->memory_bytes >= ob+size) /* writing */ 2166114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett memcpy(display->memory+ob, data, size); 2167114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2168114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett /* Always update the size: */ 2169114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett display->output_bytes = ob+size; 2170114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett } 2171114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett } 2172114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2173114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett else 2174114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_error(png_ptr, "png_image_write_to_memory: PNG too big"); 2175114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett} 2176114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2177114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarettstatic void (PNGCBAPI 2178114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarettimage_memory_flush)(png_structp png_ptr) 2179114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett{ 2180114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett PNG_UNUSED(png_ptr) 2181114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett} 2182114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2183114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarettstatic int 2184114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarettpng_image_write_memory(png_voidp argument) 2185114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett{ 2186114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_image_write_control *display = png_voidcast(png_image_write_control*, 21877a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis argument); 2188114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2189114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett /* The rest of the memory-specific init and write_main in an error protected 2190114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett * environment. This case needs to use callbacks for the write operations 2191114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett * since libpng has no built in support for writing to memory. 2192114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett */ 2193114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_set_write_fn(display->image->opaque->png_ptr, display/*io_ptr*/, 21947a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis image_memory_write, image_memory_flush); 2195114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2196114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett return png_image_write_main(display); 2197114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett} 2198114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2199114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarettint PNGAPI 2200114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarettpng_image_write_to_memory(png_imagep image, void *memory, 22017a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis png_alloc_size_t * PNG_RESTRICT memory_bytes, int convert_to_8bit, 22027a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis const void *buffer, png_int_32 row_stride, const void *colormap) 2203114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett{ 2204114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett /* Write the image to the given buffer, or count the bytes if it is NULL */ 2205114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (image != NULL && image->version == PNG_IMAGE_VERSION) 2206114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett { 2207114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (memory_bytes != NULL && buffer != NULL) 2208114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett { 2209114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett /* This is to give the caller an easier error detection in the NULL 2210114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett * case and guard against uninitialized variable problems: 2211114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett */ 2212114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (memory == NULL) 2213114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett *memory_bytes = 0; 2214114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2215114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (png_image_write_init(image) != 0) 2216114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett { 2217114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_image_write_control display; 2218114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett int result; 2219114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2220114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett memset(&display, 0, (sizeof display)); 2221114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett display.image = image; 2222114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett display.buffer = buffer; 2223114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett display.row_stride = row_stride; 2224114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett display.colormap = colormap; 2225114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett display.convert_to_8bit = convert_to_8bit; 2226114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett display.memory = png_voidcast(png_bytep, memory); 2227114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett display.memory_bytes = *memory_bytes; 2228114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett display.output_bytes = 0; 2229114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2230114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett result = png_safe_execute(image, png_image_write_memory, &display); 2231114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett png_image_free(image); 2232114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2233114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett /* write_memory returns true even if we ran out of buffer. */ 2234114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (result) 2235114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett { 2236114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett /* On out-of-buffer this function returns '0' but still updates 2237114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett * memory_bytes: 2238114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett */ 2239114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (memory != NULL && display.output_bytes > *memory_bytes) 2240114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett result = 0; 2241114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2242114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett *memory_bytes = display.output_bytes; 2243114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett } 2244114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2245114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett return result; 2246114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett } 2247114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2248114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett else 2249114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett return 0; 2250114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett } 2251114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2252114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett else 2253114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett return png_image_error(image, 22547a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "png_image_write_to_memory: invalid argument"); 2255114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett } 2256114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2257114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett else if (image != NULL) 2258114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett return png_image_error(image, 22597a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "png_image_write_to_memory: incorrect PNG_IMAGE_VERSION"); 2260114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2261114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett else 2262114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett return 0; 2263114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett} 2264114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett 2265114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett#ifdef PNG_SIMPLIFIED_WRITE_STDIO_SUPPORTED 2266b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint PNGAPI 2267b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit, 22687a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis const void *buffer, png_int_32 row_stride, const void *colormap) 2269b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2270b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Write the image to the given (FILE*). */ 2271b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image != NULL && image->version == PNG_IMAGE_VERSION) 2272b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2273114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (file != NULL && buffer != NULL) 2274b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 22759b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett if (png_image_write_init(image) != 0) 2276b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2277b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_write_control display; 2278b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int result; 2279b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2280b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* This is slightly evil, but png_init_io doesn't do anything other 2281b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * than this and we haven't changed the standard IO functions so 2282b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * this saves a 'safe' function. 2283b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2284b50c217251b086440efcdb273c22f86a06c80cbaChris Craik image->opaque->png_ptr->io_ptr = file; 2285b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2286b50c217251b086440efcdb273c22f86a06c80cbaChris Craik memset(&display, 0, (sizeof display)); 2287b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display.image = image; 2288b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display.buffer = buffer; 2289b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display.row_stride = row_stride; 2290b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display.colormap = colormap; 2291b50c217251b086440efcdb273c22f86a06c80cbaChris Craik display.convert_to_8bit = convert_to_8bit; 2292b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2293b50c217251b086440efcdb273c22f86a06c80cbaChris Craik result = png_safe_execute(image, png_image_write_main, &display); 2294b50c217251b086440efcdb273c22f86a06c80cbaChris Craik png_image_free(image); 2295b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return result; 2296b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2297b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2298b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2299b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 2300b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2301b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2302b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2303b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 23047a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "png_image_write_to_stdio: invalid argument"); 2305b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2306b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2307b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (image != NULL) 2308b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 23097a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION"); 2310b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2311b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2312b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 2313b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2314b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2315b50c217251b086440efcdb273c22f86a06c80cbaChris Craikint PNGAPI 2316b50c217251b086440efcdb273c22f86a06c80cbaChris Craikpng_image_write_to_file(png_imagep image, const char *file_name, 23177a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis int convert_to_8bit, const void *buffer, png_int_32 row_stride, 23187a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis const void *colormap) 2319b50c217251b086440efcdb273c22f86a06c80cbaChris Craik{ 2320b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Write the image to the named file. */ 2321b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (image != NULL && image->version == PNG_IMAGE_VERSION) 2322b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2323114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett if (file_name != NULL && buffer != NULL) 2324b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2325b50c217251b086440efcdb273c22f86a06c80cbaChris Craik FILE *fp = fopen(file_name, "wb"); 2326b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2327b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fp != NULL) 2328b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2329b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer, 23307a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis row_stride, colormap) != 0) 2331b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2332b50c217251b086440efcdb273c22f86a06c80cbaChris Craik int error; /* from fflush/fclose */ 2333b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2334b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Make sure the file is flushed correctly. */ 2335b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fflush(fp) == 0 && ferror(fp) == 0) 2336b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2337b50c217251b086440efcdb273c22f86a06c80cbaChris Craik if (fclose(fp) == 0) 2338b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 1; 2339b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2340b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = errno; /* from fclose */ 2341b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2342b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2343b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2344b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2345b50c217251b086440efcdb273c22f86a06c80cbaChris Craik error = errno; /* from fflush or ferror */ 2346b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)fclose(fp); 2347b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2348b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2349b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)remove(file_name); 2350b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* The image has already been cleaned up; this is just used to 2351b50c217251b086440efcdb273c22f86a06c80cbaChris Craik * set the error (because the original write succeeded). 2352b50c217251b086440efcdb273c22f86a06c80cbaChris Craik */ 2353b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, strerror(error)); 2354b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2355b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2356b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2357b50c217251b086440efcdb273c22f86a06c80cbaChris Craik { 2358b50c217251b086440efcdb273c22f86a06c80cbaChris Craik /* Clean up: just the opened file. */ 2359b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)fclose(fp); 2360b50c217251b086440efcdb273c22f86a06c80cbaChris Craik (void)remove(file_name); 2361b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 2362b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2363b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2364b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2365b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2366b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, strerror(errno)); 2367b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2368b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2369b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2370b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 23717a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "png_image_write_to_file: invalid argument"); 2372b50c217251b086440efcdb273c22f86a06c80cbaChris Craik } 2373b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2374b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else if (image != NULL) 2375b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return png_image_error(image, 23767a055fdaacbcb54d3606638017fb3381f05d96acAlex Naidis "png_image_write_to_file: incorrect PNG_IMAGE_VERSION"); 2377b50c217251b086440efcdb273c22f86a06c80cbaChris Craik 2378b50c217251b086440efcdb273c22f86a06c80cbaChris Craik else 2379b50c217251b086440efcdb273c22f86a06c80cbaChris Craik return 0; 2380b50c217251b086440efcdb273c22f86a06c80cbaChris Craik} 2381114668651129dc978b9710d0f0ad107ee5ee3281Matt Sarett#endif /* SIMPLIFIED_WRITE_STDIO */ 2382b50c217251b086440efcdb273c22f86a06c80cbaChris Craik#endif /* SIMPLIFIED_WRITE */ 23839b1fe63dcc7ba076b9730b7bfa031cc0dbc25561Matt Sarett#endif /* WRITE */ 2384