18b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
28b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* pngwutil.c - utilities to write a PNG file
38b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
48b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Last changed in libpng 1.2.19 August 18, 2007
58b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * For conditions of distribution and use, see copyright notice in png.h
68b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Copyright (c) 1998-2007 Glenn Randers-Pehrson
78b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
88b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
98b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PNG_INTERNAL
128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#include "png.h"
138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_WRITE_SUPPORTED
148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Place a 32-bit number into a buffer in PNG byte order.  We work
168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * with unsigned numbers for convenience, although one supported
178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * ancillary chunk uses signed (two's complement) numbers.
188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid PNGAPI
208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_save_uint_32(png_bytep buf, png_uint_32 i)
218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[0] = (png_byte)((i >> 24) & 0xff);
238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[1] = (png_byte)((i >> 16) & 0xff);
248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[2] = (png_byte)((i >> 8) & 0xff);
258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[3] = (png_byte)(i & 0xff);
268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* The png_save_int_32 function assumes integers are stored in two's
298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * complement format.  If this isn't the case, then this routine needs to
308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * be modified to write data in two's complement format.
318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid PNGAPI
338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_save_int_32(png_bytep buf, png_int_32 i)
348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[0] = (png_byte)((i >> 24) & 0xff);
368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[1] = (png_byte)((i >> 16) & 0xff);
378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[2] = (png_byte)((i >> 8) & 0xff);
388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[3] = (png_byte)(i & 0xff);
398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Place a 16-bit number into a buffer in PNG byte order.
428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The parameter is declared unsigned int, not png_uint_16,
438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * just to avoid potential problems on pre-ANSI C compilers.
448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid PNGAPI
468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_save_uint_16(png_bytep buf, unsigned int i)
478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[0] = (png_byte)((i >> 8) & 0xff);
498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[1] = (png_byte)(i & 0xff);
508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Write a PNG chunk all at once.  The type is an array of ASCII characters
538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * representing the chunk name.  The array must be at least 4 bytes in
548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * length, and does not need to be null terminated.  To be safe, pass the
558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * pre-defined chunk names here, and if you need a new one, define it
568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * where the others are defined.  The length is the length of the data.
578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * All the data must be present.  If that is not possible, use the
588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * functions instead.
608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid PNGAPI
628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_chunk(png_structp png_ptr, png_bytep chunk_name,
638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_bytep data, png_size_t length)
648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if(png_ptr == NULL) return;
668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length);
678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, data, length);
688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_end(png_ptr);
698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Write the start of a PNG chunk.  The type is the chunk type.
728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The total_length is the sum of the lengths of all the data you will be
738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * passing in png_write_chunk_data().
748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid PNGAPI
768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_chunk_start(png_structp png_ptr, png_bytep chunk_name,
778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_uint_32 length)
788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[4];
808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug2(0, "Writing %s chunk (%lu bytes)\n", chunk_name, length);
818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if(png_ptr == NULL) return;
828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write the length */
848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf, length);
858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_data(png_ptr, buf, (png_size_t)4);
868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write the chunk name */
888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_data(png_ptr, chunk_name, (png_size_t)4);
898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* reset the crc and run it over the chunk name */
908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_reset_crc(png_ptr);
918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_calculate_crc(png_ptr, chunk_name, (png_size_t)4);
928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Write the data of a PNG chunk started with png_write_chunk_start().
958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * Note that multiple calls to this function are allowed, and that the
968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sum of the lengths from these calls *must* add up to the total_length
978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * given to png_write_chunk_start().
988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid PNGAPI
1008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length)
1018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write the data, and run the CRC over it */
1038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if(png_ptr == NULL) return;
1048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (data != NULL && length > 0)
1058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
1068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_calculate_crc(png_ptr, data, length);
1078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_data(png_ptr, data, length);
1088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
1098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Finish a chunk started with png_write_chunk_start(). */
1128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid PNGAPI
1138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_chunk_end(png_structp png_ptr)
1148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[4];
1168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if(png_ptr == NULL) return;
1188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write the crc */
1208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf, png_ptr->crc);
1218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_data(png_ptr, buf, (png_size_t)4);
1238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Simple function to write the signature.  If we have already written
1268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * the magic bytes of the signature, or more likely, the PNG stream is
1278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * being embedded into another stream and doesn't need its own signature,
1288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * we should call png_set_sig_bytes() to tell libpng how many of the
1298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * bytes have already been written.
1308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
1318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
1328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_sig(png_structp png_ptr)
1338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
1358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write the rest of the 8 byte signature */
1368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
1378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      (png_size_t)8 - png_ptr->sig_bytes);
1388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if(png_ptr->sig_bytes < 3)
1398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
1408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
1418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED)
1438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/*
1448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * This pair of functions encapsulates the operation of (a) compressing a
1458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * text string, and (b) issuing it later as a series of chunk data writes.
1468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The compression_state structure is shared context for these functions
1478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * set up by the caller in order to make the whole mess thread-safe.
1488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
1498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projecttypedef struct
1518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    char *input;   /* the uncompressed input data */
1538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int input_len;   /* its length */
1548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int num_output_ptr; /* number of output pointers used */
1558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    int max_output_ptr; /* size of output_ptr */
1568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    png_charpp output_ptr; /* array of pointers to output */
1578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project} compression_state;
1588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* compress given text into storage in the png_ptr structure */
1608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic int /* PRIVATE */
1618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_text_compress(png_structp png_ptr,
1628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        png_charp text, png_size_t text_len, int compression,
1638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        compression_state *comp)
1648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
1658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int ret;
1668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp->num_output_ptr = 0;
1688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp->max_output_ptr = 0;
1698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp->output_ptr = NULL;
1708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp->input = NULL;
1718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp->input_len = 0;
1728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* we may just want to pass the text right through */
1748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (compression == PNG_TEXT_COMPRESSION_NONE)
1758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
1768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       comp->input = text;
1778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       comp->input_len = text_len;
1788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       return((int)text_len);
1798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
1808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (compression >= PNG_TEXT_COMPRESSION_LAST)
1828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
1838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
1848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      char msg[50];
1858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_snprintf(msg, 50, "Unknown compression type %d", compression);
1868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, msg);
1878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
1888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Unknown compression type");
1898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
1908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
1918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
1928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* We can't write the chunk until we find out how much data we have,
1938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * which means we need to run the compressor first and save the
1948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * output.  This shouldn't be a problem, as the vast majority of
1958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * comments should be reasonable, but we will set up an array of
1968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * malloc'd pointers to be sure.
1978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *
1988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * If we knew the application was well behaved, we could simplify this
1998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * greatly by assuming we can always malloc an output buffer large
2008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
2018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * and malloc this directly.  The only time this would be a bad idea is
2028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * if we can't malloc more than 64K and we have 64K of random input
2038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * data, or if the input string is incredibly large (although this
2048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * wouldn't cause a failure, just a slowdown due to swapping).
2058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
2068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* set up the compression buffers */
2088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.avail_in = (uInt)text_len;
2098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.next_in = (Bytef *)text;
2108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
2118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;
2128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* this is the same compression loop as in png_write_row() */
2148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   do
2158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
2168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* compress the data */
2178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
2188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (ret != Z_OK)
2198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
2208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* error */
2218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (png_ptr->zstream.msg != NULL)
2228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_error(png_ptr, png_ptr->zstream.msg);
2238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
2248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_error(png_ptr, "zlib error");
2258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
2268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* check to see if we need more room */
2278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (!(png_ptr->zstream.avail_out))
2288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
2298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* make sure the output array has room */
2308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (comp->num_output_ptr >= comp->max_output_ptr)
2318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
2328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int old_max;
2338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            old_max = comp->max_output_ptr;
2358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            comp->max_output_ptr = comp->num_output_ptr + 4;
2368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (comp->output_ptr != NULL)
2378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
2388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_charpp old_ptr;
2398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               old_ptr = comp->output_ptr;
2418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               comp->output_ptr = (png_charpp)png_malloc(png_ptr,
2428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  (png_uint_32)(comp->max_output_ptr *
2438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  png_sizeof (png_charpp)));
2448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_memcpy(comp->output_ptr, old_ptr, old_max
2458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  * png_sizeof (png_charp));
2468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_free(png_ptr, old_ptr);
2478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
2488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            else
2498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               comp->output_ptr = (png_charpp)png_malloc(png_ptr,
2508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  (png_uint_32)(comp->max_output_ptr *
2518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  png_sizeof (png_charp)));
2528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
2538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* save the data */
2558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         comp->output_ptr[comp->num_output_ptr] = (png_charp)png_malloc(png_ptr,
2568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            (png_uint_32)png_ptr->zbuf_size);
2578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
2588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_ptr->zbuf_size);
2598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         comp->num_output_ptr++;
2608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* and reset the buffer */
2628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
2638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->zstream.next_out = png_ptr->zbuf;
2648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
2658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* continue until we don't have any more to compress */
2668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   } while (png_ptr->zstream.avail_in);
2678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* finish the compression */
2698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   do
2708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
2718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* tell zlib we are finished */
2728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      ret = deflate(&png_ptr->zstream, Z_FINISH);
2738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (ret == Z_OK)
2758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
2768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* check to see if we need more room */
2778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (!(png_ptr->zstream.avail_out))
2788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
2798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* check to make sure our output array has room */
2808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (comp->num_output_ptr >= comp->max_output_ptr)
2818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
2828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               int old_max;
2838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               old_max = comp->max_output_ptr;
2858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               comp->max_output_ptr = comp->num_output_ptr + 4;
2868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               if (comp->output_ptr != NULL)
2878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               {
2888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  png_charpp old_ptr;
2898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
2908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  old_ptr = comp->output_ptr;
2918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  /* This could be optimized to realloc() */
2928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
2938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     (png_uint_32)(comp->max_output_ptr *
2948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     png_sizeof (png_charpp)));
2958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  png_memcpy(comp->output_ptr, old_ptr,
2968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     old_max * png_sizeof (png_charp));
2978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  png_free(png_ptr, old_ptr);
2988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               }
2998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               else
3008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  comp->output_ptr = (png_charpp)png_malloc(png_ptr,
3018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     (png_uint_32)(comp->max_output_ptr *
3028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                     png_sizeof (png_charp)));
3038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
3048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* save off the data */
3068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            comp->output_ptr[comp->num_output_ptr] =
3078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               (png_charp)png_malloc(png_ptr, (png_uint_32)png_ptr->zbuf_size);
3088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
3098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_ptr->zbuf_size);
3108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            comp->num_output_ptr++;
3118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* and reset the buffer pointers */
3138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
3148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_ptr->zstream.next_out = png_ptr->zbuf;
3158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
3168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
3178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      else if (ret != Z_STREAM_END)
3188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
3198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* we got an error */
3208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (png_ptr->zstream.msg != NULL)
3218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_error(png_ptr, png_ptr->zstream.msg);
3228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
3238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_error(png_ptr, "zlib error");
3248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
3258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   } while (ret != Z_STREAM_END);
3268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* text length is number of buffers plus last buffer */
3288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   text_len = png_ptr->zbuf_size * comp->num_output_ptr;
3298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
3308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
3318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return((int)text_len);
3338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* ship the compressed text out via chunk writes */
3368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectstatic void /* PRIVATE */
3378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
3388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int i;
3408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* handle the no-compression case */
3428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (comp->input)
3438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
3448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       png_write_chunk_data(png_ptr, (png_bytep)comp->input,
3458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                            (png_size_t)comp->input_len);
3468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       return;
3478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
3488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write saved output buffers, if any */
3508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for (i = 0; i < comp->num_output_ptr; i++)
3518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
3528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk_data(png_ptr,(png_bytep)comp->output_ptr[i],
3538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->zbuf_size);
3548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_free(png_ptr, comp->output_ptr[i]);
3558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      comp->output_ptr[i]=NULL;
3568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
3578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (comp->max_output_ptr != 0)
3588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_free(png_ptr, comp->output_ptr);
3598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      comp->output_ptr=NULL;
3608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write anything left in zbuf */
3618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
3628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk_data(png_ptr, png_ptr->zbuf,
3638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->zbuf_size - png_ptr->zstream.avail_out);
3648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* reset zlib for another zTXt/iTXt or image data */
3668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   deflateReset(&png_ptr->zstream);
3678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.data_type = Z_BINARY;
3688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
3698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Write the IHDR chunk, and update the png_struct with the necessary
3728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * information.  Note that the rest of this code depends upon this
3738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * information being correct.
3748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
3758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
3768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
3778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int bit_depth, int color_type, int compression_type, int filter_type,
3788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int interlace_type)
3798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
3808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
3818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_IHDR;
3828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
3838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[13]; /* buffer to store the IHDR info */
3848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
3858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_IHDR\n");
3868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Check that we have valid input data from the application info */
3878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   switch (color_type)
3888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
3898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case PNG_COLOR_TYPE_GRAY:
3908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         switch (bit_depth)
3918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
3928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1:
3938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2:
3948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4:
3958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 8:
3968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 16: png_ptr->channels = 1; break;
3978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: png_error(png_ptr,"Invalid bit depth for grayscale image");
3988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
3998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         break;
4008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case PNG_COLOR_TYPE_RGB:
4018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (bit_depth != 8 && bit_depth != 16)
4028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_error(png_ptr, "Invalid bit depth for RGB image");
4038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->channels = 3;
4048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         break;
4058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case PNG_COLOR_TYPE_PALETTE:
4068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         switch (bit_depth)
4078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
4088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 1:
4098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 2:
4108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 4:
4118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            case 8: png_ptr->channels = 1; break;
4128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            default: png_error(png_ptr, "Invalid bit depth for paletted image");
4138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
4148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         break;
4158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case PNG_COLOR_TYPE_GRAY_ALPHA:
4168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (bit_depth != 8 && bit_depth != 16)
4178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
4188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->channels = 2;
4198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         break;
4208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      case PNG_COLOR_TYPE_RGB_ALPHA:
4218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (bit_depth != 8 && bit_depth != 16)
4228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_error(png_ptr, "Invalid bit depth for RGBA image");
4238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->channels = 4;
4248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         break;
4258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      default:
4268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_error(png_ptr, "Invalid image color type specified");
4278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
4288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
4308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
4318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid compression type specified");
4328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      compression_type = PNG_COMPRESSION_TYPE_BASE;
4338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
4348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Write filter_method 64 (intrapixel differencing) only if
4368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
4378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * 2. Libpng did not write a PNG signature (this filter_method is only
4388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *    used in PNG datastreams that are embedded in MNG datastreams) and
4398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * 3. The application called png_permit_mng_features with a mask that
4408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *    included PNG_FLAG_MNG_FILTER_64 and
4418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * 4. The filter_method is 64 and
4428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * 5. The color_type is RGB or RGBA
4438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
4448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (
4458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_MNG_FEATURES_SUPPORTED)
4468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
4478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
4488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      (color_type == PNG_COLOR_TYPE_RGB ||
4498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
4508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
4518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      filter_type != PNG_FILTER_TYPE_BASE)
4538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
4548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid filter type specified");
4558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      filter_type = PNG_FILTER_TYPE_BASE;
4568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
4578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_WRITE_INTERLACING_SUPPORTED
4598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (interlace_type != PNG_INTERLACE_NONE &&
4608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      interlace_type != PNG_INTERLACE_ADAM7)
4618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
4628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid interlace type specified");
4638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      interlace_type = PNG_INTERLACE_ADAM7;
4648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
4658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
4668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   interlace_type=PNG_INTERLACE_NONE;
4678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* save off the relevent information */
4708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->bit_depth = (png_byte)bit_depth;
4718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->color_type = (png_byte)color_type;
4728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->interlaced = (png_byte)interlace_type;
4738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_MNG_FEATURES_SUPPORTED)
4748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->filter_type = (png_byte)filter_type;
4758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
4768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->compression_type = (png_byte)compression_type;
4778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->width = width;
4788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->height = height;
4798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
4818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
4828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* set the usr info, so any transformations can modify it */
4838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->usr_width = png_ptr->width;
4848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->usr_bit_depth = png_ptr->bit_depth;
4858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->usr_channels = png_ptr->channels;
4868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* pack the header information into the buffer */
4888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf, width);
4898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 4, height);
4908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[8] = (png_byte)bit_depth;
4918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[9] = (png_byte)color_type;
4928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[10] = (png_byte)compression_type;
4938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[11] = (png_byte)filter_type;
4948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[12] = (png_byte)interlace_type;
4958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write the chunk */
4978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13);
4988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
4998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* initialize zlib with PNG info */
5008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.zalloc = png_zalloc;
5018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.zfree = png_zfree;
5028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.opaque = (voidpf)png_ptr;
5038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!(png_ptr->do_filter))
5048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
5058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
5068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->bit_depth < 8)
5078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->do_filter = PNG_FILTER_NONE;
5088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      else
5098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->do_filter = PNG_ALL_FILTERS;
5108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
5118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
5128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
5138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->do_filter != PNG_FILTER_NONE)
5148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->zlib_strategy = Z_FILTERED;
5158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      else
5168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
5178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
5188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
5198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
5208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
5218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->zlib_mem_level = 8;
5228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
5238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->zlib_window_bits = 15;
5248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
5258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->zlib_method = 8;
5268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
5278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->zlib_method, png_ptr->zlib_window_bits,
5288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->zlib_mem_level, png_ptr->zlib_strategy) != Z_OK)
5298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       png_error(png_ptr, "zlib failed to initialize compressor");
5308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.next_out = png_ptr->zbuf;
5318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
5328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* libpng is not interested in zstream.data_type */
5338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* set it to a predefined value, to avoid its evaluation inside zlib */
5348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.data_type = Z_BINARY;
5358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->mode = PNG_HAVE_IHDR;
5378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
5388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write the palette.  We are careful not to trust png_color to be in the
5408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * correct order for PNG, so people can redefine it to any convenient
5418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * structure.
5428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
5438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
5448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
5458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
5468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
5478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_PLTE;
5488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_uint_32 i;
5508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_colorp pal_ptr;
5518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[3];
5528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_PLTE\n");
5548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if ((
5558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_MNG_FEATURES_SUPPORTED)
5568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
5578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
5588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        num_pal == 0) || num_pal > 256)
5598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
5608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
5618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     {
5628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        png_error(png_ptr, "Invalid number of colors in palette");
5638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     }
5648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     else
5658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     {
5668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        png_warning(png_ptr, "Invalid number of colors in palette");
5678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
5688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     }
5698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
5708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
5728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
5738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr,
5748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        "Ignoring request to write a PLTE chunk in grayscale PNG");
5758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
5768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
5778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->num_palette = (png_uint_16)num_pal;
5798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug1(3, "num_palette = %d\n", png_ptr->num_palette);
5808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
5818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_start(png_ptr, png_PLTE, num_pal * 3);
5828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef PNG_NO_POINTER_INDEXING
5838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
5848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
5858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[0] = pal_ptr->red;
5868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[1] = pal_ptr->green;
5878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[2] = pal_ptr->blue;
5888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
5898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
5908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
5918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* This is a little slower but some buggy compilers need to do this instead */
5928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   pal_ptr=palette;
5938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for (i = 0; i < num_pal; i++)
5948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
5958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[0] = pal_ptr[i].red;
5968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[1] = pal_ptr[i].green;
5978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[2] = pal_ptr[i].blue;
5988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
5998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
6008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_end(png_ptr);
6028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->mode |= PNG_HAVE_PLTE;
6038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write an IDAT chunk */
6068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
6078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
6088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
6108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_IDAT;
6118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_IDAT\n");
6138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Optimize the CMF field in the zlib stream. */
6158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* This hack of the zlib stream is compliant to the stream specification. */
6168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
6178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
6188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
6198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      unsigned int z_cmf = data[0];  /* zlib compression method and flags */
6208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
6218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
6228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* Avoid memory underflows and multiplication overflows. */
6238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* The conditions below are practically always satisfied;
6248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            however, they still must be checked. */
6258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (length >= 2 &&
6268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project             png_ptr->height < 16384 && png_ptr->width < 16384)
6278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
6288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_uint_32 uncompressed_idat_size = png_ptr->height *
6298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               ((png_ptr->width *
6308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
6318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unsigned int z_cinfo = z_cmf >> 4;
6328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            unsigned int half_z_window_size = 1 << (z_cinfo + 7);
6338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            while (uncompressed_idat_size <= half_z_window_size &&
6348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   half_z_window_size >= 256)
6358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
6368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               z_cinfo--;
6378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               half_z_window_size >>= 1;
6388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
6398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
6408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (data[0] != (png_byte)z_cmf)
6418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
6428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               data[0] = (png_byte)z_cmf;
6438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               data[1] &= 0xe0;
6448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f);
6458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
6468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
6478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
6488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      else
6498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_error(png_ptr,
6508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "Invalid zlib compression method or flags in IDAT");
6518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
6528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length);
6548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->mode |= PNG_HAVE_IDAT;
6558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write an IEND chunk */
6588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
6598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_IEND(png_structp png_ptr)
6608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
6628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_IEND;
6638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_IEND\n");
6658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL,
6668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     (png_size_t)0);
6678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->mode |= PNG_HAVE_IEND;
6688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_gAMA_SUPPORTED)
6718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write a gAMA chunk */
6728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_FLOATING_POINT_SUPPORTED
6738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
6748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_gAMA(png_structp png_ptr, double file_gamma)
6758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
6778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_gAMA;
6788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_uint_32 igamma;
6808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[4];
6818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_gAMA\n");
6838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* file_gamma is saved in 1/100,000ths */
6848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5);
6858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf, igamma);
6868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
6878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
6888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_FIXED_POINT_SUPPORTED
6908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
6918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
6928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
6938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
6948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_gAMA;
6958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
6968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[4];
6978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
6988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_gAMA\n");
6998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* file_gamma is saved in 1/100,000ths */
7008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf, (png_uint_32)file_gamma);
7018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
7028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
7048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
7058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_sRGB_SUPPORTED)
7078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write a sRGB chunk */
7088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
7098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_sRGB(png_structp png_ptr, int srgb_intent)
7108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
7128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_sRGB;
7138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
7148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[1];
7158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_sRGB\n");
7178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if(srgb_intent >= PNG_sRGB_INTENT_LAST)
7188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_warning(png_ptr,
7198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            "Invalid sRGB rendering intent specified");
7208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[0]=(png_byte)srgb_intent;
7218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1);
7228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
7248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_iCCP_SUPPORTED)
7268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write an iCCP chunk */
7278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
7288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
7298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_charp profile, int profile_len)
7308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
7318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
7328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_iCCP;
7338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
7348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t name_len;
7358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_charp new_name;
7368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   compression_state comp;
7378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int embedded_profile_len = 0;
7388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_iCCP\n");
7408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.num_output_ptr = 0;
7428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.max_output_ptr = 0;
7438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.output_ptr = NULL;
7448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.input = NULL;
7458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.input_len = 0;
7468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (name == NULL || (name_len = png_check_keyword(png_ptr, name,
7488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      &new_name)) == 0)
7498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
7508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Empty keyword in iCCP chunk");
7518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
7528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
7538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
7558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Unknown compression type in iCCP chunk");
7568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (profile == NULL)
7588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      profile_len = 0;
7598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (profile_len > 3)
7618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      embedded_profile_len =
7628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          ((*( (png_bytep)profile  ))<<24) |
7638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          ((*( (png_bytep)profile+1))<<16) |
7648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          ((*( (png_bytep)profile+2))<< 8) |
7658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          ((*( (png_bytep)profile+3))    );
7668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (profile_len < embedded_profile_len)
7688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     {
7698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        png_warning(png_ptr,
7708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          "Embedded profile length too large in iCCP chunk");
7718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        return;
7728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     }
7738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (profile_len > embedded_profile_len)
7758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     {
7768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        png_warning(png_ptr,
7778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          "Truncating profile to actual length in iCCP chunk");
7788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        profile_len = embedded_profile_len;
7798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     }
7808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (profile_len)
7828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       profile_len = png_text_compress(png_ptr, profile, (png_size_t)profile_len,
7838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          PNG_COMPRESSION_TYPE_BASE, &comp);
7848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* make sure we include the NULL after the name and the compression type */
7868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_start(png_ptr, png_iCCP,
7878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          (png_uint_32)name_len+profile_len+2);
7888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   new_name[name_len+1]=0x00;
7898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 2);
7908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (profile_len)
7928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_compressed_data_out(png_ptr, &comp);
7938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_end(png_ptr);
7958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_free(png_ptr, new_name);
7968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
7978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
7988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
7998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_sPLT_SUPPORTED)
8008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write a sPLT chunk */
8018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
8028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
8038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
8058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_sPLT;
8068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t name_len;
8088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_charp new_name;
8098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte entrybuf[10];
8108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int entry_size = (spalette->depth == 8 ? 6 : 10);
8118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int palette_size = entry_size * spalette->nentries;
8128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_sPLT_entryp ep;
8138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_NO_POINTER_INDEXING
8148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int i;
8158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_sPLT\n");
8188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (spalette->name == NULL || (name_len = png_check_keyword(png_ptr,
8198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      spalette->name, &new_name))==0)
8208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
8218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Empty keyword in sPLT chunk");
8228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
8238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
8248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* make sure we include the NULL after the name */
8268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_start(png_ptr, png_sPLT,
8278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          (png_uint_32)(name_len + 2 + palette_size));
8288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, (png_bytep)new_name, name_len + 1);
8298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, 1);
8308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* loop through each palette entry, writing appropriately */
8328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef PNG_NO_POINTER_INDEXING
8338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for (ep = spalette->entries; ep<spalette->entries+spalette->nentries; ep++)
8348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
8358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       if (spalette->depth == 8)
8368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       {
8378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           entrybuf[0] = (png_byte)ep->red;
8388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           entrybuf[1] = (png_byte)ep->green;
8398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           entrybuf[2] = (png_byte)ep->blue;
8408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           entrybuf[3] = (png_byte)ep->alpha;
8418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 4, ep->frequency);
8428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       }
8438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       else
8448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       {
8458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 0, ep->red);
8468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 2, ep->green);
8478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 4, ep->blue);
8488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 6, ep->alpha);
8498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 8, ep->frequency);
8508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       }
8518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
8528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
8538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
8548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   ep=spalette->entries;
8558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for (i=0; i>spalette->nentries; i++)
8568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
8578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       if (spalette->depth == 8)
8588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       {
8598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           entrybuf[0] = (png_byte)ep[i].red;
8608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           entrybuf[1] = (png_byte)ep[i].green;
8618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           entrybuf[2] = (png_byte)ep[i].blue;
8628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           entrybuf[3] = (png_byte)ep[i].alpha;
8638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 4, ep[i].frequency);
8648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       }
8658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       else
8668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       {
8678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 0, ep[i].red);
8688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 2, ep[i].green);
8698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 4, ep[i].blue);
8708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 6, ep[i].alpha);
8718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           png_save_uint_16(entrybuf + 8, ep[i].frequency);
8728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       }
8738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       png_write_chunk_data(png_ptr, entrybuf, entry_size);
8748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
8758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_end(png_ptr);
8788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_free(png_ptr, new_name);
8798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
8808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_sBIT_SUPPORTED)
8838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write the sBIT chunk */
8848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
8858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
8868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
8878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
8888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_sBIT;
8898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
8908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[4];
8918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t size;
8928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_sBIT\n");
8948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* make sure we don't depend upon the order of PNG_COLOR_8 */
8958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (color_type & PNG_COLOR_MASK_COLOR)
8968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
8978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_byte maxbits;
8988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
8998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
9008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                png_ptr->usr_bit_depth);
9018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (sbit->red == 0 || sbit->red > maxbits ||
9028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          sbit->green == 0 || sbit->green > maxbits ||
9038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          sbit->blue == 0 || sbit->blue > maxbits)
9048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
9058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_warning(png_ptr, "Invalid sBIT depth specified");
9068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         return;
9078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
9088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[0] = sbit->red;
9098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[1] = sbit->green;
9108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[2] = sbit->blue;
9118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      size = 3;
9128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
9138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else
9148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
9158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
9168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
9178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_warning(png_ptr, "Invalid sBIT depth specified");
9188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         return;
9198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
9208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[0] = sbit->gray;
9218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      size = 1;
9228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
9238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (color_type & PNG_COLOR_MASK_ALPHA)
9258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
9268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
9278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
9288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_warning(png_ptr, "Invalid sBIT depth specified");
9298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         return;
9308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
9318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[size++] = sbit->alpha;
9328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
9338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size);
9358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
9368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_cHRM_SUPPORTED)
9398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write the cHRM chunk */
9408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_FLOATING_POINT_SUPPORTED
9418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
9428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_cHRM(png_structp png_ptr, double white_x, double white_y,
9438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   double red_x, double red_y, double green_x, double green_y,
9448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   double blue_x, double blue_y)
9458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
9468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
9478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_cHRM;
9488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[32];
9508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_uint_32 itemp;
9518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_cHRM\n");
9538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* each value is saved in 1/100,000ths */
9548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (white_x < 0 || white_x > 0.8 || white_y < 0 || white_y > 0.8 ||
9558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       white_x + white_y > 1.0)
9568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
9578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid cHRM white point specified");
9588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(PNG_NO_CONSOLE_IO)
9598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      fprintf(stderr,"white_x=%f, white_y=%f\n",white_x, white_y);
9608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
9618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
9628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
9638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   itemp = (png_uint_32)(white_x * 100000.0 + 0.5);
9648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf, itemp);
9658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   itemp = (png_uint_32)(white_y * 100000.0 + 0.5);
9668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 4, itemp);
9678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (red_x < 0 ||  red_y < 0 || red_x + red_y > 1.0)
9698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
9708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid cHRM red point specified");
9718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
9728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
9738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   itemp = (png_uint_32)(red_x * 100000.0 + 0.5);
9748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 8, itemp);
9758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   itemp = (png_uint_32)(red_y * 100000.0 + 0.5);
9768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 12, itemp);
9778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (green_x < 0 || green_y < 0 || green_x + green_y > 1.0)
9798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
9808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid cHRM green point specified");
9818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
9828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
9838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   itemp = (png_uint_32)(green_x * 100000.0 + 0.5);
9848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 16, itemp);
9858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   itemp = (png_uint_32)(green_y * 100000.0 + 0.5);
9868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 20, itemp);
9878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (blue_x < 0 || blue_y < 0 || blue_x + blue_y > 1.0)
9898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
9908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid cHRM blue point specified");
9918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
9928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
9938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   itemp = (png_uint_32)(blue_x * 100000.0 + 0.5);
9948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 24, itemp);
9958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   itemp = (png_uint_32)(blue_y * 100000.0 + 0.5);
9968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 28, itemp);
9978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
9988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
9998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
10018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_FIXED_POINT_SUPPORTED
10028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
10038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
10048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
10058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
10068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_fixed_point blue_y)
10078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
10098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_cHRM;
10108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
10118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[32];
10128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_cHRM\n");
10148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* each value is saved in 1/100,000ths */
10158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (white_x > 80000L || white_y > 80000L || white_x + white_y > 100000L)
10168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
10178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid fixed cHRM white point specified");
10188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(PNG_NO_CONSOLE_IO)
10198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      fprintf(stderr,"white_x=%ld, white_y=%ld\n",white_x, white_y);
10208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
10218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
10228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
10238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf, (png_uint_32)white_x);
10248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 4, (png_uint_32)white_y);
10258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (red_x + red_y > 100000L)
10278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
10288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid cHRM fixed red point specified");
10298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
10308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
10318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 8, (png_uint_32)red_x);
10328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 12, (png_uint_32)red_y);
10338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (green_x + green_y > 100000L)
10358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
10368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid fixed cHRM green point specified");
10378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
10388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
10398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 16, (png_uint_32)green_x);
10408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 20, (png_uint_32)green_y);
10418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (blue_x + blue_y > 100000L)
10438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
10448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid fixed cHRM blue point specified");
10458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
10468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
10478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 24, (png_uint_32)blue_x);
10488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 28, (png_uint_32)blue_y);
10498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
10518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
10528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
10538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
10548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_tRNS_SUPPORTED)
10568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write the tRNS chunk */
10578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
10588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
10598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int num_trans, int color_type)
10608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
10618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
10628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_tRNS;
10638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
10648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[6];
10658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
10668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_tRNS\n");
10678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (color_type == PNG_COLOR_TYPE_PALETTE)
10688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
10698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
10708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
10718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_warning(png_ptr,"Invalid number of transparent colors specified");
10728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         return;
10738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
10748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* write the chunk out as it is */
10758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans, (png_size_t)num_trans);
10768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
10778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else if (color_type == PNG_COLOR_TYPE_GRAY)
10788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
10798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* one 16 bit value */
10808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if(tran->gray >= (1 << png_ptr->bit_depth))
10818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
10828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_warning(png_ptr,
10838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
10848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         return;
10858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
10868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_save_uint_16(buf, tran->gray);
10878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2);
10888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
10898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else if (color_type == PNG_COLOR_TYPE_RGB)
10908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
10918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* three 16 bit values */
10928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_save_uint_16(buf, tran->red);
10938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_save_uint_16(buf + 2, tran->green);
10948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_save_uint_16(buf + 4, tran->blue);
10958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
10968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
10978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_warning(png_ptr,
10988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
10998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
11008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
11018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6);
11028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
11038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else
11048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
11058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Can't write tRNS with an alpha channel");
11068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
11078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_bKGD_SUPPORTED)
11118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write the background chunk */
11128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
11138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
11148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
11168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_bKGD;
11178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[6];
11198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_bKGD\n");
11218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (color_type == PNG_COLOR_TYPE_PALETTE)
11228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
11238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (
11248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_MNG_FEATURES_SUPPORTED)
11258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          (png_ptr->num_palette ||
11268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
11278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         back->index > png_ptr->num_palette)
11298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
11308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_warning(png_ptr, "Invalid background palette index");
11318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         return;
11328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
11338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      buf[0] = back->index;
11348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1);
11358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
11368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else if (color_type & PNG_COLOR_MASK_COLOR)
11378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
11388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_save_uint_16(buf, back->red);
11398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_save_uint_16(buf + 2, back->green);
11408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_save_uint_16(buf + 4, back->blue);
11418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if(png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
11428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
11438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_warning(png_ptr,
11448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project              "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
11458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            return;
11468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
11478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6);
11488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
11498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else
11508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
11518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if(back->gray >= (1 << png_ptr->bit_depth))
11528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
11538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_warning(png_ptr,
11548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
11558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         return;
11568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
11578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_save_uint_16(buf, back->gray);
11588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2);
11598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
11608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_hIST_SUPPORTED)
11648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write the histogram */
11658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
11668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
11678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
11688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
11698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_hIST;
11708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int i;
11728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[3];
11738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_hIST\n");
11758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (num_hist > (int)png_ptr->num_palette)
11768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
11778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_debug2(3, "num_hist = %d, num_palette = %d\n", num_hist,
11788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->num_palette);
11798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid number of histogram entries specified");
11808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
11818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
11828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_start(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
11848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for (i = 0; i < num_hist; i++)
11858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
11868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_save_uint_16(buf, hist[i]);
11878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk_data(png_ptr, buf, (png_size_t)2);
11888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
11898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_end(png_ptr);
11908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
11918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
11928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
11938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
11948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
11958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
11968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and if invalid, correct the keyword rather than discarding the entire
11978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
11988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * length, forbids leading or trailing whitespace, multiple internal spaces,
11998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
12008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project *
12018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The new_key is allocated to hold the corrected keyword and must be freed
12028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * by the calling routine.  This avoids problems with trying to write to
12038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * static keywords without having to have duplicate copies of the strings.
12048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
12058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_size_t /* PRIVATE */
12068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
12078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
12088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t key_len;
12098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_charp kp, dp;
12108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int kflag;
12118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int kwarn=0;
12128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_check_keyword\n");
12148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   *new_key = NULL;
12158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (key == NULL || (key_len = png_strlen(key)) == 0)
12178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
12188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "zero length keyword");
12198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return ((png_size_t)0);
12208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
12218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug1(2, "Keyword to be checked is '%s'\n", key);
12238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
12258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (*new_key == NULL)
12268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
12278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Out of memory while procesing keyword");
12288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return ((png_size_t)0);
12298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
12308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Replace non-printing characters with a blank and print a warning */
12328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
12338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
12348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if ((png_byte)*kp < 0x20 ||
12358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1))
12368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
12378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
12388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         char msg[40];
12398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_snprintf(msg, 40,
12418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           "invalid keyword character 0x%02X", (png_byte)*kp);
12428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_warning(png_ptr, msg);
12438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
12448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_warning(png_ptr, "invalid character in keyword");
12458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
12468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         *dp = ' ';
12478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
12488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      else
12498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
12508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         *dp = *kp;
12518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
12528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
12538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   *dp = '\0';
12548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Remove any trailing white space. */
12568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   kp = *new_key + key_len - 1;
12578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (*kp == ' ')
12588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
12598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "trailing spaces removed from keyword");
12608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      while (*kp == ' ')
12628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
12638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        *(kp--) = '\0';
12648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        key_len--;
12658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
12668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
12678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Remove any leading white space. */
12698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   kp = *new_key;
12708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (*kp == ' ')
12718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
12728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "leading spaces removed from keyword");
12738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      while (*kp == ' ')
12758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
12768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        kp++;
12778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        key_len--;
12788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
12798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
12808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug1(2, "Checking for multiple internal spaces in '%s'\n", kp);
12828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
12838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Remove multiple internal spaces. */
12848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
12858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
12868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (*kp == ' ' && kflag == 0)
12878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
12888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         *(dp++) = *kp;
12898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         kflag = 1;
12908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
12918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      else if (*kp == ' ')
12928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
12938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         key_len--;
12948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         kwarn=1;
12958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
12968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      else
12978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
12988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         *(dp++) = *kp;
12998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         kflag = 0;
13008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
13018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
13028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   *dp = '\0';
13038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if(kwarn)
13048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "extra interior spaces removed from keyword");
13058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (key_len == 0)
13078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
13088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_free(png_ptr, *new_key);
13098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      *new_key=NULL;
13108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Zero length keyword");
13118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
13128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (key_len > 79)
13148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
13158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "keyword length must be 1 - 79 characters");
13168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      new_key[79] = '\0';
13178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      key_len = 79;
13188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
13198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   return (key_len);
13218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
13238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_tEXt_SUPPORTED)
13258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write a tEXt chunk */
13268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
13278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
13288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t text_len)
13298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
13318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_tEXt;
13328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
13338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t key_len;
13348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_charp new_key;
13358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_tEXt\n");
13378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
13388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
13398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Empty keyword in tEXt chunk");
13408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
13418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
13428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (text == NULL || *text == '\0')
13448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      text_len = 0;
13458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else
13468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      text_len = png_strlen(text);
13478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* make sure we include the 0 after the key */
13498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_start(png_ptr, (png_bytep)png_tEXt, (png_uint_32)key_len+text_len+1);
13508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /*
13518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * We leave it to the application to meet PNG-1.0 requirements on the
13528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
13538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
13548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
13558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
13568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
13578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (text_len)
13588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk_data(png_ptr, (png_bytep)text, text_len);
13598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_end(png_ptr);
13618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_free(png_ptr, new_key);
13628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
13638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
13648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_zTXt_SUPPORTED)
13668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write a compressed text chunk */
13678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
13688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
13698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t text_len, int compression)
13708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
13718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
13728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_zTXt;
13738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
13748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t key_len;
13758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   char buf[1];
13768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_charp new_key;
13778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   compression_state comp;
13788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_zTXt\n");
13808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.num_output_ptr = 0;
13828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.max_output_ptr = 0;
13838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.output_ptr = NULL;
13848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.input = NULL;
13858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.input_len = 0;
13868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
13888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
13898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Empty keyword in zTXt chunk");
13908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
13918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
13928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
13938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
13948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
13958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
13968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_free(png_ptr, new_key);
13978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
13988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
13998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   text_len = png_strlen(text);
14018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* compute the compressed data; do it now for the length */
14038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   text_len = png_text_compress(png_ptr, text, text_len, compression,
14048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       &comp);
14058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write start of chunk */
14078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_start(png_ptr, (png_bytep)png_zTXt, (png_uint_32)
14088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      (key_len+text_len+2));
14098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write key */
14108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
14118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_free(png_ptr, new_key);
14128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[0] = (png_byte)compression;
14148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write compression */
14158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1);
14168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write the compressed data */
14178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_compressed_data_out(png_ptr, &comp);
14188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* close the chunk */
14208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_end(png_ptr);
14218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
14228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
14238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_iTXt_SUPPORTED)
14258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write an iTXt chunk */
14268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
14278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_iTXt(png_structp png_ptr, int compression, png_charp key,
14288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    png_charp lang, png_charp lang_key, png_charp text)
14298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
14308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
14318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_iTXt;
14328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
14338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t lang_len, key_len, lang_key_len, text_len;
14348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_charp new_lang, new_key;
14358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte cbuf[2];
14368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   compression_state comp;
14378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_iTXt\n");
14398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.num_output_ptr = 0;
14418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.max_output_ptr = 0;
14428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.output_ptr = NULL;
14438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   comp.input = NULL;
14448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (key == NULL || (key_len = png_check_keyword(png_ptr, key, &new_key))==0)
14468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
14478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Empty keyword in iTXt chunk");
14488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
14498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
14508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (lang == NULL || (lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0)
14518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
14528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Empty language field in iTXt chunk");
14538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      new_lang = NULL;
14548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      lang_len = 0;
14558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
14568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (lang_key == NULL)
14588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     lang_key_len = 0;
14598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else
14608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     lang_key_len = png_strlen(lang_key);
14618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (text == NULL)
14638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      text_len = 0;
14648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else
14658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     text_len = png_strlen(text);
14668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* compute the compressed data; do it now for the length */
14688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   text_len = png_text_compress(png_ptr, text, text_len, compression-2,
14698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      &comp);
14708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* make sure we include the compression flag, the compression byte,
14738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * and the NULs after the key, lang, and lang_key parts */
14748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_start(png_ptr, (png_bytep)png_iTXt,
14768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          (png_uint_32)(
14778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        5 /* comp byte, comp flag, terminators for key, lang and lang_key */
14788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        + key_len
14798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        + lang_len
14808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        + lang_key_len
14818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project        + text_len));
14828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /*
14848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * We leave it to the application to meet PNG-1.0 requirements on the
14858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
14868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
14878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
14888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
14898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, (png_bytep)new_key, key_len + 1);
14908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
14918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* set the compression flag */
14928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (compression == PNG_ITXT_COMPRESSION_NONE || \
14938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       compression == PNG_TEXT_COMPRESSION_NONE)
14948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       cbuf[0] = 0;
14958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else /* compression == PNG_ITXT_COMPRESSION_zTXt */
14968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       cbuf[0] = 1;
14978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* set the compression method */
14988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   cbuf[1] = 0;
14998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, cbuf, 2);
15008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   cbuf[0] = 0;
15028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf), lang_len + 1);
15038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf), lang_key_len + 1);
15048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_compressed_data_out(png_ptr, &comp);
15058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_end(png_ptr);
15078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_free(png_ptr, new_key);
15088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (new_lang)
15098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     png_free(png_ptr, new_lang);
15108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
15128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_oFFs_SUPPORTED)
15148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write the oFFs chunk */
15158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
15168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
15178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int unit_type)
15188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
15208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_oFFs;
15218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
15228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[9];
15238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_oFFs\n");
15258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (unit_type >= PNG_OFFSET_LAST)
15268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
15278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_int_32(buf, x_offset);
15298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_int_32(buf + 4, y_offset);
15308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[8] = (png_byte)unit_type;
15318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, png_oFFs, buf, (png_size_t)9);
15338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
15358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_pCAL_SUPPORTED)
15368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write the pCAL chunk (described in the PNG extensions document) */
15378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
15388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
15398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
15408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
15418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
15428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_pCAL;
15438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
15448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t purpose_len, units_len, total_len;
15458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_uint_32p params_len;
15468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[10];
15478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_charp new_purpose;
15488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int i;
15498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug1(1, "in png_write_pCAL (%d parameters)\n", nparams);
15518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (type >= PNG_EQUATION_LAST)
15528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
15538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
15558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug1(3, "pCAL purpose length = %d\n", (int)purpose_len);
15568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
15578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug1(3, "pCAL units length = %d\n", (int)units_len);
15588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   total_len = purpose_len + units_len + 10;
15598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   params_len = (png_uint_32p)png_malloc(png_ptr, (png_uint_32)(nparams
15618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      *png_sizeof(png_uint_32)));
15628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Find the length of each parameter, making sure we don't count the
15648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      null terminator for the last parameter. */
15658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for (i = 0; i < nparams; i++)
15668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
15678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
15688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_debug2(3, "pCAL parameter %d length = %lu\n", i, params_len[i]);
15698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      total_len += (png_size_t)params_len[i];
15708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
15718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug1(3, "pCAL total length = %d\n", (int)total_len);
15738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_start(png_ptr, png_pCAL, (png_uint_32)total_len);
15748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, (png_bytep)new_purpose, purpose_len);
15758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_int_32(buf, X0);
15768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_int_32(buf + 4, X1);
15778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[8] = (png_byte)type;
15788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[9] = (png_byte)nparams;
15798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, buf, (png_size_t)10);
15808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len);
15818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_free(png_ptr, new_purpose);
15838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   for (i = 0; i < nparams; i++)
15858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
15868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_chunk_data(png_ptr, (png_bytep)params[i],
15878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         (png_size_t)params_len[i]);
15888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
15898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_free(png_ptr, params_len);
15918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk_end(png_ptr);
15928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
15938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
15948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
15958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_sCAL_SUPPORTED)
15968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write the sCAL chunk */
15978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
15988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
15998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_sCAL(png_structp png_ptr, int unit, double width, double height)
16008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
16028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_sCAL;
16038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   char buf[64];
16058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t total_len;
16068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_sCAL\n");
16088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[0] = (char)unit;
16108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(_WIN32_WCE)
16118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* sprintf() function is not supported on WindowsCE */
16128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
16138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      wchar_t wc_buf[32];
16148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      size_t wc_len;
16158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      swprintf(wc_buf, TEXT("%12.12e"), width);
16168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      wc_len = wcslen(wc_buf);
16178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, NULL);
16188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      total_len = wc_len + 2;
16198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      swprintf(wc_buf, TEXT("%12.12e"), height);
16208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      wc_len = wcslen(wc_buf);
16218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len,
16228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         NULL, NULL);
16238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      total_len += wc_len;
16248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
16258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
16268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_snprintf(buf + 1, 63, "%12.12e", width);
16278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   total_len = 1 + png_strlen(buf + 1) + 1;
16288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_snprintf(buf + total_len, 64-total_len, "%12.12e", height);
16298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   total_len += png_strlen(buf + total_len);
16308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len);
16338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, png_sCAL, (png_bytep)buf, total_len);
16348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
16368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_FIXED_POINT_SUPPORTED
16378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
16388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
16398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_charp height)
16408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
16428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_sCAL;
16438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[64];
16458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t wlen, hlen, total_len;
16468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_sCAL_s\n");
16488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   wlen = png_strlen(width);
16508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   hlen = png_strlen(height);
16518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   total_len = wlen + hlen + 2;
16528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (total_len > 64)
16538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
16548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Can't write sCAL (buffer too small)");
16558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
16568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
16578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[0] = (png_byte)unit;
16598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_memcpy(buf + 1, width, wlen + 1);      /* append the '\0' here */
16608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_memcpy(buf + wlen + 2, height, hlen);  /* do NOT append the '\0' here */
16618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug1(3, "sCAL total length = %u\n", (unsigned int)total_len);
16638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, png_sCAL, buf, total_len);
16648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_pHYs_SUPPORTED)
16708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* write the pHYs chunk */
16718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
16728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
16738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_uint_32 y_pixels_per_unit,
16748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int unit_type)
16758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
16768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
16778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_pHYs;
16788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[9];
16808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_pHYs\n");
16828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (unit_type >= PNG_RESOLUTION_LAST)
16838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
16848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf, x_pixels_per_unit);
16868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_32(buf + 4, y_pixels_per_unit);
16878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[8] = (png_byte)unit_type;
16888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
16908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
16918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
16928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
16938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_tIME_SUPPORTED)
16948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Write the tIME chunk.  Use either png_convert_from_struct_tm()
16958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * or png_convert_from_time_t(), or fill in the structure yourself.
16968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
16978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
16988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_tIME(png_structp png_ptr, png_timep mod_time)
16998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
17018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   PNG_tIME;
17028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
17038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte buf[7];
17048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_tIME\n");
17068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (mod_time->month  > 12 || mod_time->month  < 1 ||
17078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       mod_time->day    > 31 || mod_time->day    < 1 ||
17088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       mod_time->hour   > 23 || mod_time->second > 60)
17098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
17108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_warning(png_ptr, "Invalid time specified for tIME chunk");
17118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
17128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
17138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_save_uint_16(buf, mod_time->year);
17158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[2] = mod_time->month;
17168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[3] = mod_time->day;
17178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[4] = mod_time->hour;
17188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[5] = mod_time->minute;
17198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf[6] = mod_time->second;
17208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
17228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
17238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
17248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* initializes the row writing capability of libpng */
17268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
17278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_start_row(png_structp png_ptr)
17288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
17298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
17308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
17318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* start of interlace block */
17338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
17348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* offset to next interlace block */
17368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
17378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* start of interlace block in the y direction */
17398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
17408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* offset to next interlace block in the y direction */
17428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
17438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
17448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_size_t buf_size;
17468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_start_row\n");
17488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   buf_size = (png_size_t)(PNG_ROWBYTES(
17498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->usr_channels*png_ptr->usr_bit_depth,png_ptr->width)+1);
17508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* set up row buffer */
17528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
17538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
17548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef PNG_NO_WRITE_FILTERING
17568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* set up filtering buffer, if using this filter */
17578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (png_ptr->do_filter & PNG_FILTER_SUB)
17588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
17598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
17608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         (png_ptr->rowbytes + 1));
17618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
17628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
17638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* We only need to keep the previous row if we are using one of these. */
17658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
17668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
17678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project     /* set up previous row buffer */
17688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->prev_row = (png_bytep)png_malloc(png_ptr, (png_uint_32)buf_size);
17698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_memset(png_ptr->prev_row, 0, buf_size);
17708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->do_filter & PNG_FILTER_UP)
17728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
17738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
17748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            (png_ptr->rowbytes + 1));
17758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
17768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
17778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->do_filter & PNG_FILTER_AVG)
17798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
17808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
17818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            (png_ptr->rowbytes + 1));
17828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
17838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
17848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->do_filter & PNG_FILTER_PAETH)
17868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
17878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
17888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            (png_ptr->rowbytes + 1));
17898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
17908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
17918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* PNG_NO_WRITE_FILTERING */
17928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
17938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
17948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_WRITE_INTERLACING_SUPPORTED
17958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* if interlaced, we need to set up width and height of pass */
17968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (png_ptr->interlaced)
17978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
17988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (!(png_ptr->transformations & PNG_INTERLACE))
17998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
18008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
18018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_pass_ystart[0]) / png_pass_yinc[0];
18028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
18038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_pass_start[0]) / png_pass_inc[0];
18048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
18058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      else
18068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
18078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->num_rows = png_ptr->height;
18088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->usr_width = png_ptr->width;
18098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
18108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
18118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else
18128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
18138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
18148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->num_rows = png_ptr->height;
18158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->usr_width = png_ptr->width;
18168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
18178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
18188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.next_out = png_ptr->zbuf;
18198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
18208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Internal use only.  Called when finished processing a row of data. */
18228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
18238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_finish_row(png_structp png_ptr)
18248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
18258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
18268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
18278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* start of interlace block */
18298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
18308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* offset to next interlace block */
18328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
18338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* start of interlace block in the y direction */
18358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
18368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* offset to next interlace block in the y direction */
18388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
18398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
18408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int ret;
18428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_finish_row\n");
18448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* next row */
18458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->row_number++;
18468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* see if we are done */
18488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (png_ptr->row_number < png_ptr->num_rows)
18498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      return;
18508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_WRITE_INTERLACING_SUPPORTED
18528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* if interlaced, go to next pass */
18538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (png_ptr->interlaced)
18548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
18558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->row_number = 0;
18568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->transformations & PNG_INTERLACE)
18578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
18588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->pass++;
18598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
18608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      else
18618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
18628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* loop until we find a non-zero width or height pass */
18638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         do
18648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
18658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_ptr->pass++;
18668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (png_ptr->pass >= 7)
18678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               break;
18688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_ptr->usr_width = (png_ptr->width +
18698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_pass_inc[png_ptr->pass] - 1 -
18708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_pass_start[png_ptr->pass]) /
18718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_pass_inc[png_ptr->pass];
18728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_ptr->num_rows = (png_ptr->height +
18738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_pass_yinc[png_ptr->pass] - 1 -
18748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_pass_ystart[png_ptr->pass]) /
18758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_pass_yinc[png_ptr->pass];
18768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (png_ptr->transformations & PNG_INTERLACE)
18778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               break;
18788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
18798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
18818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* reset the row above the image for the next pass */
18838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->pass < 7)
18848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
18858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (png_ptr->prev_row != NULL)
18868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_memset(png_ptr->prev_row, 0,
18878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
18888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               png_ptr->usr_bit_depth,png_ptr->width))+1);
18898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         return;
18908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
18918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
18928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
18938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
18948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* if we get here, we've just written the last row, so we need
18958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      to flush the compressor */
18968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   do
18978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
18988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* tell the compressor we are done */
18998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      ret = deflate(&png_ptr->zstream, Z_FINISH);
19008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* check for an error */
19018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (ret == Z_OK)
19028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
19038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* check to see if we need more room */
19048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (!(png_ptr->zstream.avail_out))
19058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
19068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
19078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_ptr->zstream.next_out = png_ptr->zbuf;
19088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
19098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
19108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
19118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      else if (ret != Z_STREAM_END)
19128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
19138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (png_ptr->zstream.msg != NULL)
19148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_error(png_ptr, png_ptr->zstream.msg);
19158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
19168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_error(png_ptr, "zlib error");
19178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
19188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   } while (ret != Z_STREAM_END);
19198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* write any extra space */
19218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
19228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
19238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
19248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->zstream.avail_out);
19258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
19268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   deflateReset(&png_ptr->zstream);
19288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.data_type = Z_BINARY;
19298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
19308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
19328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Pick out the correct pixels for the interlace pass.
19338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * The basic idea here is to go through the row with a source
19348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * pointer and a destination pointer (sp and dp), and copy the
19358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * correct pixels for the pass.  As the row gets compacted,
19368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * sp will always be >= dp, so we should never overwrite anything.
19378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * See the default: case for the easiest code to understand.
19388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
19398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
19408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
19418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
19428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_LOCAL_ARRAYS
19438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* arrays to facilitate easy interlacing - use pass (0 - 6) as index */
19448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* start of interlace block */
19468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
19478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* offset to next interlace block */
19498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
19508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
19518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_do_write_interlace\n");
19538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* we don't have to do anything on the last pass (6) */
19548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_USELESS_TESTS_SUPPORTED)
19558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (row != NULL && row_info != NULL && pass < 6)
19568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
19578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (pass < 6)
19588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
19598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
19608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* each pixel depth is handled separately */
19618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      switch (row_info->pixel_depth)
19628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
19638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         case 1:
19648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
19658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_bytep sp;
19668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_bytep dp;
19678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int shift;
19688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int d;
19698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int value;
19708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_uint_32 i;
19718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_uint_32 row_width = row_info->width;
19728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dp = row;
19748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            d = 0;
19758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = 7;
19768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = png_pass_start[pass]; i < row_width;
19778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               i += png_pass_inc[pass])
19788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
19798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sp = row + (png_size_t)(i >> 3);
19808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
19818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               d |= (value << shift);
19828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               if (shift == 0)
19848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               {
19858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  shift = 7;
19868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  *dp++ = (png_byte)d;
19878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  d = 0;
19888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               }
19898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               else
19908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  shift--;
19918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
19928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
19938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (shift != 7)
19948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               *dp = (png_byte)d;
19958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
19968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
19978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         case 2:
19988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
19998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_bytep sp;
20008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_bytep dp;
20018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int shift;
20028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int d;
20038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int value;
20048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_uint_32 i;
20058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_uint_32 row_width = row_info->width;
20068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dp = row;
20088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = 6;
20098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            d = 0;
20108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = png_pass_start[pass]; i < row_width;
20118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               i += png_pass_inc[pass])
20128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
20138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sp = row + (png_size_t)(i >> 2);
20148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
20158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               d |= (value << shift);
20168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               if (shift == 0)
20188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               {
20198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  shift = 6;
20208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  *dp++ = (png_byte)d;
20218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  d = 0;
20228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               }
20238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               else
20248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  shift -= 2;
20258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
20268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (shift != 6)
20278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                   *dp = (png_byte)d;
20288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
20308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         case 4:
20318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
20328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_bytep sp;
20338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_bytep dp;
20348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int shift;
20358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int d;
20368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            int value;
20378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_uint_32 i;
20388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_uint_32 row_width = row_info->width;
20398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dp = row;
20418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            shift = 4;
20428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            d = 0;
20438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = png_pass_start[pass]; i < row_width;
20448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               i += png_pass_inc[pass])
20458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
20468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sp = row + (png_size_t)(i >> 1);
20478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
20488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               d |= (value << shift);
20498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               if (shift == 0)
20518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               {
20528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  shift = 4;
20538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  *dp++ = (png_byte)d;
20548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  d = 0;
20558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               }
20568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               else
20578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  shift -= 4;
20588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
20598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (shift != 4)
20608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               *dp = (png_byte)d;
20618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
20638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         default:
20648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
20658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_bytep sp;
20668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_bytep dp;
20678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_uint_32 i;
20688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_uint_32 row_width = row_info->width;
20698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_size_t pixel_bytes;
20708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
20718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* start at the beginning */
20728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            dp = row;
20738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* find out how many bytes each pixel takes up */
20748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            pixel_bytes = (row_info->pixel_depth >> 3);
20758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            /* loop through the row, only looking at the pixels that
20768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               matter */
20778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            for (i = png_pass_start[pass]; i < row_width;
20788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               i += png_pass_inc[pass])
20798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
20808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               /* find out where the original pixel is */
20818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sp = row + (png_size_t)i * pixel_bytes;
20828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               /* move the pixel */
20838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               if (dp != sp)
20848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  png_memcpy(dp, sp, pixel_bytes);
20858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               /* next pixel */
20868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               dp += pixel_bytes;
20878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
20888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
20898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
20908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
20918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* set new row width */
20928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      row_info->width = (row_info->width +
20938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_pass_inc[pass] - 1 -
20948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_pass_start[pass]) /
20958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_pass_inc[pass];
20968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
20978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            row_info->width);
20988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
20998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
21008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
21018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* This filters the row, chooses which filter to use, if it has not already
21038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * been specified by the application, and then writes the row out with the
21048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project * chosen filter.
21058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project */
21068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
21078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PNG_HISHIFT 10
21088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PNG_LOMASK ((png_uint_32)0xffffL)
21098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
21108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
21118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_find_filter(png_structp png_ptr, png_row_infop row_info)
21128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
21138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_bytep prev_row, best_row, row_buf;
21148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_uint_32 mins, bpp;
21158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_byte filter_to_do = png_ptr->do_filter;
21168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_uint_32 row_bytes = row_info->rowbytes;
21178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
21188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   int num_p_filters = (int)png_ptr->num_prev_filters;
21198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
21208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_find_filter\n");
21228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* find out how many bytes offset each pixel is */
21238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   bpp = (row_info->pixel_depth + 7) >> 3;
21248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   prev_row = png_ptr->prev_row;
21268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   best_row = row_buf = png_ptr->row_buf;
21278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef PNG_NO_WRITE_FILTER
21288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   mins = PNG_MAXSUM;
21298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* The prediction method we use is to find which method provides the
21318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * smallest value when summing the absolute values of the distances
21328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * from zero, using anything >= 128 as negative numbers.  This is known
21338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * as the "minimum sum of absolute differences" heuristic.  Other
21348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * heuristics are the "weighted minimum sum of absolute differences"
21358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * (experimental and can in theory improve compression), and the "zlib
21368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * predictive" method (not implemented yet), which does test compressions
21378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * of lines using different filter methods, and then chooses the
21388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * (series of) filter(s) that give minimum compressed data size (VERY
21398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * computationally expensive).
21408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *
21418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * GRR 980525:  consider also
21428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *   (1) minimum sum of absolute differences from running average (i.e.,
21438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *       keep running sum of non-absolute differences & count of bytes)
21448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *       [track dispersion, too?  restart average if dispersion too large?]
21458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *  (1b) minimum sum of absolute differences from sliding average, probably
21468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *       with window size <= deflate window (usually 32K)
21478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *   (2) minimum sum of squared differences from zero or running average
21488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    *       (i.e., ~ root-mean-square approach)
21498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
21508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* We don't need to test the 'no filter' case if this is the only filter
21538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    * that has been chosen, as it doesn't actually do anything to the data.
21548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project    */
21558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if ((filter_to_do & PNG_FILTER_NONE) &&
21568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       filter_to_do != PNG_FILTER_NONE)
21578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
21588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_bytep rp;
21598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 sum = 0;
21608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 i;
21618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      int v;
21628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
21648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
21658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         v = *rp;
21668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sum += (v < 128) ? v : 256 - v;
21678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
21688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
21708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
21718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
21728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_uint_32 sumhi, sumlo;
21738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         int j;
21748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumlo = sum & PNG_LOMASK;
21758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
21768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* Reduce the sum if we match any of the previous rows */
21788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         for (j = 0; j < num_p_filters; j++)
21798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
21808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
21818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
21828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
21838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
21848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
21858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
21868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
21878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
21888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* Factor in the cost of this filter (this is here for completeness,
21908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          * but it makes no sense to have a "cost" for the NONE filter, as
21918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          * it has the minimum possible computational cost - none).
21928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          */
21938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
21948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
21958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
21968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
21978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
21988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (sumhi > PNG_HIMASK)
21998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sum = PNG_MAXSUM;
22008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
22018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sum = (sumhi << PNG_HISHIFT) + sumlo;
22028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
22038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
22048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      mins = sum;
22058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
22068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* sub filter */
22088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (filter_to_do == PNG_FILTER_SUB)
22098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* it's the only filter so no testing is needed */
22108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
22118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_bytep rp, lp, dp;
22128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 i;
22138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
22148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           i++, rp++, dp++)
22158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
22168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         *dp = *rp;
22178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
22188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (lp = row_buf + 1; i < row_bytes;
22198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         i++, rp++, lp++, dp++)
22208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
22218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
22228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
22238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      best_row = png_ptr->sub_row;
22248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
22258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else if (filter_to_do & PNG_FILTER_SUB)
22278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
22288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_bytep rp, dp, lp;
22298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 sum = 0, lmins = mins;
22308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 i;
22318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      int v;
22328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
22348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* We temporarily increase the "minimum sum" by the factor we
22358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       * would reduce the sum of this filter, so that we can do the
22368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       * early exit comparison without scaling the sum each time.
22378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       */
22388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
22398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
22408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         int j;
22418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_uint_32 lmhi, lmlo;
22428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmlo = lmins & PNG_LOMASK;
22438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
22448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         for (j = 0; j < num_p_filters; j++)
22468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
22478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
22488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
22498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
22508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
22518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
22528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
22538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
22548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
22558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
22578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
22588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
22598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
22608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (lmhi > PNG_HIMASK)
22628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            lmins = PNG_MAXSUM;
22638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
22648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            lmins = (lmhi << PNG_HISHIFT) + lmlo;
22658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
22668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
22678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
22698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           i++, rp++, dp++)
22708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
22718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         v = *dp = *rp;
22728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sum += (v < 128) ? v : 256 - v;
22748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
22758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (lp = row_buf + 1; i < row_bytes;
22768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         i++, rp++, lp++, dp++)
22778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
22788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
22798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sum += (v < 128) ? v : 256 - v;
22818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (sum > lmins)  /* We are already worse, don't continue. */
22838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
22848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
22858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
22878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
22888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
22898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         int j;
22908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_uint_32 sumhi, sumlo;
22918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumlo = sum & PNG_LOMASK;
22928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
22938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
22948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         for (j = 0; j < num_p_filters; j++)
22958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
22968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
22978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
22988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
22998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
23008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
23018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
23028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
23038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
23048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
23068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
23078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
23088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
23098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (sumhi > PNG_HIMASK)
23118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sum = PNG_MAXSUM;
23128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
23138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sum = (sumhi << PNG_HISHIFT) + sumlo;
23148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
23158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
23168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (sum < mins)
23188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
23198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         mins = sum;
23208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         best_row = png_ptr->sub_row;
23218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
23228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
23238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* up filter */
23258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (filter_to_do == PNG_FILTER_UP)
23268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
23278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_bytep rp, dp, pp;
23288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 i;
23298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
23318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           pp = prev_row + 1; i < row_bytes;
23328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           i++, rp++, pp++, dp++)
23338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
23348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
23358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
23368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      best_row = png_ptr->up_row;
23378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
23388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else if (filter_to_do & PNG_FILTER_UP)
23408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
23418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_bytep rp, dp, pp;
23428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 sum = 0, lmins = mins;
23438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 i;
23448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      int v;
23458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
23488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
23498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
23508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         int j;
23518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_uint_32 lmhi, lmlo;
23528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmlo = lmins & PNG_LOMASK;
23538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
23548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         for (j = 0; j < num_p_filters; j++)
23568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
23578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
23588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
23598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
23608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
23618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
23628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
23638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
23648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
23658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
23678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
23688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
23698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
23708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (lmhi > PNG_HIMASK)
23728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            lmins = PNG_MAXSUM;
23738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
23748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            lmins = (lmhi << PNG_HISHIFT) + lmlo;
23758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
23768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
23778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
23798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           pp = prev_row + 1; i < row_bytes; i++)
23808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
23818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
23828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sum += (v < 128) ? v : 256 - v;
23848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (sum > lmins)  /* We are already worse, don't continue. */
23868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
23878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
23888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
23908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
23918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
23928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         int j;
23938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_uint_32 sumhi, sumlo;
23948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumlo = sum & PNG_LOMASK;
23958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
23968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
23978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         for (j = 0; j < num_p_filters; j++)
23988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
23998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
24008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
24018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
24028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
24038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
24048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
24058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
24068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
24078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
24098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
24108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
24118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
24128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (sumhi > PNG_HIMASK)
24148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sum = PNG_MAXSUM;
24158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
24168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sum = (sumhi << PNG_HISHIFT) + sumlo;
24178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
24188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
24198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (sum < mins)
24218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
24228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         mins = sum;
24238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         best_row = png_ptr->up_row;
24248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
24258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
24268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* avg filter */
24288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (filter_to_do == PNG_FILTER_AVG)
24298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
24308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_bytep rp, dp, pp, lp;
24318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 i;
24328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
24338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           pp = prev_row + 1; i < bpp; i++)
24348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
24358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
24368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
24378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (lp = row_buf + 1; i < row_bytes; i++)
24388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
24398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
24408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                 & 0xff);
24418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
24428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      best_row = png_ptr->avg_row;
24438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
24448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else if (filter_to_do & PNG_FILTER_AVG)
24468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
24478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_bytep rp, dp, pp, lp;
24488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 sum = 0, lmins = mins;
24498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 i;
24508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      int v;
24518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
24538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
24548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
24558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         int j;
24568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_uint_32 lmhi, lmlo;
24578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmlo = lmins & PNG_LOMASK;
24588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
24598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         for (j = 0; j < num_p_filters; j++)
24618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
24628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
24638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
24648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
24658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
24668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
24678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
24688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
24698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
24708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
24728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
24738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
24748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
24758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (lmhi > PNG_HIMASK)
24778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            lmins = PNG_MAXSUM;
24788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
24798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            lmins = (lmhi << PNG_HISHIFT) + lmlo;
24808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
24818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
24828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
24848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           pp = prev_row + 1; i < bpp; i++)
24858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
24868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
24878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sum += (v < 128) ? v : 256 - v;
24898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
24908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (lp = row_buf + 1; i < row_bytes; i++)
24918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
24928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         v = *dp++ =
24938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project          (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
24948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sum += (v < 128) ? v : 256 - v;
24968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
24978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (sum > lmins)  /* We are already worse, don't continue. */
24988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
24998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
25008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
25028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
25038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
25048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         int j;
25058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_uint_32 sumhi, sumlo;
25068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumlo = sum & PNG_LOMASK;
25078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
25088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         for (j = 0; j < num_p_filters; j++)
25108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
25118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
25128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
25138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
25148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
25158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
25168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
25178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
25188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
25198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
25218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
25228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
25238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
25248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (sumhi > PNG_HIMASK)
25268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sum = PNG_MAXSUM;
25278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
25288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sum = (sumhi << PNG_HISHIFT) + sumlo;
25298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
25308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
25318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (sum < mins)
25338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
25348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         mins = sum;
25358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         best_row = png_ptr->avg_row;
25368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
25378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
25388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Paeth filter */
25408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (filter_to_do == PNG_FILTER_PAETH)
25418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
25428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_bytep rp, dp, pp, cp, lp;
25438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 i;
25448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
25458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           pp = prev_row + 1; i < bpp; i++)
25468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
25478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
25488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
25498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
25518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
25528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         int a, b, c, pa, pb, pc, p;
25538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         b = *pp++;
25558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         c = *cp++;
25568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         a = *lp++;
25578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         p = b - c;
25598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pc = a - c;
25608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_ABS
25628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pa = abs(p);
25638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pb = abs(pc);
25648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pc = abs(p + pc);
25658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
25668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pa = p < 0 ? -p : p;
25678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pb = pc < 0 ? -pc : pc;
25688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
25698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
25708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
25728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
25748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
25758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      best_row = png_ptr->paeth_row;
25768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
25778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   else if (filter_to_do & PNG_FILTER_PAETH)
25798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
25808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_bytep rp, dp, pp, cp, lp;
25818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 sum = 0, lmins = mins;
25828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_uint_32 i;
25838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      int v;
25848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
25868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
25878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
25888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         int j;
25898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_uint_32 lmhi, lmlo;
25908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmlo = lmins & PNG_LOMASK;
25918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
25928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
25938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         for (j = 0; j < num_p_filters; j++)
25948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
25958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
25968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
25978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
25988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
25998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
26008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
26018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
26028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
26038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
26058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
26068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
26078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
26088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (lmhi > PNG_HIMASK)
26108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            lmins = PNG_MAXSUM;
26118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
26128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            lmins = (lmhi << PNG_HISHIFT) + lmlo;
26138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
26148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
26158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
26178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project           pp = prev_row + 1; i < bpp; i++)
26188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
26198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
26208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sum += (v < 128) ? v : 256 - v;
26228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
26238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
26258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
26268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         int a, b, c, pa, pb, pc, p;
26278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         b = *pp++;
26298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         c = *cp++;
26308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         a = *lp++;
26318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifndef PNG_SLOW_PAETH
26338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         p = b - c;
26348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pc = a - c;
26358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#ifdef PNG_USE_ABS
26368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pa = abs(p);
26378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pb = abs(pc);
26388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pc = abs(p + pc);
26398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else
26408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pa = p < 0 ? -p : p;
26418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pb = pc < 0 ? -pc : pc;
26428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
26438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
26448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
26458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#else /* PNG_SLOW_PAETH */
26468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         p = a + b - c;
26478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pa = abs(p - a);
26488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pb = abs(p - b);
26498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         pc = abs(p - c);
26508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (pa <= pb && pa <= pc)
26518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = a;
26528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else if (pb <= pc)
26538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = b;
26548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
26558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            p = c;
26568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* PNG_SLOW_PAETH */
26578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
26598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sum += (v < 128) ? v : 256 - v;
26618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (sum > lmins)  /* We are already worse, don't continue. */
26638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            break;
26648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
26658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
26678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
26688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
26698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         int j;
26708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_uint_32 sumhi, sumlo;
26718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumlo = sum & PNG_LOMASK;
26728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
26738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         for (j = 0; j < num_p_filters; j++)
26758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         {
26768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
26778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            {
26788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
26798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
26808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
26818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project                  PNG_WEIGHT_SHIFT;
26828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            }
26838b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         }
26848b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26858b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
26868b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
26878b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
26888b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            PNG_COST_SHIFT;
26898b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26908b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (sumhi > PNG_HIMASK)
26918b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sum = PNG_MAXSUM;
26928b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
26938b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            sum = (sumhi << PNG_HISHIFT) + sumlo;
26948b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
26958b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
26968b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
26978b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (sum < mins)
26988b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
26998b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         best_row = png_ptr->paeth_row;
27008b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
27018b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
27028b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* PNG_NO_WRITE_FILTER */
27038b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Do the actual writing of the filtered row data from the chosen filter. */
27048b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27058b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_filtered_row(png_ptr, best_row);
27068b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27078b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
27088b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* Save the type of filter we picked this time for future calculations */
27098b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (png_ptr->num_prev_filters > 0)
27108b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
27118b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      int j;
27128b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      for (j = 1; j < num_p_filters; j++)
27138b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
27148b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
27158b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
27168b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->prev_filters[j] = best_row[0];
27178b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
27188b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
27198b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27208b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27218b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27228b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project/* Do the actual writing of a previously filtered row. */
27238b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectvoid /* PRIVATE */
27248b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Projectpng_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
27258b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project{
27268b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug(1, "in png_write_filtered_row\n");
27278b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_debug1(2, "filter = %d\n", filtered_row[0]);
27288b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* set up the zlib input buffer */
27298b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27308b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.next_in = filtered_row;
27318b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
27328b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* repeat until we have compressed all the data */
27338b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   do
27348b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
27358b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      int ret; /* return of zlib */
27368b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27378b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* compress the data */
27388b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
27398b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* check for compression errors */
27408b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (ret != Z_OK)
27418b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
27428b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         if (png_ptr->zstream.msg != NULL)
27438b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_error(png_ptr, png_ptr->zstream.msg);
27448b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         else
27458b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project            png_error(png_ptr, "zlib error");
27468b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
27478b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27488b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      /* see if it is time to write another IDAT */
27498b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      if (!(png_ptr->zstream.avail_out))
27508b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      {
27518b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         /* write the IDAT and reset the zlib output buffer */
27528b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
27538b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->zstream.next_out = png_ptr->zbuf;
27548b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project         png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
27558b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      }
27568b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* repeat until all data has been compressed */
27578b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   } while (png_ptr->zstream.avail_in);
27588b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27598b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* swap the current and previous rows */
27608b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (png_ptr->prev_row != NULL)
27618b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
27628b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_bytep tptr;
27638b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27648b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      tptr = png_ptr->prev_row;
27658b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->prev_row = png_ptr->row_buf;
27668b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_ptr->row_buf = tptr;
27678b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
27688b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27698b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   /* finish row - updates counters and flushes zlib if last row */
27708b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_write_finish_row(png_ptr);
27718b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27728b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#if defined(PNG_WRITE_FLUSH_SUPPORTED)
27738b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   png_ptr->flush_rows++;
27748b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project
27758b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   if (png_ptr->flush_dist > 0 &&
27768b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project       png_ptr->flush_rows >= png_ptr->flush_dist)
27778b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   {
27788b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project      png_write_flush(png_ptr);
27798b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project   }
27808b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif
27818b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project}
27828b23a6c7e1aee255004dd19098d4c2462b61b849The Android Open Source Project#endif /* PNG_WRITE_SUPPORTED */
2783