15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* pngwutil.c - utilities to write a PNG file 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Last changed in libpng 1.2.43 [February 25, 2010] 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright (c) 1998-2010 Glenn Randers-Pehrson 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * This code is released under the libpng license. 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * For conditions of distribution and use, see the disclaimer 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and license in png.h 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PNG_INTERNAL 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PNG_NO_PEDANTIC_WARNINGS 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "png.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_SUPPORTED 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Place a 32-bit number into a buffer in PNG byte order. We work 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * with unsigned numbers for convenience, although one supported 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ancillary chunk uses signed (two's complement) numbers. 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_save_uint_32(png_bytep buf, png_uint_32 i) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = (png_byte)((i >> 24) & 0xff); 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[1] = (png_byte)((i >> 16) & 0xff); 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[2] = (png_byte)((i >> 8) & 0xff); 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[3] = (png_byte)(i & 0xff); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* The png_save_int_32 function assumes integers are stored in two's 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * complement format. If this isn't the case, then this routine needs to 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * be modified to write data in two's complement format. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_save_int_32(png_bytep buf, png_int_32 i) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = (png_byte)((i >> 24) & 0xff); 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[1] = (png_byte)((i >> 16) & 0xff); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[2] = (png_byte)((i >> 8) & 0xff); 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[3] = (png_byte)(i & 0xff); 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Place a 16-bit number into a buffer in PNG byte order. 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The parameter is declared unsigned int, not png_uint_16, 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * just to avoid potential problems on pre-ANSI C compilers. 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_save_uint_16(png_bytep buf, unsigned int i) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = (png_byte)((i >> 8) & 0xff); 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[1] = (png_byte)(i & 0xff); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Simple function to write the signature. If we have already written 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the magic bytes of the signature, or more likely, the PNG stream is 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * being embedded into another stream and doesn't need its own signature, 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * we should call png_set_sig_bytes() to tell libpng how many of the 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * bytes have already been written. 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_sig(png_structp png_ptr) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10}; 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write the rest of the 8 byte signature */ 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes], 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)(8 - png_ptr->sig_bytes)); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->sig_bytes < 3) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write a PNG chunk all at once. The type is an array of ASCII characters 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * representing the chunk name. The array must be at least 4 bytes in 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * length, and does not need to be null terminated. To be safe, pass the 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * pre-defined chunk names here, and if you need a new one, define it 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * where the others are defined. The length is the length of the data. 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * All the data must be present. If that is not possible, use the 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end() 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * functions instead. 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_chunk(png_structp png_ptr, png_bytep chunk_name, 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep data, png_size_t length) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr == NULL) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, data, (png_size_t)length); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_end(png_ptr); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the start of a PNG chunk. The type is the chunk type. 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The total_length is the sum of the lengths of all the data you will be 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * passing in png_write_chunk_data(). 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name, 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 length) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[8]; 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug2(0, "Writing %s chunk, length = %lu", chunk_name, 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (unsigned long)length); 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr == NULL) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write the length and the chunk name */ 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf, length); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_memcpy(buf + 4, chunk_name, 4); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_data(png_ptr, buf, (png_size_t)8); 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Put the chunk name into png_ptr->chunk_name */ 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_memcpy(png_ptr->chunk_name, chunk_name, 4); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Reset the crc and run it over the chunk name */ 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_reset_crc(png_ptr); 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_calculate_crc(png_ptr, chunk_name, (png_size_t)4); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the data of a PNG chunk started with png_write_chunk_start(). 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Note that multiple calls to this function are allowed, and that the 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * sum of the lengths from these calls *must* add up to the total_length 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * given to png_write_chunk_start(). 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length) 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write the data, and run the CRC over it */ 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr == NULL) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data != NULL && length > 0) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_data(png_ptr, data, length); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Update the CRC after writing the data, 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in case that the user I/O routine alters it. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_calculate_crc(png_ptr, data, length); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Finish a chunk started with png_write_chunk_start(). */ 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PNGAPI 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_chunk_end(png_structp png_ptr) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[4]; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr == NULL) return; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write the crc in a single operation */ 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf, png_ptr->crc); 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_data(png_ptr, buf, (png_size_t)4); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This pair of functions encapsulates the operation of (a) compressing a 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * text string, and (b) issuing it later as a series of chunk data writes. 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The compression_state structure is shared context for these functions 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * set up by the caller in order to make the whole mess thread-safe. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef struct 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char *input; /* The uncompressed input data */ 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int input_len; /* Its length */ 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_output_ptr; /* Number of output pointers used */ 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int max_output_ptr; /* Size of output_ptr */ 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charpp output_ptr; /* Array of pointers to output */ 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} compression_state; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Compress given text into storage in the png_ptr structure */ 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static int /* PRIVATE */ 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_text_compress(png_structp png_ptr, 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp text, png_size_t text_len, int compression, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) compression_state *comp) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->num_output_ptr = 0; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->max_output_ptr = 0; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->output_ptr = NULL; 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->input = NULL; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->input_len = 0; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We may just want to pass the text right through */ 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (compression == PNG_TEXT_COMPRESSION_NONE) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->input = text; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->input_len = text_len; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return((int)text_len); 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (compression >= PNG_TEXT_COMPRESSION_LAST) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char msg[50]; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_snprintf(msg, 50, "Unknown compression type %d", compression); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, msg); 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Unknown compression type"); 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We can't write the chunk until we find out how much data we have, 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * which means we need to run the compressor first and save the 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * output. This shouldn't be a problem, as the vast majority of 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * comments should be reasonable, but we will set up an array of 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * malloc'd pointers to be sure. 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * If we knew the application was well behaved, we could simplify this 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * greatly by assuming we can always malloc an output buffer large 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * enough to hold the compressed text ((1001 * text_len / 1000) + 12) 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and malloc this directly. The only time this would be a bad idea is 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * if we can't malloc more than 64K and we have 64K of random input 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * data, or if the input string is incredibly large (although this 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * wouldn't cause a failure, just a slowdown due to swapping). 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set up the compression buffers */ 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.avail_in = (uInt)text_len; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.next_in = (Bytef *)text; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This is the same compression loop as in png_write_row() */ 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Compress the data */ 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret != Z_OK) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Error */ 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->zstream.msg != NULL) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, png_ptr->zstream.msg); 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, "zlib error"); 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check to see if we need more room */ 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->zstream.avail_out)) 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Make sure the output array has room */ 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (comp->num_output_ptr >= comp->max_output_ptr) 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_max; 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_max = comp->max_output_ptr; 2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->max_output_ptr = comp->num_output_ptr + 4; 2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (comp->output_ptr != NULL) 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charpp old_ptr; 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_ptr = comp->output_ptr; 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->output_ptr = (png_charpp)png_malloc(png_ptr, 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32) 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (comp->max_output_ptr * png_sizeof(png_charpp))); 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_memcpy(comp->output_ptr, old_ptr, old_max 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * png_sizeof(png_charp)); 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, old_ptr); 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->output_ptr = (png_charpp)png_malloc(png_ptr, 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32) 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (comp->max_output_ptr * png_sizeof(png_charp))); 2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Save the data */ 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->output_ptr[comp->num_output_ptr] = 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_charp)png_malloc(png_ptr, 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)png_ptr->zbuf_size); 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zbuf_size); 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->num_output_ptr++; 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* and reset the buffer */ 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.next_out = png_ptr->zbuf; 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Continue until we don't have any more to compress */ 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (png_ptr->zstream.avail_in); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Finish the compression */ 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Tell zlib we are finished */ 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = deflate(&png_ptr->zstream, Z_FINISH); 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret == Z_OK) 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check to see if we need more room */ 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->zstream.avail_out)) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check to make sure our output array has room */ 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (comp->num_output_ptr >= comp->max_output_ptr) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int old_max; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_max = comp->max_output_ptr; 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->max_output_ptr = comp->num_output_ptr + 4; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (comp->output_ptr != NULL) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charpp old_ptr; 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_ptr = comp->output_ptr; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This could be optimized to realloc() */ 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->output_ptr = (png_charpp)png_malloc(png_ptr, 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(comp->max_output_ptr * 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_sizeof(png_charp))); 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_memcpy(comp->output_ptr, old_ptr, 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) old_max * png_sizeof(png_charp)); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, old_ptr); 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->output_ptr = (png_charpp)png_malloc(png_ptr, 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(comp->max_output_ptr * 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_sizeof(png_charp))); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Save the data */ 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->output_ptr[comp->num_output_ptr] = 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_charp)png_malloc(png_ptr, 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)png_ptr->zbuf_size); 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf, 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zbuf_size); 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->num_output_ptr++; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* and reset the buffer pointers */ 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.next_out = png_ptr->zbuf; 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (ret != Z_STREAM_END) 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We got an error */ 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->zstream.msg != NULL) 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, png_ptr->zstream.msg); 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, "zlib error"); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (ret != Z_STREAM_END); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Text length is number of buffers plus last buffer */ 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_len = png_ptr->zbuf_size * comp->num_output_ptr; 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out; 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return((int)text_len); 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Ship the compressed text out via chunk writes */ 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void /* PRIVATE */ 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Handle the no-compression case */ 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (comp->input) 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)comp->input, 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)comp->input_len); 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write saved output buffers, if any */ 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < comp->num_output_ptr; i++) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i], 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)png_ptr->zbuf_size); 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, comp->output_ptr[i]); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->output_ptr[i]=NULL; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (comp->max_output_ptr != 0) 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, comp->output_ptr); 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp->output_ptr=NULL; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write anything left in zbuf */ 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size) 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, png_ptr->zbuf, 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out)); 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Reset zlib for another zTXt/iTXt or image data */ 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deflateReset(&png_ptr->zstream); 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.data_type = Z_BINARY; 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the IHDR chunk, and update the png_struct with the necessary 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * information. Note that the rest of this code depends upon this 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * information being correct. 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int bit_depth, int color_type, int compression_type, int filter_type, 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int interlace_type) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_IHDR; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret; 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[13]; /* Buffer to store the IHDR info */ 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_IHDR"); 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check that we have valid input data from the application info */ 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (color_type) 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PNG_COLOR_TYPE_GRAY: 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (bit_depth) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 1: 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 2: 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 4: 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 8: 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 16: png_ptr->channels = 1; break; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: png_error(png_ptr, 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Invalid bit depth for grayscale image"); 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PNG_COLOR_TYPE_RGB: 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bit_depth != 8 && bit_depth != 16) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, "Invalid bit depth for RGB image"); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->channels = 3; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PNG_COLOR_TYPE_PALETTE: 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (bit_depth) 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 1: 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 2: 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 4: 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 8: png_ptr->channels = 1; break; 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: png_error(png_ptr, "Invalid bit depth for paletted image"); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PNG_COLOR_TYPE_GRAY_ALPHA: 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bit_depth != 8 && bit_depth != 16) 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, "Invalid bit depth for grayscale+alpha image"); 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->channels = 2; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PNG_COLOR_TYPE_RGB_ALPHA: 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (bit_depth != 8 && bit_depth != 16) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, "Invalid bit depth for RGBA image"); 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->channels = 4; 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, "Invalid image color type specified"); 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (compression_type != PNG_COMPRESSION_TYPE_BASE) 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Invalid compression type specified"); 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) compression_type = PNG_COMPRESSION_TYPE_BASE; 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write filter_method 64 (intrapixel differencing) only if 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 2. Libpng did not write a PNG signature (this filter_method is only 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * used in PNG datastreams that are embedded in MNG datastreams) and 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 3. The application called png_permit_mng_features with a mask that 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * included PNG_FLAG_MNG_FILTER_64 and 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 4. The filter_method is 64 and 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 5. The color_type is RGB or RGBA 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_MNG_FEATURES_SUPPORTED 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) && 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) && 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (color_type == PNG_COLOR_TYPE_RGB || 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) color_type == PNG_COLOR_TYPE_RGB_ALPHA) && 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) && 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter_type != PNG_FILTER_TYPE_BASE) 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Invalid filter type specified"); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter_type = PNG_FILTER_TYPE_BASE; 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_INTERLACING_SUPPORTED 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (interlace_type != PNG_INTERLACE_NONE && 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interlace_type != PNG_INTERLACE_ADAM7) 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Invalid interlace type specified"); 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interlace_type = PNG_INTERLACE_ADAM7; 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) interlace_type=PNG_INTERLACE_NONE; 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Save the relevent information */ 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->bit_depth = (png_byte)bit_depth; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->color_type = (png_byte)color_type; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->interlaced = (png_byte)interlace_type; 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_MNG_FEATURES_SUPPORTED 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->filter_type = (png_byte)filter_type; 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->compression_type = (png_byte)compression_type; 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->width = width; 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->height = height; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels); 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width); 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set the usr info, so any transformations can modify it */ 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->usr_width = png_ptr->width; 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->usr_bit_depth = png_ptr->bit_depth; 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->usr_channels = png_ptr->channels; 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Pack the header information into the buffer */ 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf, width); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 4, height); 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[8] = (png_byte)bit_depth; 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[9] = (png_byte)color_type; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[10] = (png_byte)compression_type; 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[11] = (png_byte)filter_type; 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[12] = (png_byte)interlace_type; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write the chunk */ 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13); 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Initialize zlib with PNG info */ 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.zalloc = png_zalloc; 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.zfree = png_zfree; 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.opaque = (voidpf)png_ptr; 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->do_filter)) 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE || 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->bit_depth < 8) 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->do_filter = PNG_FILTER_NONE; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->do_filter = PNG_ALL_FILTERS; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->do_filter != PNG_FILTER_NONE) 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zlib_strategy = Z_FILTERED; 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY; 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL)) 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zlib_level = Z_DEFAULT_COMPRESSION; 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL)) 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zlib_mem_level = 8; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS)) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zlib_window_bits = 15; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zlib_method = 8; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zlib_method, png_ptr->zlib_window_bits, 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zlib_mem_level, png_ptr->zlib_strategy); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret != Z_OK) 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret == Z_VERSION_ERROR) png_error(png_ptr, 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "zlib failed to initialize compressor -- version error"); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret == Z_STREAM_ERROR) png_error(png_ptr, 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "zlib failed to initialize compressor -- stream error"); 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret == Z_MEM_ERROR) png_error(png_ptr, 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "zlib failed to initialize compressor -- mem error"); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, "zlib failed to initialize compressor"); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.next_out = png_ptr->zbuf; 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* libpng is not interested in zstream.data_type */ 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set it to a predefined value, to avoid its evaluation inside zlib */ 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.data_type = Z_BINARY; 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->mode = PNG_HAVE_IHDR; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the palette. We are careful not to trust png_color to be in the 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * correct order for PNG, so people can redefine it to any convenient 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * structure. 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal) 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_PLTE; 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_colorp pal_ptr; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[3]; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_PLTE"); 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (( 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_MNG_FEATURES_SUPPORTED 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) && 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_pal == 0) || num_pal > 256) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, "Invalid number of colors in palette"); 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Invalid number of colors in palette"); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR)) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Ignoring request to write a PLTE chunk in grayscale PNG"); 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->num_palette = (png_uint_16)num_pal; 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug1(3, "num_palette = %d", png_ptr->num_palette); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_start(png_ptr, (png_bytep)png_PLTE, 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(num_pal * 3)); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_POINTER_INDEXING_SUPPORTED 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++) 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = pal_ptr->red; 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[1] = pal_ptr->green; 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[2] = pal_ptr->blue; 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, buf, (png_size_t)3); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This is a little slower but some buggy compilers need to do this 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * instead 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pal_ptr=palette; 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < num_pal; i++) 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = pal_ptr[i].red; 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[1] = pal_ptr[i].green; 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[2] = pal_ptr[i].blue; 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, buf, (png_size_t)3); 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_end(png_ptr); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->mode |= PNG_HAVE_PLTE; 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write an IDAT chunk */ 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_IDAT; 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_IDAT"); 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Optimize the CMF field in the zlib stream. */ 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* This hack of the zlib stream is compliant to the stream specification. */ 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->mode & PNG_HAVE_IDAT) && 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int z_cmf = data[0]; /* zlib compression method and flags */ 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Avoid memory underflows and multiplication overflows. 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The conditions below are practically always satisfied; 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * however, they still must be checked. 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (length >= 2 && 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->height < 16384 && png_ptr->width < 16384) 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 uncompressed_idat_size = png_ptr->height * 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((png_ptr->width * 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->channels * png_ptr->bit_depth + 15) >> 3); 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int z_cinfo = z_cmf >> 4; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int half_z_window_size = 1 << (z_cinfo + 7); 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (uncompressed_idat_size <= half_z_window_size && 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) half_z_window_size >= 256) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z_cinfo--; 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) half_z_window_size >>= 1; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4); 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (data[0] != (png_byte)z_cmf) 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[0] = (png_byte)z_cmf; 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[1] &= 0xe0; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f); 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Invalid zlib compression method or flags in IDAT"); 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length); 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->mode |= PNG_HAVE_IDAT; 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write an IEND chunk */ 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_IEND(png_structp png_ptr) 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_IEND; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_IEND"); 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL, 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)0); 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->mode |= PNG_HAVE_IEND; 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_gAMA_SUPPORTED 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write a gAMA chunk */ 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_FLOATING_POINT_SUPPORTED 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_gAMA(png_structp png_ptr, double file_gamma) 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_gAMA; 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 igamma; 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[4]; 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_gAMA"); 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* file_gamma is saved in 1/100,000ths */ 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5); 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf, igamma); 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_FIXED_POINT_SUPPORTED 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma) 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_gAMA; 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[4]; 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_gAMA"); 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* file_gamma is saved in 1/100,000ths */ 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf, (png_uint_32)file_gamma); 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4); 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_sRGB_SUPPORTED 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write a sRGB chunk */ 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_sRGB(png_structp png_ptr, int srgb_intent) 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_sRGB; 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[1]; 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_sRGB"); 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (srgb_intent >= PNG_sRGB_INTENT_LAST) 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Invalid sRGB rendering intent specified"); 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0]=(png_byte)srgb_intent; 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1); 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_iCCP_SUPPORTED 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write an iCCP chunk */ 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type, 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp profile, int profile_len) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_iCCP; 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t name_len; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp new_name; 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) compression_state comp; 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int embedded_profile_len = 0; 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_iCCP"); 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.num_output_ptr = 0; 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.max_output_ptr = 0; 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.output_ptr = NULL; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.input = NULL; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.input_len = 0; 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((name_len = png_check_keyword(png_ptr, name, 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &new_name)) == 0) 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (compression_type != PNG_COMPRESSION_TYPE_BASE) 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Unknown compression type in iCCP chunk"); 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile == NULL) 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_len = 0; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_len > 3) 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) embedded_profile_len = 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((*( (png_bytep)profile ))<<24) | 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((*( (png_bytep)profile + 1))<<16) | 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((*( (png_bytep)profile + 2))<< 8) | 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((*( (png_bytep)profile + 3)) ); 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (embedded_profile_len < 0) 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Embedded profile length in iCCP chunk is negative"); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, new_name); 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_len < embedded_profile_len) 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Embedded profile length too large in iCCP chunk"); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, new_name); 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_len > embedded_profile_len) 8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, 8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Truncating profile to actual length in iCCP chunk"); 8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_len = embedded_profile_len; 8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_len) 8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_len = png_text_compress(png_ptr, profile, 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp); 8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Make sure we include the NULL after the name and the compression type */ 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_start(png_ptr, (png_bytep)png_iCCP, 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(name_len + profile_len + 2)); 8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_name[name_len + 1] = 0x00; 8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)new_name, 8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)(name_len + 2)); 8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (profile_len) 8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_compressed_data_out(png_ptr, &comp); 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_end(png_ptr); 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, new_name); 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_sPLT_SUPPORTED 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write a sPLT chunk */ 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette) 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_sPLT; 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t name_len; 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp new_name; 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte entrybuf[10]; 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int entry_size = (spalette->depth == 8 ? 6 : 10); 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int palette_size = entry_size * spalette->nentries; 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_sPLT_entryp ep; 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PNG_POINTER_INDEXING_SUPPORTED 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_sPLT"); 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0) 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Make sure we include the NULL after the name */ 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_start(png_ptr, (png_bytep)png_sPLT, 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(name_len + 2 + palette_size)); 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)new_name, 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)(name_len + 1)); 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1); 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Loop through each palette entry, writing appropriately */ 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_POINTER_INDEXING_SUPPORTED 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++) 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (spalette->depth == 8) 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entrybuf[0] = (png_byte)ep->red; 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entrybuf[1] = (png_byte)ep->green; 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entrybuf[2] = (png_byte)ep->blue; 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entrybuf[3] = (png_byte)ep->alpha; 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 4, ep->frequency); 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 0, ep->red); 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 2, ep->green); 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 4, ep->blue); 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 6, ep->alpha); 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 8, ep->frequency); 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ep=spalette->entries; 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i=0; i>spalette->nentries; i++) 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (spalette->depth == 8) 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entrybuf[0] = (png_byte)ep[i].red; 9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entrybuf[1] = (png_byte)ep[i].green; 9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entrybuf[2] = (png_byte)ep[i].blue; 9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) entrybuf[3] = (png_byte)ep[i].alpha; 9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 4, ep[i].frequency); 9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 0, ep[i].red); 9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 2, ep[i].green); 9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 4, ep[i].blue); 9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 6, ep[i].alpha); 9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(entrybuf + 8, ep[i].frequency); 9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size); 9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_end(png_ptr); 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, new_name); 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_sBIT_SUPPORTED 9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the sBIT chunk */ 9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type) 9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_sBIT; 9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[4]; 9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t size; 9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_sBIT"); 9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Make sure we don't depend upon the order of PNG_COLOR_8 */ 9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (color_type & PNG_COLOR_MASK_COLOR) 9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte maxbits; 9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 : 9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->usr_bit_depth); 9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sbit->red == 0 || sbit->red > maxbits || 9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sbit->green == 0 || sbit->green > maxbits || 9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sbit->blue == 0 || sbit->blue > maxbits) 9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Invalid sBIT depth specified"); 9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = sbit->red; 9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[1] = sbit->green; 9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[2] = sbit->blue; 9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size = 3; 9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth) 9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Invalid sBIT depth specified"); 9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = sbit->gray; 9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size = 1; 9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (color_type & PNG_COLOR_MASK_ALPHA) 9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth) 9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Invalid sBIT depth specified"); 9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[size++] = sbit->alpha; 9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size); 9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_cHRM_SUPPORTED 9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the cHRM chunk */ 9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_FLOATING_POINT_SUPPORTED 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_cHRM(png_structp png_ptr, double white_x, double white_y, 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double red_x, double red_y, double green_x, double green_y, 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) double blue_x, double blue_y) 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_cHRM; 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[32]; 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y, 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int_green_x, int_green_y, int_blue_x, int_blue_y; 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_cHRM"); 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int_white_x = (png_uint_32)(white_x * 100000.0 + 0.5); 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int_white_y = (png_uint_32)(white_y * 100000.0 + 0.5); 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int_red_x = (png_uint_32)(red_x * 100000.0 + 0.5); 10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int_red_y = (png_uint_32)(red_y * 100000.0 + 0.5); 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5); 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5); 10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int_blue_x = (png_uint_32)(blue_x * 100000.0 + 0.5); 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int_blue_y = (png_uint_32)(blue_y * 100000.0 + 0.5); 10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_CHECK_cHRM_SUPPORTED 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y, 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y)) 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Each value is saved in 1/100,000ths */ 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf, int_white_x); 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 4, int_white_y); 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 8, int_red_x); 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 12, int_red_y); 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 16, int_green_x); 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 20, int_green_y); 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 24, int_blue_x); 10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 28, int_blue_y); 10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); 10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_FIXED_POINT_SUPPORTED 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x, 10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y, 10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x, 10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_fixed_point blue_y) 10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_cHRM; 10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[32]; 10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_cHRM"); 10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Each value is saved in 1/100,000ths */ 10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_CHECK_cHRM_SUPPORTED 10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y, 10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) green_x, green_y, blue_x, blue_y)) 10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf, (png_uint_32)white_x); 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 4, (png_uint_32)white_y); 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 8, (png_uint_32)red_x); 10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 12, (png_uint_32)red_y); 10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 16, (png_uint_32)green_x); 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 20, (png_uint_32)green_y); 10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 24, (png_uint_32)blue_x); 10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 28, (png_uint_32)blue_y); 10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32); 10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_tRNS_SUPPORTED 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the tRNS chunk */ 10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran, 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_trans, int color_type) 10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_tRNS; 10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[6]; 10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_tRNS"); 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (color_type == PNG_COLOR_TYPE_PALETTE) 10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette) 10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Invalid number of transparent colors specified"); 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write the chunk out as it is */ 10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans, 10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)num_trans); 10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (color_type == PNG_COLOR_TYPE_GRAY) 10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* One 16 bit value */ 11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (tran->gray >= (1 << png_ptr->bit_depth)) 11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Ignoring attempt to write tRNS chunk out-of-range for bit_depth"); 11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(buf, tran->gray); 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2); 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (color_type == PNG_COLOR_TYPE_RGB) 11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Three 16 bit values */ 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(buf, tran->red); 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(buf + 2, tran->green); 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(buf + 4, tran->blue); 11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) 11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, 11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8"); 11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6); 11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Can't write tRNS with an alpha channel"); 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_bKGD_SUPPORTED 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the background chunk */ 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type) 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_bKGD; 11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[6]; 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_bKGD"); 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (color_type == PNG_COLOR_TYPE_PALETTE) 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ( 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_MNG_FEATURES_SUPPORTED 11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_ptr->num_palette || 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) && 11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) back->index >= png_ptr->num_palette) 11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Invalid background palette index"); 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = back->index; 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1); 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (color_type & PNG_COLOR_MASK_COLOR) 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(buf, back->red); 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(buf + 2, back->green); 11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(buf + 4, back->blue); 11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4])) 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8"); 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6); 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (back->gray >= (1 << png_ptr->bit_depth)) 11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "Ignoring attempt to write bKGD chunk out-of-range for bit_depth"); 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(buf, back->gray); 11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2); 11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_hIST_SUPPORTED 11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the histogram */ 11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist) 11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_hIST; 11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[3]; 11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_hIST"); 11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (num_hist > (int)png_ptr->num_palette) 11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug2(3, "num_hist = %d, num_palette = %d", num_hist, 12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->num_palette); 12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Invalid number of histogram entries specified"); 12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_start(png_ptr, (png_bytep)png_hIST, 12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(num_hist * 2)); 12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < num_hist; i++) 12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(buf, hist[i]); 12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, buf, (png_size_t)2); 12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_end(png_ptr); 12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \ 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED) 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification, 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and if invalid, correct the keyword rather than discarding the entire 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * chunk. The PNG 1.0 specification requires keywords 1-79 characters in 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * length, forbids leading or trailing whitespace, multiple internal spaces, 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and the non-break space (0x80) from ISO 8859-1. Returns keyword length. 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The new_key is allocated to hold the corrected keyword and must be freed 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * by the calling routine. This avoids problems with trying to write to 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * static keywords without having to have duplicate copies of the strings. 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_size_t /* PRIVATE */ 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key) 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t key_len; 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp kp, dp; 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int kflag; 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int kwarn=0; 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_check_keyword"); 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *new_key = NULL; 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key == NULL || (key_len = png_strlen(key)) == 0) 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "zero length keyword"); 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((png_size_t)0); 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug1(2, "Keyword to be checked is '%s'", key); 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2)); 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*new_key == NULL) 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Out of memory while procesing keyword"); 12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ((png_size_t)0); 12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Replace non-printing characters with a blank and print a warning */ 12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++) 12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((png_byte)*kp < 0x20 || 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1)) 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE) 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char msg[40]; 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_snprintf(msg, 40, 12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "invalid keyword character 0x%02X", (png_byte)*kp); 12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, msg); 12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "invalid character in keyword"); 12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp = ' '; 12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp = *kp; 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp = '\0'; 12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Remove any trailing white space. */ 12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kp = *new_key + key_len - 1; 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*kp == ' ') 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "trailing spaces removed from keyword"); 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*kp == ' ') 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *(kp--) = '\0'; 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_len--; 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Remove any leading white space. */ 12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kp = *new_key; 12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*kp == ' ') 12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "leading spaces removed from keyword"); 12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*kp == ' ') 12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kp++; 13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_len--; 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug1(2, "Checking for multiple internal spaces in '%s'", kp); 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Remove multiple internal spaces. */ 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (kflag = 0, dp = *new_key; *kp != '\0'; kp++) 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (*kp == ' ' && kflag == 0) 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 13125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *(dp++) = *kp; 13135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kflag = 1; 13145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (*kp == ' ') 13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_len--; 13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kwarn=1; 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *(dp++) = *kp; 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kflag = 0; 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp = '\0'; 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (kwarn) 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "extra interior spaces removed from keyword"); 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key_len == 0) 13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, *new_key); 13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *new_key=NULL; 13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Zero length keyword"); 13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (key_len > 79) 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "keyword length must be 1 - 79 characters"); 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*new_key)[79] = '\0'; 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) key_len = 79; 13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (key_len); 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_tEXt_SUPPORTED 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write a tEXt chunk */ 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text, 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t text_len) 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_tEXt; 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t key_len; 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp new_key; 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_tEXt"); 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text == NULL || *text == '\0') 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_len = 0; 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_len = png_strlen(text); 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Make sure we include the 0 after the key */ 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(key_len + text_len + 1)); 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * We leave it to the application to meet PNG-1.0 requirements on the 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)new_key, 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)(key_len + 1)); 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text_len) 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)text, (png_size_t)text_len); 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_end(png_ptr); 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, new_key); 13865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 13885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_zTXt_SUPPORTED 13905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write a compressed text chunk */ 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text, 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t text_len, int compression) 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_zTXt; 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 13985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t key_len; 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[1]; 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp new_key; 14015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) compression_state comp; 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_zTXt"); 14045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.num_output_ptr = 0; 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.max_output_ptr = 0; 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.output_ptr = NULL; 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.input = NULL; 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.input_len = 0; 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 14135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, new_key); 14145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE) 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_tEXt(png_ptr, new_key, text, (png_size_t)0); 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, new_key); 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_len = png_strlen(text); 14255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Compute the compressed data; do it now for the length */ 14275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_len = png_text_compress(png_ptr, text, text_len, compression, 14285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &comp); 14295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write start of chunk */ 14315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, 14325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(key_len+text_len + 2)); 14335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write key */ 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)new_key, 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)(key_len + 1)); 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, new_key); 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = (png_byte)compression; 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write compression */ 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1); 14415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write the compressed data */ 14425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_compressed_data_out(png_ptr, &comp); 14435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Close the chunk */ 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_end(png_ptr); 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_iTXt_SUPPORTED 14505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write an iTXt chunk */ 14515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 14525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_iTXt(png_structp png_ptr, int compression, png_charp key, 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp lang, png_charp lang_key, png_charp text) 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_iTXt; 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t lang_len, key_len, lang_key_len, text_len; 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp new_lang; 14605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp new_key = NULL; 14615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte cbuf[2]; 14625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) compression_state comp; 14635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_iTXt"); 14655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.num_output_ptr = 0; 14675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.max_output_ptr = 0; 14685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.output_ptr = NULL; 14695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) comp.input = NULL; 14705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0) 14725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 14735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0) 14755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 14765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Empty language field in iTXt chunk"); 14775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_lang = NULL; 14785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lang_len = 0; 14795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 14805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lang_key == NULL) 14825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lang_key_len = 0; 14835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 14845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lang_key_len = png_strlen(lang_key); 14855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (text == NULL) 14875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_len = 0; 14885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 14895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_len = png_strlen(text); 14905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Compute the compressed data; do it now for the length */ 14925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) text_len = png_text_compress(png_ptr, text, text_len, compression-2, 14935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &comp); 14945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Make sure we include the compression flag, the compression byte, 14975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and the NULs after the key, lang, and lang_key parts */ 14985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_start(png_ptr, (png_bytep)png_iTXt, 15005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)( 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5 /* comp byte, comp flag, terminators for key, lang and lang_key */ 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) + key_len 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) + lang_len 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) + lang_key_len 15055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) + text_len)); 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We leave it to the application to meet PNG-1.0 requirements on the 15085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of 15095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them. 15105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG. 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)new_key, 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)(key_len + 1)); 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set the compression flag */ 15165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (compression == PNG_ITXT_COMPRESSION_NONE || \ 15175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) compression == PNG_TEXT_COMPRESSION_NONE) 15185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cbuf[0] = 0; 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else /* compression == PNG_ITXT_COMPRESSION_zTXt */ 15205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cbuf[0] = 1; 15215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set the compression method */ 15225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cbuf[1] = 0; 15235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, cbuf, (png_size_t)2); 15245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cbuf[0] = 0; 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)(lang_len + 1)); 15285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), 15295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)(lang_key_len + 1)); 15305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_compressed_data_out(png_ptr, &comp); 15315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_end(png_ptr); 15335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, new_key); 15345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, new_lang); 15355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 15375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_oFFs_SUPPORTED 15395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the oFFs chunk */ 15405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 15415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset, 15425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int unit_type) 15435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 15445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 15455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_oFFs; 15465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 15475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[9]; 15485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_oFFs"); 15505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unit_type >= PNG_OFFSET_LAST) 15525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Unrecognized unit type for oFFs chunk"); 15535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_int_32(buf, x_offset); 15555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_int_32(buf + 4, y_offset); 15565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[8] = (png_byte)unit_type; 15575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9); 15595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 15605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 15615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_pCAL_SUPPORTED 15625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the pCAL chunk (described in the PNG extensions document) */ 15635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 15645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0, 15655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_int_32 X1, int type, int nparams, png_charp units, png_charpp params) 15665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 15675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 15685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_pCAL; 15695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 15705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t purpose_len, units_len, total_len; 15715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32p params_len; 15725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[10]; 15735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp new_purpose; 15745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i; 15755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug1(1, "in png_write_pCAL (%d parameters)", nparams); 15775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (type >= PNG_EQUATION_LAST) 15795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Unrecognized equation type for pCAL chunk"); 15805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1; 15825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug1(3, "pCAL purpose length = %d", (int)purpose_len); 15835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) units_len = png_strlen(units) + (nparams == 0 ? 0 : 1); 15845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug1(3, "pCAL units length = %d", (int)units_len); 15855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_len = purpose_len + units_len + 10; 15865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params_len = (png_uint_32p)png_malloc(png_ptr, 15885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(nparams * png_sizeof(png_uint_32))); 15895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Find the length of each parameter, making sure we don't count the 15915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) null terminator for the last parameter. */ 15925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < nparams; i++) 15935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 15945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1); 15955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug2(3, "pCAL parameter %d length = %lu", i, 15965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (unsigned long) params_len[i]); 15975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_len += (png_size_t)params_len[i]; 15985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 15995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug1(3, "pCAL total length = %d", (int)total_len); 16015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len); 16025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)new_purpose, 16035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)purpose_len); 16045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_int_32(buf, X0); 16055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_int_32(buf + 4, X1); 16065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[8] = (png_byte)type; 16075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[9] = (png_byte)nparams; 16085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, buf, (png_size_t)10); 16095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len); 16105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, new_purpose); 16125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0; i < nparams; i++) 16145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 16155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_data(png_ptr, (png_bytep)params[i], 16165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)params_len[i]); 16175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_free(png_ptr, params_len); 16205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk_end(png_ptr); 16215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 16235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_sCAL_SUPPORTED 16255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the sCAL chunk */ 16265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED) 16275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 16285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_sCAL(png_structp png_ptr, int unit, double width, double height) 16295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 16305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 16315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_sCAL; 16325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 16335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[64]; 16345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t total_len; 16355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_sCAL"); 16375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = (char)unit; 16395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef _WIN32_WCE 16405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* sprintf() function is not supported on WindowsCE */ 16415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 16425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wchar_t wc_buf[32]; 16435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t wc_len; 16445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swprintf(wc_buf, TEXT("%12.12e"), width); 16455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wc_len = wcslen(wc_buf); 16465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, 16475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL); 16485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_len = wc_len + 2; 16495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) swprintf(wc_buf, TEXT("%12.12e"), height); 16505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wc_len = wcslen(wc_buf); 16515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len, 16525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, NULL); 16535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_len += wc_len; 16545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 16565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_snprintf(buf + 1, 63, "%12.12e", width); 16575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_len = 1 + png_strlen(buf + 1) + 1; 16585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_snprintf(buf + total_len, 64-total_len, "%12.12e", height); 16595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_len += png_strlen(buf + total_len); 16605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 16615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); 16635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len); 16645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 16665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_FIXED_POINT_SUPPORTED 16675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 16685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width, 16695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_charp height) 16705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 16715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 16725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_sCAL; 16735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 16745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[64]; 16755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t wlen, hlen, total_len; 16765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_sCAL_s"); 16785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wlen = png_strlen(width); 16805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hlen = png_strlen(height); 16815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_len = wlen + hlen + 2; 16825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (total_len > 64) 16835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 16845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Can't write sCAL (buffer too small)"); 16855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 16865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 16875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[0] = (png_byte)unit; 16895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */ 16905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */ 16915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug1(3, "sCAL total length = %u", (unsigned int)total_len); 16935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_sCAL, buf, total_len); 16945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 16955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 16965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 16975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 16985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 16995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_pHYs_SUPPORTED 17005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the pHYs chunk */ 17015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 17025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit, 17035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 y_pixels_per_unit, 17045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int unit_type) 17055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 17075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_pHYs; 17085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 17095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[9]; 17105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_pHYs"); 17125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (unit_type >= PNG_RESOLUTION_LAST) 17145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Unrecognized unit type for pHYs chunk"); 17155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf, x_pixels_per_unit); 17175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_32(buf + 4, y_pixels_per_unit); 17185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[8] = (png_byte)unit_type; 17195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9); 17215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 17235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_tIME_SUPPORTED 17255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Write the tIME chunk. Use either png_convert_from_struct_tm() 17265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * or png_convert_from_time_t(), or fill in the structure yourself. 17275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 17285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 17295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_tIME(png_structp png_ptr, png_timep mod_time) 17305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_LOCAL_ARRAYS 17325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_tIME; 17335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 17345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte buf[7]; 17355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_tIME"); 17375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (mod_time->month > 12 || mod_time->month < 1 || 17395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mod_time->day > 31 || mod_time->day < 1 || 17405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mod_time->hour > 23 || mod_time->second > 60) 17415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 17425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_warning(png_ptr, "Invalid time specified for tIME chunk"); 17435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 17445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_save_uint_16(buf, mod_time->year); 17475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[2] = mod_time->month; 17485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[3] = mod_time->day; 17495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[4] = mod_time->hour; 17505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[5] = mod_time->minute; 17515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf[6] = mod_time->second; 17525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7); 17545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 17555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 17565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Initializes the row writing capability of libpng */ 17585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 17595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_start_row(png_structp png_ptr) 17605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 17615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_INTERLACING_SUPPORTED 17625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 17635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Start of interlace block */ 17655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 17665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Offset to next interlace block */ 17685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 17695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Start of interlace block in the y direction */ 17715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; 17725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Offset to next interlace block in the y direction */ 17745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; 17755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 17765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t buf_size; 17785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_start_row"); 17805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) buf_size = (png_size_t)(PNG_ROWBYTES( 17825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1); 17835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set up row buffer */ 17855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, 17865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)buf_size); 17875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; 17885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_FILTER_SUPPORTED 17905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set up filtering buffer, if using this filter */ 17915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->do_filter & PNG_FILTER_SUB) 17925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 17935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, 17945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(png_ptr->rowbytes + 1)); 17955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; 17965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 17975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 17985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We only need to keep the previous row if we are using one of these. */ 17995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) 18005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set up previous row buffer */ 18025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, 18035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)buf_size); 18045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->do_filter & PNG_FILTER_UP) 18065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->up_row = (png_bytep)png_malloc(png_ptr, 18085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(png_ptr->rowbytes + 1)); 18095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; 18105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->do_filter & PNG_FILTER_AVG) 18135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, 18155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(png_ptr->rowbytes + 1)); 18165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; 18175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->do_filter & PNG_FILTER_PAETH) 18205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, 18225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_uint_32)(png_ptr->rowbytes + 1)); 18235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; 18245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_WRITE_FILTER_SUPPORTED */ 18275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_INTERLACING_SUPPORTED 18295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If interlaced, we need to set up width and height of pass */ 18305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->interlaced) 18315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->transformations & PNG_INTERLACE)) 18335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 - 18355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_pass_ystart[0]) / png_pass_yinc[0]; 18365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 - 18375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_pass_start[0]) / png_pass_inc[0]; 18385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 18405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->num_rows = png_ptr->height; 18425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->usr_width = png_ptr->width; 18435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 18465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 18475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->num_rows = png_ptr->height; 18495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->usr_width = png_ptr->width; 18505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 18525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.next_out = png_ptr->zbuf; 18535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 18545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Internal use only. Called when finished processing a row of data. */ 18565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 18575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_finish_row(png_structp png_ptr) 18585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 18595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_INTERLACING_SUPPORTED 18605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 18615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Start of interlace block */ 18635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 18645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Offset to next interlace block */ 18665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 18675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Start of interlace block in the y direction */ 18695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1}; 18705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Offset to next interlace block in the y direction */ 18725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2}; 18735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 18745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret; 18765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_finish_row"); 18785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Next row */ 18805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->row_number++; 18815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* See if we are done */ 18835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->row_number < png_ptr->num_rows) 18845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 18855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 18865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_INTERLACING_SUPPORTED 18875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If interlaced, go to next pass */ 18885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->interlaced) 18895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->row_number = 0; 18915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->transformations & PNG_INTERLACE) 18925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->pass++; 18945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 18955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 18965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 18975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Loop until we find a non-zero width or height pass */ 18985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do 18995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 19005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->pass++; 19015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->pass >= 7) 19025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 19035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->usr_width = (png_ptr->width + 19045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_pass_inc[png_ptr->pass] - 1 - 19055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_pass_start[png_ptr->pass]) / 19065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_pass_inc[png_ptr->pass]; 19075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->num_rows = (png_ptr->height + 19085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_pass_yinc[png_ptr->pass] - 1 - 19095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_pass_ystart[png_ptr->pass]) / 19105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_pass_yinc[png_ptr->pass]; 19115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->transformations & PNG_INTERLACE) 19125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 19135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0); 19145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Reset the row above the image for the next pass */ 19185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->pass < 7) 19195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 19205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->prev_row != NULL) 19215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_memset(png_ptr->prev_row, 0, 19225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels* 19235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->usr_bit_depth, png_ptr->width)) + 1); 19245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 19255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 19285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* If we get here, we've just written the last row, so we need 19305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to flush the compressor */ 19315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do 19325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 19335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Tell the compressor we are done */ 19345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = deflate(&png_ptr->zstream, Z_FINISH); 19355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check for an error */ 19365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret == Z_OK) 19375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 19385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check to see if we need more room */ 19395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->zstream.avail_out)) 19405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 19415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); 19425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.next_out = png_ptr->zbuf; 19435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 19445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (ret != Z_STREAM_END) 19475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 19485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->zstream.msg != NULL) 19495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, png_ptr->zstream.msg); 19505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 19515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, "zlib error"); 19525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (ret != Z_STREAM_END); 19545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write any extra space */ 19565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->zstream.avail_out < png_ptr->zbuf_size) 19575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 19585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size - 19595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.avail_out); 19605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 19615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) deflateReset(&png_ptr->zstream); 19635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.data_type = Z_BINARY; 19645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 19655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_INTERLACING_SUPPORTED 19675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Pick out the correct pixels for the interlace pass. 19685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The basic idea here is to go through the row with a source 19695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * pointer and a destination pointer (sp and dp), and copy the 19705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * correct pixels for the pass. As the row gets compacted, 19715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * sp will always be >= dp, so we should never overwrite anything. 19725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * See the default: case for the easiest code to understand. 19735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 19745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 19755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) 19765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 19775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */ 19785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Start of interlace block */ 19805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0}; 19815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Offset to next interlace block */ 19835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1}; 19845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_do_write_interlace"); 19865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 19875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We don't have to do anything on the last pass (6) */ 19885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USELESS_TESTS_SUPPORTED 19895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (row != NULL && row_info != NULL && pass < 6) 19905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 19915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pass < 6) 19925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 19935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 19945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Each pixel depth is handled separately */ 19955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (row_info->pixel_depth) 19965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 19975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 1: 19985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 19995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep sp; 20005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep dp; 20015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int shift; 20025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int d; 20035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int value; 20045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 20055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 row_width = row_info->width; 20065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dp = row; 20085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d = 0; 20095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift = 7; 20105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = png_pass_start[pass]; i < row_width; 20115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i += png_pass_inc[pass]) 20125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 20135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sp = row + (png_size_t)(i >> 3); 20145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01; 20155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d |= (value << shift); 20165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shift == 0) 20185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 20195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift = 7; 20205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp++ = (png_byte)d; 20215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d = 0; 20225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 20245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift--; 20255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shift != 7) 20285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp = (png_byte)d; 20295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 20305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 2: 20325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 20335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep sp; 20345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep dp; 20355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int shift; 20365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int d; 20375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int value; 20385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 20395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 row_width = row_info->width; 20405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dp = row; 20425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift = 6; 20435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d = 0; 20445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = png_pass_start[pass]; i < row_width; 20455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i += png_pass_inc[pass]) 20465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 20475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sp = row + (png_size_t)(i >> 2); 20485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03; 20495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d |= (value << shift); 20505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shift == 0) 20525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 20535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift = 6; 20545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp++ = (png_byte)d; 20555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d = 0; 20565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 20585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift -= 2; 20595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shift != 6) 20615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp = (png_byte)d; 20625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 20635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case 4: 20655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 20665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep sp; 20675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep dp; 20685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int shift; 20695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int d; 20705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int value; 20715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 20725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 row_width = row_info->width; 20735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dp = row; 20755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift = 4; 20765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d = 0; 20775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = png_pass_start[pass]; i < row_width; 20785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i += png_pass_inc[pass]) 20795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 20805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sp = row + (png_size_t)(i >> 1); 20815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f; 20825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d |= (value << shift); 20835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 20845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shift == 0) 20855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 20865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift = 4; 20875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp++ = (png_byte)d; 20885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) d = 0; 20895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 20915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) shift -= 4; 20925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (shift != 4) 20945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp = (png_byte)d; 20955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 20965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 20975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 20985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 20995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep sp; 21005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep dp; 21015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 21025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 row_width = row_info->width; 21035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_size_t pixel_bytes; 21045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Start at the beginning */ 21065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dp = row; 21075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Find out how many bytes each pixel takes up */ 21085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pixel_bytes = (row_info->pixel_depth >> 3); 21095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Loop through the row, only looking at the pixels that 21105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) matter */ 21115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = png_pass_start[pass]; i < row_width; 21125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i += png_pass_inc[pass]) 21135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 21145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Find out where the original pixel is */ 21155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sp = row + (png_size_t)i * pixel_bytes; 21165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Move the pixel */ 21175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (dp != sp) 21185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_memcpy(dp, sp, pixel_bytes); 21195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Next pixel */ 21205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dp += pixel_bytes; 21215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 21235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set new row width */ 21265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row_info->width = (row_info->width + 21275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_pass_inc[pass] - 1 - 21285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_pass_start[pass]) / 21295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_pass_inc[pass]; 21305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, 21315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row_info->width); 21325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 21345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 21355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* This filters the row, chooses which filter to use, if it has not already 21375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * been specified by the application, and then writes the row out with the 21385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * chosen filter. 21395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 21405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) 21415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PNG_HISHIFT 10 21425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PNG_LOMASK ((png_uint_32)0xffffL) 21435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) 21445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 21455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_find_filter(png_structp png_ptr, png_row_infop row_info) 21465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 21475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep best_row; 21485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_FILTER_SUPPORTED 21495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep prev_row, row_buf; 21505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 mins, bpp; 21515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_byte filter_to_do = png_ptr->do_filter; 21525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 row_bytes = row_info->rowbytes; 21535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 21545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_p_filters = (int)png_ptr->num_prev_filters; 21555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 21565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_find_filter"); 21585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 21605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) 21615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 21625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* These will never be selected so we need not test them. */ 21635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); 21645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 21655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 21665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Find out how many bytes offset each pixel is */ 21685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bpp = (row_info->pixel_depth + 7) >> 3; 21695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prev_row = png_ptr->prev_row; 21715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 21725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_row = png_ptr->row_buf; 21735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_FILTER_SUPPORTED 21745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) row_buf = best_row; 21755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mins = PNG_MAXSUM; 21765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* The prediction method we use is to find which method provides the 21785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * smallest value when summing the absolute values of the distances 21795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * from zero, using anything >= 128 as negative numbers. This is known 21805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * as the "minimum sum of absolute differences" heuristic. Other 21815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * heuristics are the "weighted minimum sum of absolute differences" 21825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (experimental and can in theory improve compression), and the "zlib 21835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * predictive" method (not implemented yet), which does test compressions 21845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of lines using different filter methods, and then chooses the 21855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (series of) filter(s) that give minimum compressed data size (VERY 21865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * computationally expensive). 21875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 21885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * GRR 980525: consider also 21895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (1) minimum sum of absolute differences from running average (i.e., 21905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * keep running sum of non-absolute differences & count of bytes) 21915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * [track dispersion, too? restart average if dispersion too large?] 21925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (1b) minimum sum of absolute differences from sliding average, probably 21935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * with window size <= deflate window (usually 32K) 21945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (2) minimum sum of squared differences from zero or running average 21955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * (i.e., ~ root-mean-square approach) 21965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 21975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We don't need to test the 'no filter' case if this is the only filter 22005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * that has been chosen, as it doesn't actually do anything to the data. 22015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 22025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((filter_to_do & PNG_FILTER_NONE) && 22035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filter_to_do != PNG_FILTER_NONE) 22045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep rp; 22065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 sum = 0; 22075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 22085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int v; 22095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) 22115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v = *rp; 22135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum += (v < 128) ? v : 256 - v; 22145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 22175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 22185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 sumhi, sumlo; 22205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 22215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = sum & PNG_LOMASK; 22225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ 22235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Reduce the sum if we match any of the previous rows */ 22255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < num_p_filters; j++) 22265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) 22285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = (sumlo * png_ptr->filter_weights[j]) >> 22305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 22315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sumhi * png_ptr->filter_weights[j]) >> 22325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 22335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Factor in the cost of this filter (this is here for completeness, 22375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * but it makes no sense to have a "cost" for the NONE filter, as 22385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * it has the minimum possible computational cost - none). 22395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 22405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> 22415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 22425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> 22435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 22445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sumhi > PNG_HIMASK) 22465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum = PNG_MAXSUM; 22475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 22485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum = (sumhi << PNG_HISHIFT) + sumlo; 22495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 22515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mins = sum; 22525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Sub filter */ 22555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filter_to_do == PNG_FILTER_SUB) 22565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* It's the only filter so no testing is needed */ 22575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep rp, lp, dp; 22595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 22605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; 22615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i++, rp++, dp++) 22625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp = *rp; 22645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (lp = row_buf + 1; i < row_bytes; 22665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i++, rp++, lp++, dp++) 22675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); 22695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_row = png_ptr->sub_row; 22715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 22725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (filter_to_do & PNG_FILTER_SUB) 22745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep rp, dp, lp; 22765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 sum = 0, lmins = mins; 22775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 22785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int v; 22795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 22815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* We temporarily increase the "minimum sum" by the factor we 22825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * would reduce the sum of this filter, so that we can do the 22835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * early exit comparison without scaling the sum each time. 22845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */ 22855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 22865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 22885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 lmhi, lmlo; 22895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = lmins & PNG_LOMASK; 22905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 22915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < num_p_filters; j++) 22935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) 22955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 22965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 22975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 22985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 22995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 23005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 23045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 23055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 23065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 23075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lmhi > PNG_HIMASK) 23095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmins = PNG_MAXSUM; 23105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 23115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmins = (lmhi << PNG_HISHIFT) + lmlo; 23125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 23145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; 23165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i++, rp++, dp++) 23175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 23185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v = *dp = *rp; 23195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum += (v < 128) ? v : 256 - v; 23215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (lp = row_buf + 1; i < row_bytes; 23235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i++, rp++, lp++, dp++) 23245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 23255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); 23265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum += (v < 128) ? v : 256 - v; 23285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sum > lmins) /* We are already worse, don't continue. */ 23305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 23315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 23345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 23355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 23365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 23375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 sumhi, sumlo; 23385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = sum & PNG_LOMASK; 23395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 23405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < num_p_filters; j++) 23425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 23435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) 23445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 23455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> 23465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 23475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> 23485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 23495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 23535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 23545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> 23555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 23565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sumhi > PNG_HIMASK) 23585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum = PNG_MAXSUM; 23595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 23605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum = (sumhi << PNG_HISHIFT) + sumlo; 23615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 23635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sum < mins) 23655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 23665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mins = sum; 23675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_row = png_ptr->sub_row; 23685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Up filter */ 23725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filter_to_do == PNG_FILTER_UP) 23735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 23745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep rp, dp, pp; 23755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 23765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, 23785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp = prev_row + 1; i < row_bytes; 23795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i++, rp++, pp++, dp++) 23805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 23815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); 23825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_row = png_ptr->up_row; 23845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 23855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (filter_to_do & PNG_FILTER_UP) 23875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 23885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep rp, dp, pp; 23895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 sum = 0, lmins = mins; 23905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 23915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int v; 23925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 23945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 23955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 23965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 23975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 23985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 lmhi, lmlo; 23995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = lmins & PNG_LOMASK; 24005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 24015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < num_p_filters; j++) 24035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) 24055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 24075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 24085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 24095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 24105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> 24145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 24155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> 24165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 24175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lmhi > PNG_HIMASK) 24195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmins = PNG_MAXSUM; 24205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 24215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmins = (lmhi << PNG_HISHIFT) + lmlo; 24225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 24245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, 24265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp = prev_row + 1; i < row_bytes; i++) 24275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); 24295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum += (v < 128) ? v : 256 - v; 24315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sum > lmins) /* We are already worse, don't continue. */ 24335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 24345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 24375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 24385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 24405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 sumhi, sumlo; 24415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = sum & PNG_LOMASK; 24425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 24435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < num_p_filters; j++) 24455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) 24475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = (sumlo * png_ptr->filter_weights[j]) >> 24495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 24505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sumhi * png_ptr->filter_weights[j]) >> 24515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 24525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> 24565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 24575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> 24585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 24595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sumhi > PNG_HIMASK) 24615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum = PNG_MAXSUM; 24625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 24635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum = (sumhi << PNG_HISHIFT) + sumlo; 24645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 24665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sum < mins) 24685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mins = sum; 24705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_row = png_ptr->up_row; 24715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Avg filter */ 24755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filter_to_do == PNG_FILTER_AVG) 24765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep rp, dp, pp, lp; 24785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 24795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, 24805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp = prev_row + 1; i < bpp; i++) 24815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); 24835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (lp = row_buf + 1; i < row_bytes; i++) 24855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) 24875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) & 0xff); 24885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_row = png_ptr->avg_row; 24905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 24915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (filter_to_do & PNG_FILTER_AVG) 24935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 24945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep rp, dp, pp, lp; 24955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 sum = 0, lmins = mins; 24965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 24975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int v; 24985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 24995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 25005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 25015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 25035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 lmhi, lmlo; 25045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = lmins & PNG_LOMASK; 25055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 25065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < num_p_filters; j++) 25085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) 25105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 25125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 25135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 25145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 25155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> 25195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 25205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> 25215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 25225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lmhi > PNG_HIMASK) 25245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmins = PNG_MAXSUM; 25255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 25265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmins = (lmhi << PNG_HISHIFT) + lmlo; 25275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 25295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, 25315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp = prev_row + 1; i < bpp; i++) 25325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); 25345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum += (v < 128) ? v : 256 - v; 25365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (lp = row_buf + 1; i < row_bytes; i++) 25385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v = *dp++ = 25405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff); 25415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum += (v < 128) ? v : 256 - v; 25435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sum > lmins) /* We are already worse, don't continue. */ 25455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 25465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 25495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 25505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 25525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 sumhi, sumlo; 25535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = sum & PNG_LOMASK; 25545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 25555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < num_p_filters; j++) 25575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) 25595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = (sumlo * png_ptr->filter_weights[j]) >> 25615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 25625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sumhi * png_ptr->filter_weights[j]) >> 25635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 25645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> 25685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 25695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> 25705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 25715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sumhi > PNG_HIMASK) 25735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum = PNG_MAXSUM; 25745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 25755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum = (sumhi << PNG_HISHIFT) + sumlo; 25765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 25785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sum < mins) 25805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mins = sum; 25825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_row = png_ptr->avg_row; 25835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Paeth filter */ 25875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (filter_to_do == PNG_FILTER_PAETH) 25885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep rp, dp, pp, cp, lp; 25905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 25915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, 25925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp = prev_row + 1; i < bpp; i++) 25935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); 25955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 25965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 25975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) 25985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 25995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int a, b, c, pa, pb, pc, p; 26005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) b = *pp++; 26025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c = *cp++; 26035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a = *lp++; 26045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = b - c; 26065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pc = a - c; 26075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_ABS 26095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pa = abs(p); 26105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pb = abs(pc); 26115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pc = abs(p + pc); 26125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 26135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pa = p < 0 ? -p : p; 26145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pb = pc < 0 ? -pc : pc; 26155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pc = (p + pc) < 0 ? -(p + pc) : p + pc; 26165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; 26195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); 26215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_row = png_ptr->paeth_row; 26235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (filter_to_do & PNG_FILTER_PAETH) 26265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 26275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep rp, dp, pp, cp, lp; 26285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 sum = 0, lmins = mins; 26295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 i; 26305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int v; 26315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 26335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 26345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 26355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 26365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 lmhi, lmlo; 26375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = lmins & PNG_LOMASK; 26385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; 26395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < num_p_filters; j++) 26415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 26425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) 26435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 26445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> 26455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 26465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> 26475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 26485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> 26525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 26535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> 26545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 26555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (lmhi > PNG_HIMASK) 26575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmins = PNG_MAXSUM; 26585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 26595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lmins = (lmhi << PNG_HISHIFT) + lmlo; 26605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, 26645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pp = prev_row + 1; i < bpp; i++) 26655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 26665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); 26675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum += (v < 128) ? v : 256 - v; 26695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 26705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) 26725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 26735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int a, b, c, pa, pb, pc, p; 26745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) b = *pp++; 26765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c = *cp++; 26775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) a = *lp++; 26785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef PNG_SLOW_PAETH 26805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = b - c; 26815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pc = a - c; 26825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_USE_ABS 26835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pa = abs(p); 26845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pb = abs(pc); 26855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pc = abs(p + pc); 26865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 26875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pa = p < 0 ? -p : p; 26885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pb = pc < 0 ? -pc : pc; 26895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pc = (p + pc) < 0 ? -(p + pc) : p + pc; 26905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 26915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; 26925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else /* PNG_SLOW_PAETH */ 26935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = a + b - c; 26945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pa = abs(p - a); 26955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pb = abs(p - b); 26965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pc = abs(p - c); 26975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (pa <= pb && pa <= pc) 26985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = a; 26995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else if (pb <= pc) 27005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = b; 27015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 27025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p = c; 27035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_SLOW_PAETH */ 27045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); 27065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum += (v < 128) ? v : 256 - v; 27085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sum > lmins) /* We are already worse, don't continue. */ 27105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 27115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 27145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) 27155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 27165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 27175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_uint_32 sumhi, sumlo; 27185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = sum & PNG_LOMASK; 27195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; 27205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 0; j < num_p_filters; j++) 27225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 27235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) 27245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 27255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = (sumlo * png_ptr->filter_weights[j]) >> 27265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 27275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sumhi * png_ptr->filter_weights[j]) >> 27285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_WEIGHT_SHIFT; 27295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> 27335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 27345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> 27355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PNG_COST_SHIFT; 27365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sumhi > PNG_HIMASK) 27385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum = PNG_MAXSUM; 27395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 27405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sum = (sumhi << PNG_HISHIFT) + sumlo; 27415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 27435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (sum < mins) 27455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 27465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) best_row = png_ptr->paeth_row; 27475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_WRITE_FILTER_SUPPORTED */ 27505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Do the actual writing of the filtered row data from the chosen filter. */ 27515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_filtered_row(png_ptr, best_row); 27535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_FILTER_SUPPORTED 27555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED 27565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Save the type of filter we picked this time for future calculations */ 27575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->num_prev_filters > 0) 27585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 27595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int j; 27605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (j = 1; j < num_p_filters; j++) 27615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 27625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; 27635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->prev_filters[j] = best_row[0]; 27655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 27675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_WRITE_FILTER_SUPPORTED */ 27685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 27695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* Do the actual writing of a previously filtered row. */ 27725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void /* PRIVATE */ 27735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row) 27745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){ 27755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug(1, "in png_write_filtered_row"); 27765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_debug1(2, "filter = %d", filtered_row[0]); 27785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Set up the zlib input buffer */ 27795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.next_in = filtered_row; 27815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1; 27825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Repeat until we have compressed all the data */ 27835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) do 27845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 27855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int ret; /* Return of zlib */ 27865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Compress the data */ 27885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = deflate(&png_ptr->zstream, Z_NO_FLUSH); 27895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Check for compression errors */ 27905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (ret != Z_OK) 27915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 27925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->zstream.msg != NULL) 27935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, png_ptr->zstream.msg); 27945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 27955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_error(png_ptr, "zlib error"); 27965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 27975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 27985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* See if it is time to write another IDAT */ 27995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!(png_ptr->zstream.avail_out)) 28005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 28015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Write the IDAT and reset the zlib output buffer */ 28025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size); 28035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.next_out = png_ptr->zbuf; 28045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; 28055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Repeat until all data has been compressed */ 28075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } while (png_ptr->zstream.avail_in); 28085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Swap the current and previous rows */ 28105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->prev_row != NULL) 28115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 28125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_bytep tptr; 28135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) tptr = png_ptr->prev_row; 28155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->prev_row = png_ptr->row_buf; 28165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->row_buf = tptr; 28175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) /* Finish row - updates counters and flushes zlib if last row */ 28205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_finish_row(png_ptr); 28215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifdef PNG_WRITE_FLUSH_SUPPORTED 28235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->flush_rows++; 28245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 28255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (png_ptr->flush_dist > 0 && 28265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_ptr->flush_rows >= png_ptr->flush_dist) 28275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 28285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) png_write_flush(png_ptr); 28295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 28305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 28315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 28325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif /* PNG_WRITE_SUPPORTED */ 2833