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