Home | History | Annotate | Download | only in libpng
      1 
      2 /* pngwutil.c - utilities to write a PNG file
      3  *
      4  * Last changed in libpng 1.2.43 [February 25, 2010]
      5  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
      6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
      7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
      8  *
      9  * This code is released under the libpng license.
     10  * For conditions of distribution and use, see the disclaimer
     11  * and license in png.h
     12  */
     13 
     14 #define PNG_INTERNAL
     15 #define PNG_NO_PEDANTIC_WARNINGS
     16 #include "png.h"
     17 #ifdef PNG_WRITE_SUPPORTED
     18 
     19 /* Place a 32-bit number into a buffer in PNG byte order.  We work
     20  * with unsigned numbers for convenience, although one supported
     21  * ancillary chunk uses signed (two's complement) numbers.
     22  */
     23 void PNGAPI
     24 png_save_uint_32(png_bytep buf, png_uint_32 i)
     25 {
     26    buf[0] = (png_byte)((i >> 24) & 0xff);
     27    buf[1] = (png_byte)((i >> 16) & 0xff);
     28    buf[2] = (png_byte)((i >> 8) & 0xff);
     29    buf[3] = (png_byte)(i & 0xff);
     30 }
     31 
     32 /* The png_save_int_32 function assumes integers are stored in two's
     33  * complement format.  If this isn't the case, then this routine needs to
     34  * be modified to write data in two's complement format.
     35  */
     36 void PNGAPI
     37 png_save_int_32(png_bytep buf, png_int_32 i)
     38 {
     39    buf[0] = (png_byte)((i >> 24) & 0xff);
     40    buf[1] = (png_byte)((i >> 16) & 0xff);
     41    buf[2] = (png_byte)((i >> 8) & 0xff);
     42    buf[3] = (png_byte)(i & 0xff);
     43 }
     44 
     45 /* Place a 16-bit number into a buffer in PNG byte order.
     46  * The parameter is declared unsigned int, not png_uint_16,
     47  * just to avoid potential problems on pre-ANSI C compilers.
     48  */
     49 void PNGAPI
     50 png_save_uint_16(png_bytep buf, unsigned int i)
     51 {
     52    buf[0] = (png_byte)((i >> 8) & 0xff);
     53    buf[1] = (png_byte)(i & 0xff);
     54 }
     55 
     56 /* Simple function to write the signature.  If we have already written
     57  * the magic bytes of the signature, or more likely, the PNG stream is
     58  * being embedded into another stream and doesn't need its own signature,
     59  * we should call png_set_sig_bytes() to tell libpng how many of the
     60  * bytes have already been written.
     61  */
     62 void /* PRIVATE */
     63 png_write_sig(png_structp png_ptr)
     64 {
     65    png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
     66 
     67    /* Write the rest of the 8 byte signature */
     68    png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
     69       (png_size_t)(8 - png_ptr->sig_bytes));
     70    if (png_ptr->sig_bytes < 3)
     71       png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
     72 }
     73 
     74 /* Write a PNG chunk all at once.  The type is an array of ASCII characters
     75  * representing the chunk name.  The array must be at least 4 bytes in
     76  * length, and does not need to be null terminated.  To be safe, pass the
     77  * pre-defined chunk names here, and if you need a new one, define it
     78  * where the others are defined.  The length is the length of the data.
     79  * All the data must be present.  If that is not possible, use the
     80  * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
     81  * functions instead.
     82  */
     83 void PNGAPI
     84 png_write_chunk(png_structp png_ptr, png_bytep chunk_name,
     85    png_bytep data, png_size_t length)
     86 {
     87    if (png_ptr == NULL)
     88       return;
     89    png_write_chunk_start(png_ptr, chunk_name, (png_uint_32)length);
     90    png_write_chunk_data(png_ptr, data, (png_size_t)length);
     91    png_write_chunk_end(png_ptr);
     92 }
     93 
     94 /* Write the start of a PNG chunk.  The type is the chunk type.
     95  * The total_length is the sum of the lengths of all the data you will be
     96  * passing in png_write_chunk_data().
     97  */
     98 void PNGAPI
     99 png_write_chunk_start(png_structp png_ptr, png_bytep chunk_name,
    100    png_uint_32 length)
    101 {
    102    png_byte buf[8];
    103 
    104    png_debug2(0, "Writing %s chunk, length = %lu", chunk_name,
    105       (unsigned long)length);
    106 
    107    if (png_ptr == NULL)
    108       return;
    109 
    110 
    111    /* Write the length and the chunk name */
    112    png_save_uint_32(buf, length);
    113    png_memcpy(buf + 4, chunk_name, 4);
    114    png_write_data(png_ptr, buf, (png_size_t)8);
    115    /* Put the chunk name into png_ptr->chunk_name */
    116    png_memcpy(png_ptr->chunk_name, chunk_name, 4);
    117    /* Reset the crc and run it over the chunk name */
    118    png_reset_crc(png_ptr);
    119    png_calculate_crc(png_ptr, chunk_name, (png_size_t)4);
    120 }
    121 
    122 /* Write the data of a PNG chunk started with png_write_chunk_start().
    123  * Note that multiple calls to this function are allowed, and that the
    124  * sum of the lengths from these calls *must* add up to the total_length
    125  * given to png_write_chunk_start().
    126  */
    127 void PNGAPI
    128 png_write_chunk_data(png_structp png_ptr, png_bytep data, png_size_t length)
    129 {
    130    /* Write the data, and run the CRC over it */
    131    if (png_ptr == NULL)
    132       return;
    133    if (data != NULL && length > 0)
    134    {
    135       png_write_data(png_ptr, data, length);
    136       /* Update the CRC after writing the data,
    137        * in case that the user I/O routine alters it.
    138        */
    139       png_calculate_crc(png_ptr, data, length);
    140    }
    141 }
    142 
    143 /* Finish a chunk started with png_write_chunk_start(). */
    144 void PNGAPI
    145 png_write_chunk_end(png_structp png_ptr)
    146 {
    147    png_byte buf[4];
    148 
    149    if (png_ptr == NULL) return;
    150 
    151    /* Write the crc in a single operation */
    152    png_save_uint_32(buf, png_ptr->crc);
    153 
    154    png_write_data(png_ptr, buf, (png_size_t)4);
    155 }
    156 
    157 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_iCCP_SUPPORTED)
    158 /* This pair of functions encapsulates the operation of (a) compressing a
    159  * text string, and (b) issuing it later as a series of chunk data writes.
    160  * The compression_state structure is shared context for these functions
    161  * set up by the caller in order to make the whole mess thread-safe.
    162  */
    163 
    164 typedef struct
    165 {
    166    char *input;   /* The uncompressed input data */
    167    int input_len;   /* Its length */
    168    int num_output_ptr; /* Number of output pointers used */
    169    int max_output_ptr; /* Size of output_ptr */
    170    png_charpp output_ptr; /* Array of pointers to output */
    171 } compression_state;
    172 
    173 /* Compress given text into storage in the png_ptr structure */
    174 static int /* PRIVATE */
    175 png_text_compress(png_structp png_ptr,
    176         png_charp text, png_size_t text_len, int compression,
    177         compression_state *comp)
    178 {
    179    int ret;
    180 
    181    comp->num_output_ptr = 0;
    182    comp->max_output_ptr = 0;
    183    comp->output_ptr = NULL;
    184    comp->input = NULL;
    185    comp->input_len = 0;
    186 
    187    /* We may just want to pass the text right through */
    188    if (compression == PNG_TEXT_COMPRESSION_NONE)
    189    {
    190        comp->input = text;
    191        comp->input_len = text_len;
    192        return((int)text_len);
    193    }
    194 
    195    if (compression >= PNG_TEXT_COMPRESSION_LAST)
    196    {
    197 #if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
    198       char msg[50];
    199       png_snprintf(msg, 50, "Unknown compression type %d", compression);
    200       png_warning(png_ptr, msg);
    201 #else
    202       png_warning(png_ptr, "Unknown compression type");
    203 #endif
    204    }
    205 
    206    /* We can't write the chunk until we find out how much data we have,
    207     * which means we need to run the compressor first and save the
    208     * output.  This shouldn't be a problem, as the vast majority of
    209     * comments should be reasonable, but we will set up an array of
    210     * malloc'd pointers to be sure.
    211     *
    212     * If we knew the application was well behaved, we could simplify this
    213     * greatly by assuming we can always malloc an output buffer large
    214     * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
    215     * and malloc this directly.  The only time this would be a bad idea is
    216     * if we can't malloc more than 64K and we have 64K of random input
    217     * data, or if the input string is incredibly large (although this
    218     * wouldn't cause a failure, just a slowdown due to swapping).
    219     */
    220 
    221    /* Set up the compression buffers */
    222    png_ptr->zstream.avail_in = (uInt)text_len;
    223    png_ptr->zstream.next_in = (Bytef *)text;
    224    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
    225    png_ptr->zstream.next_out = (Bytef *)png_ptr->zbuf;
    226 
    227    /* This is the same compression loop as in png_write_row() */
    228    do
    229    {
    230       /* Compress the data */
    231       ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
    232       if (ret != Z_OK)
    233       {
    234          /* Error */
    235          if (png_ptr->zstream.msg != NULL)
    236             png_error(png_ptr, png_ptr->zstream.msg);
    237          else
    238             png_error(png_ptr, "zlib error");
    239       }
    240       /* Check to see if we need more room */
    241       if (!(png_ptr->zstream.avail_out))
    242       {
    243          /* Make sure the output array has room */
    244          if (comp->num_output_ptr >= comp->max_output_ptr)
    245          {
    246             int old_max;
    247 
    248             old_max = comp->max_output_ptr;
    249             comp->max_output_ptr = comp->num_output_ptr + 4;
    250             if (comp->output_ptr != NULL)
    251             {
    252                png_charpp old_ptr;
    253 
    254                old_ptr = comp->output_ptr;
    255                comp->output_ptr = (png_charpp)png_malloc(png_ptr,
    256                   (png_uint_32)
    257                   (comp->max_output_ptr * png_sizeof(png_charpp)));
    258                png_memcpy(comp->output_ptr, old_ptr, old_max
    259                   * png_sizeof(png_charp));
    260                png_free(png_ptr, old_ptr);
    261             }
    262             else
    263                comp->output_ptr = (png_charpp)png_malloc(png_ptr,
    264                   (png_uint_32)
    265                   (comp->max_output_ptr * png_sizeof(png_charp)));
    266          }
    267 
    268          /* Save the data */
    269          comp->output_ptr[comp->num_output_ptr] =
    270             (png_charp)png_malloc(png_ptr,
    271             (png_uint_32)png_ptr->zbuf_size);
    272          png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
    273             png_ptr->zbuf_size);
    274          comp->num_output_ptr++;
    275 
    276          /* and reset the buffer */
    277          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
    278          png_ptr->zstream.next_out = png_ptr->zbuf;
    279       }
    280    /* Continue until we don't have any more to compress */
    281    } while (png_ptr->zstream.avail_in);
    282 
    283    /* Finish the compression */
    284    do
    285    {
    286       /* Tell zlib we are finished */
    287       ret = deflate(&png_ptr->zstream, Z_FINISH);
    288 
    289       if (ret == Z_OK)
    290       {
    291          /* Check to see if we need more room */
    292          if (!(png_ptr->zstream.avail_out))
    293          {
    294             /* Check to make sure our output array has room */
    295             if (comp->num_output_ptr >= comp->max_output_ptr)
    296             {
    297                int old_max;
    298 
    299                old_max = comp->max_output_ptr;
    300                comp->max_output_ptr = comp->num_output_ptr + 4;
    301                if (comp->output_ptr != NULL)
    302                {
    303                   png_charpp old_ptr;
    304 
    305                   old_ptr = comp->output_ptr;
    306                   /* This could be optimized to realloc() */
    307                   comp->output_ptr = (png_charpp)png_malloc(png_ptr,
    308                      (png_uint_32)(comp->max_output_ptr *
    309                      png_sizeof(png_charp)));
    310                   png_memcpy(comp->output_ptr, old_ptr,
    311                      old_max * png_sizeof(png_charp));
    312                   png_free(png_ptr, old_ptr);
    313                }
    314                else
    315                   comp->output_ptr = (png_charpp)png_malloc(png_ptr,
    316                      (png_uint_32)(comp->max_output_ptr *
    317                      png_sizeof(png_charp)));
    318             }
    319 
    320             /* Save the data */
    321             comp->output_ptr[comp->num_output_ptr] =
    322                (png_charp)png_malloc(png_ptr,
    323                (png_uint_32)png_ptr->zbuf_size);
    324             png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
    325                png_ptr->zbuf_size);
    326             comp->num_output_ptr++;
    327 
    328             /* and reset the buffer pointers */
    329             png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
    330             png_ptr->zstream.next_out = png_ptr->zbuf;
    331          }
    332       }
    333       else if (ret != Z_STREAM_END)
    334       {
    335          /* We got an error */
    336          if (png_ptr->zstream.msg != NULL)
    337             png_error(png_ptr, png_ptr->zstream.msg);
    338          else
    339             png_error(png_ptr, "zlib error");
    340       }
    341    } while (ret != Z_STREAM_END);
    342 
    343    /* Text length is number of buffers plus last buffer */
    344    text_len = png_ptr->zbuf_size * comp->num_output_ptr;
    345    if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
    346       text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
    347 
    348    return((int)text_len);
    349 }
    350 
    351 /* Ship the compressed text out via chunk writes */
    352 static void /* PRIVATE */
    353 png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
    354 {
    355    int i;
    356 
    357    /* Handle the no-compression case */
    358    if (comp->input)
    359    {
    360       png_write_chunk_data(png_ptr, (png_bytep)comp->input,
    361                             (png_size_t)comp->input_len);
    362       return;
    363    }
    364 
    365    /* Write saved output buffers, if any */
    366    for (i = 0; i < comp->num_output_ptr; i++)
    367    {
    368       png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i],
    369          (png_size_t)png_ptr->zbuf_size);
    370       png_free(png_ptr, comp->output_ptr[i]);
    371        comp->output_ptr[i]=NULL;
    372    }
    373    if (comp->max_output_ptr != 0)
    374       png_free(png_ptr, comp->output_ptr);
    375        comp->output_ptr=NULL;
    376    /* Write anything left in zbuf */
    377    if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
    378       png_write_chunk_data(png_ptr, png_ptr->zbuf,
    379          (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
    380 
    381    /* Reset zlib for another zTXt/iTXt or image data */
    382    deflateReset(&png_ptr->zstream);
    383    png_ptr->zstream.data_type = Z_BINARY;
    384 }
    385 #endif
    386 
    387 /* Write the IHDR chunk, and update the png_struct with the necessary
    388  * information.  Note that the rest of this code depends upon this
    389  * information being correct.
    390  */
    391 void /* PRIVATE */
    392 png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
    393    int bit_depth, int color_type, int compression_type, int filter_type,
    394    int interlace_type)
    395 {
    396 #ifdef PNG_USE_LOCAL_ARRAYS
    397    PNG_IHDR;
    398 #endif
    399    int ret;
    400 
    401    png_byte buf[13]; /* Buffer to store the IHDR info */
    402 
    403    png_debug(1, "in png_write_IHDR");
    404 
    405    /* Check that we have valid input data from the application info */
    406    switch (color_type)
    407    {
    408       case PNG_COLOR_TYPE_GRAY:
    409          switch (bit_depth)
    410          {
    411             case 1:
    412             case 2:
    413             case 4:
    414             case 8:
    415             case 16: png_ptr->channels = 1; break;
    416             default: png_error(png_ptr,
    417                          "Invalid bit depth for grayscale image");
    418          }
    419          break;
    420       case PNG_COLOR_TYPE_RGB:
    421          if (bit_depth != 8 && bit_depth != 16)
    422             png_error(png_ptr, "Invalid bit depth for RGB image");
    423          png_ptr->channels = 3;
    424          break;
    425       case PNG_COLOR_TYPE_PALETTE:
    426          switch (bit_depth)
    427          {
    428             case 1:
    429             case 2:
    430             case 4:
    431             case 8: png_ptr->channels = 1; break;
    432             default: png_error(png_ptr, "Invalid bit depth for paletted image");
    433          }
    434          break;
    435       case PNG_COLOR_TYPE_GRAY_ALPHA:
    436          if (bit_depth != 8 && bit_depth != 16)
    437             png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
    438          png_ptr->channels = 2;
    439          break;
    440       case PNG_COLOR_TYPE_RGB_ALPHA:
    441          if (bit_depth != 8 && bit_depth != 16)
    442             png_error(png_ptr, "Invalid bit depth for RGBA image");
    443          png_ptr->channels = 4;
    444          break;
    445       default:
    446          png_error(png_ptr, "Invalid image color type specified");
    447    }
    448 
    449    if (compression_type != PNG_COMPRESSION_TYPE_BASE)
    450    {
    451       png_warning(png_ptr, "Invalid compression type specified");
    452       compression_type = PNG_COMPRESSION_TYPE_BASE;
    453    }
    454 
    455    /* Write filter_method 64 (intrapixel differencing) only if
    456     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
    457     * 2. Libpng did not write a PNG signature (this filter_method is only
    458     *    used in PNG datastreams that are embedded in MNG datastreams) and
    459     * 3. The application called png_permit_mng_features with a mask that
    460     *    included PNG_FLAG_MNG_FILTER_64 and
    461     * 4. The filter_method is 64 and
    462     * 5. The color_type is RGB or RGBA
    463     */
    464    if (
    465 #ifdef PNG_MNG_FEATURES_SUPPORTED
    466       !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
    467       ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
    468       (color_type == PNG_COLOR_TYPE_RGB ||
    469        color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
    470       (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
    471 #endif
    472       filter_type != PNG_FILTER_TYPE_BASE)
    473    {
    474       png_warning(png_ptr, "Invalid filter type specified");
    475       filter_type = PNG_FILTER_TYPE_BASE;
    476    }
    477 
    478 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
    479    if (interlace_type != PNG_INTERLACE_NONE &&
    480       interlace_type != PNG_INTERLACE_ADAM7)
    481    {
    482       png_warning(png_ptr, "Invalid interlace type specified");
    483       interlace_type = PNG_INTERLACE_ADAM7;
    484    }
    485 #else
    486    interlace_type=PNG_INTERLACE_NONE;
    487 #endif
    488 
    489    /* Save the relevent information */
    490    png_ptr->bit_depth = (png_byte)bit_depth;
    491    png_ptr->color_type = (png_byte)color_type;
    492    png_ptr->interlaced = (png_byte)interlace_type;
    493 #ifdef PNG_MNG_FEATURES_SUPPORTED
    494    png_ptr->filter_type = (png_byte)filter_type;
    495 #endif
    496    png_ptr->compression_type = (png_byte)compression_type;
    497    png_ptr->width = width;
    498    png_ptr->height = height;
    499 
    500    png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
    501    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
    502    /* Set the usr info, so any transformations can modify it */
    503    png_ptr->usr_width = png_ptr->width;
    504    png_ptr->usr_bit_depth = png_ptr->bit_depth;
    505    png_ptr->usr_channels = png_ptr->channels;
    506 
    507    /* Pack the header information into the buffer */
    508    png_save_uint_32(buf, width);
    509    png_save_uint_32(buf + 4, height);
    510    buf[8] = (png_byte)bit_depth;
    511    buf[9] = (png_byte)color_type;
    512    buf[10] = (png_byte)compression_type;
    513    buf[11] = (png_byte)filter_type;
    514    buf[12] = (png_byte)interlace_type;
    515 
    516    /* Write the chunk */
    517    png_write_chunk(png_ptr, (png_bytep)png_IHDR, buf, (png_size_t)13);
    518 
    519    /* Initialize zlib with PNG info */
    520    png_ptr->zstream.zalloc = png_zalloc;
    521    png_ptr->zstream.zfree = png_zfree;
    522    png_ptr->zstream.opaque = (voidpf)png_ptr;
    523    if (!(png_ptr->do_filter))
    524    {
    525       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
    526          png_ptr->bit_depth < 8)
    527          png_ptr->do_filter = PNG_FILTER_NONE;
    528       else
    529          png_ptr->do_filter = PNG_ALL_FILTERS;
    530    }
    531    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
    532    {
    533       if (png_ptr->do_filter != PNG_FILTER_NONE)
    534          png_ptr->zlib_strategy = Z_FILTERED;
    535       else
    536          png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
    537    }
    538    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
    539       png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
    540    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
    541       png_ptr->zlib_mem_level = 8;
    542    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
    543       png_ptr->zlib_window_bits = 15;
    544    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
    545       png_ptr->zlib_method = 8;
    546    ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
    547          png_ptr->zlib_method, png_ptr->zlib_window_bits,
    548          png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
    549    if (ret != Z_OK)
    550    {
    551       if (ret == Z_VERSION_ERROR) png_error(png_ptr,
    552           "zlib failed to initialize compressor -- version error");
    553       if (ret == Z_STREAM_ERROR) png_error(png_ptr,
    554            "zlib failed to initialize compressor -- stream error");
    555       if (ret == Z_MEM_ERROR) png_error(png_ptr,
    556            "zlib failed to initialize compressor -- mem error");
    557       png_error(png_ptr, "zlib failed to initialize compressor");
    558    }
    559    png_ptr->zstream.next_out = png_ptr->zbuf;
    560    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
    561    /* libpng is not interested in zstream.data_type */
    562    /* Set it to a predefined value, to avoid its evaluation inside zlib */
    563    png_ptr->zstream.data_type = Z_BINARY;
    564 
    565    png_ptr->mode = PNG_HAVE_IHDR;
    566 }
    567 
    568 /* Write the palette.  We are careful not to trust png_color to be in the
    569  * correct order for PNG, so people can redefine it to any convenient
    570  * structure.
    571  */
    572 void /* PRIVATE */
    573 png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
    574 {
    575 #ifdef PNG_USE_LOCAL_ARRAYS
    576    PNG_PLTE;
    577 #endif
    578    png_uint_32 i;
    579    png_colorp pal_ptr;
    580    png_byte buf[3];
    581 
    582    png_debug(1, "in png_write_PLTE");
    583 
    584    if ((
    585 #ifdef PNG_MNG_FEATURES_SUPPORTED
    586         !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
    587 #endif
    588         num_pal == 0) || num_pal > 256)
    589    {
    590      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
    591      {
    592         png_error(png_ptr, "Invalid number of colors in palette");
    593      }
    594      else
    595      {
    596         png_warning(png_ptr, "Invalid number of colors in palette");
    597         return;
    598      }
    599    }
    600 
    601    if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
    602    {
    603       png_warning(png_ptr,
    604         "Ignoring request to write a PLTE chunk in grayscale PNG");
    605       return;
    606    }
    607 
    608    png_ptr->num_palette = (png_uint_16)num_pal;
    609    png_debug1(3, "num_palette = %d", png_ptr->num_palette);
    610 
    611    png_write_chunk_start(png_ptr, (png_bytep)png_PLTE,
    612      (png_uint_32)(num_pal * 3));
    613 #ifdef PNG_POINTER_INDEXING_SUPPORTED
    614    for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
    615    {
    616       buf[0] = pal_ptr->red;
    617       buf[1] = pal_ptr->green;
    618       buf[2] = pal_ptr->blue;
    619       png_write_chunk_data(png_ptr, buf, (png_size_t)3);
    620    }
    621 #else
    622    /* This is a little slower but some buggy compilers need to do this
    623     * instead
    624     */
    625    pal_ptr=palette;
    626    for (i = 0; i < num_pal; i++)
    627    {
    628       buf[0] = pal_ptr[i].red;
    629       buf[1] = pal_ptr[i].green;
    630       buf[2] = pal_ptr[i].blue;
    631       png_write_chunk_data(png_ptr, buf, (png_size_t)3);
    632    }
    633 #endif
    634    png_write_chunk_end(png_ptr);
    635    png_ptr->mode |= PNG_HAVE_PLTE;
    636 }
    637 
    638 /* Write an IDAT chunk */
    639 void /* PRIVATE */
    640 png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
    641 {
    642 #ifdef PNG_USE_LOCAL_ARRAYS
    643    PNG_IDAT;
    644 #endif
    645 
    646    png_debug(1, "in png_write_IDAT");
    647 
    648    /* Optimize the CMF field in the zlib stream. */
    649    /* This hack of the zlib stream is compliant to the stream specification. */
    650    if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
    651        png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
    652    {
    653       unsigned int z_cmf = data[0];  /* zlib compression method and flags */
    654       if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
    655       {
    656          /* Avoid memory underflows and multiplication overflows.
    657           *
    658           * The conditions below are practically always satisfied;
    659           * however, they still must be checked.
    660           */
    661          if (length >= 2 &&
    662              png_ptr->height < 16384 && png_ptr->width < 16384)
    663          {
    664             png_uint_32 uncompressed_idat_size = png_ptr->height *
    665                ((png_ptr->width *
    666                png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
    667             unsigned int z_cinfo = z_cmf >> 4;
    668             unsigned int half_z_window_size = 1 << (z_cinfo + 7);
    669             while (uncompressed_idat_size <= half_z_window_size &&
    670                    half_z_window_size >= 256)
    671             {
    672                z_cinfo--;
    673                half_z_window_size >>= 1;
    674             }
    675             z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
    676             if (data[0] != (png_byte)z_cmf)
    677             {
    678                data[0] = (png_byte)z_cmf;
    679                data[1] &= 0xe0;
    680                data[1] += (png_byte)(0x1f - ((z_cmf << 8) + data[1]) % 0x1f);
    681             }
    682          }
    683       }
    684       else
    685          png_error(png_ptr,
    686             "Invalid zlib compression method or flags in IDAT");
    687    }
    688 
    689    png_write_chunk(png_ptr, (png_bytep)png_IDAT, data, length);
    690    png_ptr->mode |= PNG_HAVE_IDAT;
    691 }
    692 
    693 /* Write an IEND chunk */
    694 void /* PRIVATE */
    695 png_write_IEND(png_structp png_ptr)
    696 {
    697 #ifdef PNG_USE_LOCAL_ARRAYS
    698    PNG_IEND;
    699 #endif
    700 
    701    png_debug(1, "in png_write_IEND");
    702 
    703    png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL,
    704      (png_size_t)0);
    705    png_ptr->mode |= PNG_HAVE_IEND;
    706 }
    707 
    708 #ifdef PNG_WRITE_gAMA_SUPPORTED
    709 /* Write a gAMA chunk */
    710 #ifdef PNG_FLOATING_POINT_SUPPORTED
    711 void /* PRIVATE */
    712 png_write_gAMA(png_structp png_ptr, double file_gamma)
    713 {
    714 #ifdef PNG_USE_LOCAL_ARRAYS
    715    PNG_gAMA;
    716 #endif
    717    png_uint_32 igamma;
    718    png_byte buf[4];
    719 
    720    png_debug(1, "in png_write_gAMA");
    721 
    722    /* file_gamma is saved in 1/100,000ths */
    723    igamma = (png_uint_32)(file_gamma * 100000.0 + 0.5);
    724    png_save_uint_32(buf, igamma);
    725    png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
    726 }
    727 #endif
    728 #ifdef PNG_FIXED_POINT_SUPPORTED
    729 void /* PRIVATE */
    730 png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
    731 {
    732 #ifdef PNG_USE_LOCAL_ARRAYS
    733    PNG_gAMA;
    734 #endif
    735    png_byte buf[4];
    736 
    737    png_debug(1, "in png_write_gAMA");
    738 
    739    /* file_gamma is saved in 1/100,000ths */
    740    png_save_uint_32(buf, (png_uint_32)file_gamma);
    741    png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
    742 }
    743 #endif
    744 #endif
    745 
    746 #ifdef PNG_WRITE_sRGB_SUPPORTED
    747 /* Write a sRGB chunk */
    748 void /* PRIVATE */
    749 png_write_sRGB(png_structp png_ptr, int srgb_intent)
    750 {
    751 #ifdef PNG_USE_LOCAL_ARRAYS
    752    PNG_sRGB;
    753 #endif
    754    png_byte buf[1];
    755 
    756    png_debug(1, "in png_write_sRGB");
    757 
    758    if (srgb_intent >= PNG_sRGB_INTENT_LAST)
    759          png_warning(png_ptr,
    760             "Invalid sRGB rendering intent specified");
    761    buf[0]=(png_byte)srgb_intent;
    762    png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1);
    763 }
    764 #endif
    765 
    766 #ifdef PNG_WRITE_iCCP_SUPPORTED
    767 /* Write an iCCP chunk */
    768 void /* PRIVATE */
    769 png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
    770    png_charp profile, int profile_len)
    771 {
    772 #ifdef PNG_USE_LOCAL_ARRAYS
    773    PNG_iCCP;
    774 #endif
    775    png_size_t name_len;
    776    png_charp new_name;
    777    compression_state comp;
    778    int embedded_profile_len = 0;
    779 
    780    png_debug(1, "in png_write_iCCP");
    781 
    782    comp.num_output_ptr = 0;
    783    comp.max_output_ptr = 0;
    784    comp.output_ptr = NULL;
    785    comp.input = NULL;
    786    comp.input_len = 0;
    787 
    788    if ((name_len = png_check_keyword(png_ptr, name,
    789       &new_name)) == 0)
    790       return;
    791 
    792    if (compression_type != PNG_COMPRESSION_TYPE_BASE)
    793       png_warning(png_ptr, "Unknown compression type in iCCP chunk");
    794 
    795    if (profile == NULL)
    796       profile_len = 0;
    797 
    798    if (profile_len > 3)
    799       embedded_profile_len =
    800           ((*( (png_bytep)profile    ))<<24) |
    801           ((*( (png_bytep)profile + 1))<<16) |
    802           ((*( (png_bytep)profile + 2))<< 8) |
    803           ((*( (png_bytep)profile + 3))    );
    804 
    805    if (embedded_profile_len < 0)
    806    {
    807       png_warning(png_ptr,
    808         "Embedded profile length in iCCP chunk is negative");
    809       png_free(png_ptr, new_name);
    810       return;
    811    }
    812 
    813    if (profile_len < embedded_profile_len)
    814    {
    815       png_warning(png_ptr,
    816         "Embedded profile length too large in iCCP chunk");
    817       png_free(png_ptr, new_name);
    818       return;
    819    }
    820 
    821    if (profile_len > embedded_profile_len)
    822    {
    823       png_warning(png_ptr,
    824         "Truncating profile to actual length in iCCP chunk");
    825       profile_len = embedded_profile_len;
    826    }
    827 
    828    if (profile_len)
    829       profile_len = png_text_compress(png_ptr, profile,
    830         (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp);
    831 
    832    /* Make sure we include the NULL after the name and the compression type */
    833    png_write_chunk_start(png_ptr, (png_bytep)png_iCCP,
    834           (png_uint_32)(name_len + profile_len + 2));
    835    new_name[name_len + 1] = 0x00;
    836    png_write_chunk_data(png_ptr, (png_bytep)new_name,
    837      (png_size_t)(name_len + 2));
    838 
    839    if (profile_len)
    840       png_write_compressed_data_out(png_ptr, &comp);
    841 
    842    png_write_chunk_end(png_ptr);
    843    png_free(png_ptr, new_name);
    844 }
    845 #endif
    846 
    847 #ifdef PNG_WRITE_sPLT_SUPPORTED
    848 /* Write a sPLT chunk */
    849 void /* PRIVATE */
    850 png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
    851 {
    852 #ifdef PNG_USE_LOCAL_ARRAYS
    853    PNG_sPLT;
    854 #endif
    855    png_size_t name_len;
    856    png_charp new_name;
    857    png_byte entrybuf[10];
    858    int entry_size = (spalette->depth == 8 ? 6 : 10);
    859    int palette_size = entry_size * spalette->nentries;
    860    png_sPLT_entryp ep;
    861 #ifndef PNG_POINTER_INDEXING_SUPPORTED
    862    int i;
    863 #endif
    864 
    865    png_debug(1, "in png_write_sPLT");
    866 
    867    if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0)
    868       return;
    869 
    870    /* Make sure we include the NULL after the name */
    871    png_write_chunk_start(png_ptr, (png_bytep)png_sPLT,
    872      (png_uint_32)(name_len + 2 + palette_size));
    873    png_write_chunk_data(png_ptr, (png_bytep)new_name,
    874      (png_size_t)(name_len + 1));
    875    png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1);
    876 
    877    /* Loop through each palette entry, writing appropriately */
    878 #ifdef PNG_POINTER_INDEXING_SUPPORTED
    879    for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
    880    {
    881       if (spalette->depth == 8)
    882       {
    883           entrybuf[0] = (png_byte)ep->red;
    884           entrybuf[1] = (png_byte)ep->green;
    885           entrybuf[2] = (png_byte)ep->blue;
    886           entrybuf[3] = (png_byte)ep->alpha;
    887           png_save_uint_16(entrybuf + 4, ep->frequency);
    888       }
    889       else
    890       {
    891           png_save_uint_16(entrybuf + 0, ep->red);
    892           png_save_uint_16(entrybuf + 2, ep->green);
    893           png_save_uint_16(entrybuf + 4, ep->blue);
    894           png_save_uint_16(entrybuf + 6, ep->alpha);
    895           png_save_uint_16(entrybuf + 8, ep->frequency);
    896       }
    897       png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
    898    }
    899 #else
    900    ep=spalette->entries;
    901    for (i=0; i>spalette->nentries; i++)
    902    {
    903       if (spalette->depth == 8)
    904       {
    905           entrybuf[0] = (png_byte)ep[i].red;
    906           entrybuf[1] = (png_byte)ep[i].green;
    907           entrybuf[2] = (png_byte)ep[i].blue;
    908           entrybuf[3] = (png_byte)ep[i].alpha;
    909           png_save_uint_16(entrybuf + 4, ep[i].frequency);
    910       }
    911       else
    912       {
    913           png_save_uint_16(entrybuf + 0, ep[i].red);
    914           png_save_uint_16(entrybuf + 2, ep[i].green);
    915           png_save_uint_16(entrybuf + 4, ep[i].blue);
    916           png_save_uint_16(entrybuf + 6, ep[i].alpha);
    917           png_save_uint_16(entrybuf + 8, ep[i].frequency);
    918       }
    919       png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
    920    }
    921 #endif
    922 
    923    png_write_chunk_end(png_ptr);
    924    png_free(png_ptr, new_name);
    925 }
    926 #endif
    927 
    928 #ifdef PNG_WRITE_sBIT_SUPPORTED
    929 /* Write the sBIT chunk */
    930 void /* PRIVATE */
    931 png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
    932 {
    933 #ifdef PNG_USE_LOCAL_ARRAYS
    934    PNG_sBIT;
    935 #endif
    936    png_byte buf[4];
    937    png_size_t size;
    938 
    939    png_debug(1, "in png_write_sBIT");
    940 
    941    /* Make sure we don't depend upon the order of PNG_COLOR_8 */
    942    if (color_type & PNG_COLOR_MASK_COLOR)
    943    {
    944       png_byte maxbits;
    945 
    946       maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
    947                 png_ptr->usr_bit_depth);
    948       if (sbit->red == 0 || sbit->red > maxbits ||
    949           sbit->green == 0 || sbit->green > maxbits ||
    950           sbit->blue == 0 || sbit->blue > maxbits)
    951       {
    952          png_warning(png_ptr, "Invalid sBIT depth specified");
    953          return;
    954       }
    955       buf[0] = sbit->red;
    956       buf[1] = sbit->green;
    957       buf[2] = sbit->blue;
    958       size = 3;
    959    }
    960    else
    961    {
    962       if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
    963       {
    964          png_warning(png_ptr, "Invalid sBIT depth specified");
    965          return;
    966       }
    967       buf[0] = sbit->gray;
    968       size = 1;
    969    }
    970 
    971    if (color_type & PNG_COLOR_MASK_ALPHA)
    972    {
    973       if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
    974       {
    975          png_warning(png_ptr, "Invalid sBIT depth specified");
    976          return;
    977       }
    978       buf[size++] = sbit->alpha;
    979    }
    980 
    981    png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size);
    982 }
    983 #endif
    984 
    985 #ifdef PNG_WRITE_cHRM_SUPPORTED
    986 /* Write the cHRM chunk */
    987 #ifdef PNG_FLOATING_POINT_SUPPORTED
    988 void /* PRIVATE */
    989 png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
    990    double red_x, double red_y, double green_x, double green_y,
    991    double blue_x, double blue_y)
    992 {
    993 #ifdef PNG_USE_LOCAL_ARRAYS
    994    PNG_cHRM;
    995 #endif
    996    png_byte buf[32];
    997 
    998    png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y,
    999       int_green_x, int_green_y, int_blue_x, int_blue_y;
   1000 
   1001    png_debug(1, "in png_write_cHRM");
   1002 
   1003    int_white_x = (png_uint_32)(white_x * 100000.0 + 0.5);
   1004    int_white_y = (png_uint_32)(white_y * 100000.0 + 0.5);
   1005    int_red_x   = (png_uint_32)(red_x   * 100000.0 + 0.5);
   1006    int_red_y   = (png_uint_32)(red_y   * 100000.0 + 0.5);
   1007    int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5);
   1008    int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5);
   1009    int_blue_x  = (png_uint_32)(blue_x  * 100000.0 + 0.5);
   1010    int_blue_y  = (png_uint_32)(blue_y  * 100000.0 + 0.5);
   1011 
   1012 #ifdef PNG_CHECK_cHRM_SUPPORTED
   1013    if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y,
   1014       int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y))
   1015 #endif
   1016    {
   1017       /* Each value is saved in 1/100,000ths */
   1018 
   1019       png_save_uint_32(buf, int_white_x);
   1020       png_save_uint_32(buf + 4, int_white_y);
   1021 
   1022       png_save_uint_32(buf + 8, int_red_x);
   1023       png_save_uint_32(buf + 12, int_red_y);
   1024 
   1025       png_save_uint_32(buf + 16, int_green_x);
   1026       png_save_uint_32(buf + 20, int_green_y);
   1027 
   1028       png_save_uint_32(buf + 24, int_blue_x);
   1029       png_save_uint_32(buf + 28, int_blue_y);
   1030 
   1031       png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
   1032    }
   1033 }
   1034 #endif
   1035 #ifdef PNG_FIXED_POINT_SUPPORTED
   1036 void /* PRIVATE */
   1037 png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
   1038    png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
   1039    png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
   1040    png_fixed_point blue_y)
   1041 {
   1042 #ifdef PNG_USE_LOCAL_ARRAYS
   1043    PNG_cHRM;
   1044 #endif
   1045    png_byte buf[32];
   1046 
   1047    png_debug(1, "in png_write_cHRM");
   1048 
   1049    /* Each value is saved in 1/100,000ths */
   1050 #ifdef PNG_CHECK_cHRM_SUPPORTED
   1051    if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
   1052       green_x, green_y, blue_x, blue_y))
   1053 #endif
   1054    {
   1055       png_save_uint_32(buf, (png_uint_32)white_x);
   1056       png_save_uint_32(buf + 4, (png_uint_32)white_y);
   1057 
   1058       png_save_uint_32(buf + 8, (png_uint_32)red_x);
   1059       png_save_uint_32(buf + 12, (png_uint_32)red_y);
   1060 
   1061       png_save_uint_32(buf + 16, (png_uint_32)green_x);
   1062       png_save_uint_32(buf + 20, (png_uint_32)green_y);
   1063 
   1064       png_save_uint_32(buf + 24, (png_uint_32)blue_x);
   1065       png_save_uint_32(buf + 28, (png_uint_32)blue_y);
   1066 
   1067       png_write_chunk(png_ptr, (png_bytep)png_cHRM, buf, (png_size_t)32);
   1068    }
   1069 }
   1070 #endif
   1071 #endif
   1072 
   1073 #ifdef PNG_WRITE_tRNS_SUPPORTED
   1074 /* Write the tRNS chunk */
   1075 void /* PRIVATE */
   1076 png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
   1077    int num_trans, int color_type)
   1078 {
   1079 #ifdef PNG_USE_LOCAL_ARRAYS
   1080    PNG_tRNS;
   1081 #endif
   1082    png_byte buf[6];
   1083 
   1084    png_debug(1, "in png_write_tRNS");
   1085 
   1086    if (color_type == PNG_COLOR_TYPE_PALETTE)
   1087    {
   1088       if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
   1089       {
   1090          png_warning(png_ptr, "Invalid number of transparent colors specified");
   1091          return;
   1092       }
   1093       /* Write the chunk out as it is */
   1094       png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans,
   1095         (png_size_t)num_trans);
   1096    }
   1097    else if (color_type == PNG_COLOR_TYPE_GRAY)
   1098    {
   1099       /* One 16 bit value */
   1100       if (tran->gray >= (1 << png_ptr->bit_depth))
   1101       {
   1102          png_warning(png_ptr,
   1103            "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
   1104          return;
   1105       }
   1106       png_save_uint_16(buf, tran->gray);
   1107       png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)2);
   1108    }
   1109    else if (color_type == PNG_COLOR_TYPE_RGB)
   1110    {
   1111       /* Three 16 bit values */
   1112       png_save_uint_16(buf, tran->red);
   1113       png_save_uint_16(buf + 2, tran->green);
   1114       png_save_uint_16(buf + 4, tran->blue);
   1115       if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
   1116       {
   1117          png_warning(png_ptr,
   1118            "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
   1119          return;
   1120       }
   1121       png_write_chunk(png_ptr, (png_bytep)png_tRNS, buf, (png_size_t)6);
   1122    }
   1123    else
   1124    {
   1125       png_warning(png_ptr, "Can't write tRNS with an alpha channel");
   1126    }
   1127 }
   1128 #endif
   1129 
   1130 #ifdef PNG_WRITE_bKGD_SUPPORTED
   1131 /* Write the background chunk */
   1132 void /* PRIVATE */
   1133 png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
   1134 {
   1135 #ifdef PNG_USE_LOCAL_ARRAYS
   1136    PNG_bKGD;
   1137 #endif
   1138    png_byte buf[6];
   1139 
   1140    png_debug(1, "in png_write_bKGD");
   1141 
   1142    if (color_type == PNG_COLOR_TYPE_PALETTE)
   1143    {
   1144       if (
   1145 #ifdef PNG_MNG_FEATURES_SUPPORTED
   1146           (png_ptr->num_palette ||
   1147           (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
   1148 #endif
   1149          back->index >= png_ptr->num_palette)
   1150       {
   1151          png_warning(png_ptr, "Invalid background palette index");
   1152          return;
   1153       }
   1154       buf[0] = back->index;
   1155       png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)1);
   1156    }
   1157    else if (color_type & PNG_COLOR_MASK_COLOR)
   1158    {
   1159       png_save_uint_16(buf, back->red);
   1160       png_save_uint_16(buf + 2, back->green);
   1161       png_save_uint_16(buf + 4, back->blue);
   1162       if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
   1163       {
   1164          png_warning(png_ptr,
   1165            "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
   1166          return;
   1167       }
   1168       png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)6);
   1169    }
   1170    else
   1171    {
   1172       if (back->gray >= (1 << png_ptr->bit_depth))
   1173       {
   1174          png_warning(png_ptr,
   1175            "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
   1176          return;
   1177       }
   1178       png_save_uint_16(buf, back->gray);
   1179       png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2);
   1180    }
   1181 }
   1182 #endif
   1183 
   1184 #ifdef PNG_WRITE_hIST_SUPPORTED
   1185 /* Write the histogram */
   1186 void /* PRIVATE */
   1187 png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
   1188 {
   1189 #ifdef PNG_USE_LOCAL_ARRAYS
   1190    PNG_hIST;
   1191 #endif
   1192    int i;
   1193    png_byte buf[3];
   1194 
   1195    png_debug(1, "in png_write_hIST");
   1196 
   1197    if (num_hist > (int)png_ptr->num_palette)
   1198    {
   1199       png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
   1200          png_ptr->num_palette);
   1201       png_warning(png_ptr, "Invalid number of histogram entries specified");
   1202       return;
   1203    }
   1204 
   1205    png_write_chunk_start(png_ptr, (png_bytep)png_hIST,
   1206      (png_uint_32)(num_hist * 2));
   1207    for (i = 0; i < num_hist; i++)
   1208    {
   1209       png_save_uint_16(buf, hist[i]);
   1210       png_write_chunk_data(png_ptr, buf, (png_size_t)2);
   1211    }
   1212    png_write_chunk_end(png_ptr);
   1213 }
   1214 #endif
   1215 
   1216 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
   1217     defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
   1218 /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
   1219  * and if invalid, correct the keyword rather than discarding the entire
   1220  * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
   1221  * length, forbids leading or trailing whitespace, multiple internal spaces,
   1222  * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
   1223  *
   1224  * The new_key is allocated to hold the corrected keyword and must be freed
   1225  * by the calling routine.  This avoids problems with trying to write to
   1226  * static keywords without having to have duplicate copies of the strings.
   1227  */
   1228 png_size_t /* PRIVATE */
   1229 png_check_keyword(png_structp png_ptr, png_charp key, png_charpp new_key)
   1230 {
   1231    png_size_t key_len;
   1232    png_charp kp, dp;
   1233    int kflag;
   1234    int kwarn=0;
   1235 
   1236    png_debug(1, "in png_check_keyword");
   1237 
   1238    *new_key = NULL;
   1239 
   1240    if (key == NULL || (key_len = png_strlen(key)) == 0)
   1241    {
   1242       png_warning(png_ptr, "zero length keyword");
   1243       return ((png_size_t)0);
   1244    }
   1245 
   1246    png_debug1(2, "Keyword to be checked is '%s'", key);
   1247 
   1248    *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
   1249    if (*new_key == NULL)
   1250    {
   1251       png_warning(png_ptr, "Out of memory while procesing keyword");
   1252       return ((png_size_t)0);
   1253    }
   1254 
   1255    /* Replace non-printing characters with a blank and print a warning */
   1256    for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
   1257    {
   1258       if ((png_byte)*kp < 0x20 ||
   1259          ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1))
   1260       {
   1261 #if defined(PNG_STDIO_SUPPORTED) && !defined(_WIN32_WCE)
   1262          char msg[40];
   1263 
   1264          png_snprintf(msg, 40,
   1265            "invalid keyword character 0x%02X", (png_byte)*kp);
   1266          png_warning(png_ptr, msg);
   1267 #else
   1268          png_warning(png_ptr, "invalid character in keyword");
   1269 #endif
   1270          *dp = ' ';
   1271       }
   1272       else
   1273       {
   1274          *dp = *kp;
   1275       }
   1276    }
   1277    *dp = '\0';
   1278 
   1279    /* Remove any trailing white space. */
   1280    kp = *new_key + key_len - 1;
   1281    if (*kp == ' ')
   1282    {
   1283       png_warning(png_ptr, "trailing spaces removed from keyword");
   1284 
   1285       while (*kp == ' ')
   1286       {
   1287          *(kp--) = '\0';
   1288          key_len--;
   1289       }
   1290    }
   1291 
   1292    /* Remove any leading white space. */
   1293    kp = *new_key;
   1294    if (*kp == ' ')
   1295    {
   1296       png_warning(png_ptr, "leading spaces removed from keyword");
   1297 
   1298       while (*kp == ' ')
   1299       {
   1300          kp++;
   1301          key_len--;
   1302       }
   1303    }
   1304 
   1305    png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
   1306 
   1307    /* Remove multiple internal spaces. */
   1308    for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
   1309    {
   1310       if (*kp == ' ' && kflag == 0)
   1311       {
   1312          *(dp++) = *kp;
   1313          kflag = 1;
   1314       }
   1315       else if (*kp == ' ')
   1316       {
   1317          key_len--;
   1318          kwarn=1;
   1319       }
   1320       else
   1321       {
   1322          *(dp++) = *kp;
   1323          kflag = 0;
   1324       }
   1325    }
   1326    *dp = '\0';
   1327    if (kwarn)
   1328       png_warning(png_ptr, "extra interior spaces removed from keyword");
   1329 
   1330    if (key_len == 0)
   1331    {
   1332       png_free(png_ptr, *new_key);
   1333        *new_key=NULL;
   1334       png_warning(png_ptr, "Zero length keyword");
   1335    }
   1336 
   1337    if (key_len > 79)
   1338    {
   1339       png_warning(png_ptr, "keyword length must be 1 - 79 characters");
   1340       (*new_key)[79] = '\0';
   1341       key_len = 79;
   1342    }
   1343 
   1344    return (key_len);
   1345 }
   1346 #endif
   1347 
   1348 #ifdef PNG_WRITE_tEXt_SUPPORTED
   1349 /* Write a tEXt chunk */
   1350 void /* PRIVATE */
   1351 png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
   1352    png_size_t text_len)
   1353 {
   1354 #ifdef PNG_USE_LOCAL_ARRAYS
   1355    PNG_tEXt;
   1356 #endif
   1357    png_size_t key_len;
   1358    png_charp new_key;
   1359 
   1360    png_debug(1, "in png_write_tEXt");
   1361 
   1362    if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
   1363       return;
   1364 
   1365    if (text == NULL || *text == '\0')
   1366       text_len = 0;
   1367    else
   1368       text_len = png_strlen(text);
   1369 
   1370    /* Make sure we include the 0 after the key */
   1371    png_write_chunk_start(png_ptr, (png_bytep)png_tEXt,
   1372       (png_uint_32)(key_len + text_len + 1));
   1373    /*
   1374     * We leave it to the application to meet PNG-1.0 requirements on the
   1375     * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
   1376     * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
   1377     * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
   1378     */
   1379    png_write_chunk_data(png_ptr, (png_bytep)new_key,
   1380      (png_size_t)(key_len + 1));
   1381    if (text_len)
   1382       png_write_chunk_data(png_ptr, (png_bytep)text, (png_size_t)text_len);
   1383 
   1384    png_write_chunk_end(png_ptr);
   1385    png_free(png_ptr, new_key);
   1386 }
   1387 #endif
   1388 
   1389 #ifdef PNG_WRITE_zTXt_SUPPORTED
   1390 /* Write a compressed text chunk */
   1391 void /* PRIVATE */
   1392 png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
   1393    png_size_t text_len, int compression)
   1394 {
   1395 #ifdef PNG_USE_LOCAL_ARRAYS
   1396    PNG_zTXt;
   1397 #endif
   1398    png_size_t key_len;
   1399    char buf[1];
   1400    png_charp new_key;
   1401    compression_state comp;
   1402 
   1403    png_debug(1, "in png_write_zTXt");
   1404 
   1405    comp.num_output_ptr = 0;
   1406    comp.max_output_ptr = 0;
   1407    comp.output_ptr = NULL;
   1408    comp.input = NULL;
   1409    comp.input_len = 0;
   1410 
   1411    if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
   1412    {
   1413       png_free(png_ptr, new_key);
   1414       return;
   1415    }
   1416 
   1417    if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
   1418    {
   1419       png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
   1420       png_free(png_ptr, new_key);
   1421       return;
   1422    }
   1423 
   1424    text_len = png_strlen(text);
   1425 
   1426    /* Compute the compressed data; do it now for the length */
   1427    text_len = png_text_compress(png_ptr, text, text_len, compression,
   1428        &comp);
   1429 
   1430    /* Write start of chunk */
   1431    png_write_chunk_start(png_ptr, (png_bytep)png_zTXt,
   1432      (png_uint_32)(key_len+text_len + 2));
   1433    /* Write key */
   1434    png_write_chunk_data(png_ptr, (png_bytep)new_key,
   1435      (png_size_t)(key_len + 1));
   1436    png_free(png_ptr, new_key);
   1437 
   1438    buf[0] = (png_byte)compression;
   1439    /* Write compression */
   1440    png_write_chunk_data(png_ptr, (png_bytep)buf, (png_size_t)1);
   1441    /* Write the compressed data */
   1442    png_write_compressed_data_out(png_ptr, &comp);
   1443 
   1444    /* Close the chunk */
   1445    png_write_chunk_end(png_ptr);
   1446 }
   1447 #endif
   1448 
   1449 #ifdef PNG_WRITE_iTXt_SUPPORTED
   1450 /* Write an iTXt chunk */
   1451 void /* PRIVATE */
   1452 png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
   1453     png_charp lang, png_charp lang_key, png_charp text)
   1454 {
   1455 #ifdef PNG_USE_LOCAL_ARRAYS
   1456    PNG_iTXt;
   1457 #endif
   1458    png_size_t lang_len, key_len, lang_key_len, text_len;
   1459    png_charp new_lang;
   1460    png_charp new_key = NULL;
   1461    png_byte cbuf[2];
   1462    compression_state comp;
   1463 
   1464    png_debug(1, "in png_write_iTXt");
   1465 
   1466    comp.num_output_ptr = 0;
   1467    comp.max_output_ptr = 0;
   1468    comp.output_ptr = NULL;
   1469    comp.input = NULL;
   1470 
   1471    if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
   1472       return;
   1473 
   1474    if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang))==0)
   1475    {
   1476       png_warning(png_ptr, "Empty language field in iTXt chunk");
   1477       new_lang = NULL;
   1478       lang_len = 0;
   1479    }
   1480 
   1481    if (lang_key == NULL)
   1482       lang_key_len = 0;
   1483    else
   1484       lang_key_len = png_strlen(lang_key);
   1485 
   1486    if (text == NULL)
   1487       text_len = 0;
   1488    else
   1489       text_len = png_strlen(text);
   1490 
   1491    /* Compute the compressed data; do it now for the length */
   1492    text_len = png_text_compress(png_ptr, text, text_len, compression-2,
   1493       &comp);
   1494 
   1495 
   1496    /* Make sure we include the compression flag, the compression byte,
   1497     * and the NULs after the key, lang, and lang_key parts */
   1498 
   1499    png_write_chunk_start(png_ptr, (png_bytep)png_iTXt,
   1500           (png_uint_32)(
   1501         5 /* comp byte, comp flag, terminators for key, lang and lang_key */
   1502         + key_len
   1503         + lang_len
   1504         + lang_key_len
   1505         + text_len));
   1506 
   1507    /* We leave it to the application to meet PNG-1.0 requirements on the
   1508     * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
   1509     * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
   1510     * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
   1511     */
   1512    png_write_chunk_data(png_ptr, (png_bytep)new_key,
   1513      (png_size_t)(key_len + 1));
   1514 
   1515    /* Set the compression flag */
   1516    if (compression == PNG_ITXT_COMPRESSION_NONE || \
   1517        compression == PNG_TEXT_COMPRESSION_NONE)
   1518        cbuf[0] = 0;
   1519    else /* compression == PNG_ITXT_COMPRESSION_zTXt */
   1520        cbuf[0] = 1;
   1521    /* Set the compression method */
   1522    cbuf[1] = 0;
   1523    png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
   1524 
   1525    cbuf[0] = 0;
   1526    png_write_chunk_data(png_ptr, (new_lang ? (png_bytep)new_lang : cbuf),
   1527      (png_size_t)(lang_len + 1));
   1528    png_write_chunk_data(png_ptr, (lang_key ? (png_bytep)lang_key : cbuf),
   1529      (png_size_t)(lang_key_len + 1));
   1530    png_write_compressed_data_out(png_ptr, &comp);
   1531 
   1532    png_write_chunk_end(png_ptr);
   1533    png_free(png_ptr, new_key);
   1534    png_free(png_ptr, new_lang);
   1535 }
   1536 #endif
   1537 
   1538 #ifdef PNG_WRITE_oFFs_SUPPORTED
   1539 /* Write the oFFs chunk */
   1540 void /* PRIVATE */
   1541 png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
   1542    int unit_type)
   1543 {
   1544 #ifdef PNG_USE_LOCAL_ARRAYS
   1545    PNG_oFFs;
   1546 #endif
   1547    png_byte buf[9];
   1548 
   1549    png_debug(1, "in png_write_oFFs");
   1550 
   1551    if (unit_type >= PNG_OFFSET_LAST)
   1552       png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
   1553 
   1554    png_save_int_32(buf, x_offset);
   1555    png_save_int_32(buf + 4, y_offset);
   1556    buf[8] = (png_byte)unit_type;
   1557 
   1558    png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9);
   1559 }
   1560 #endif
   1561 #ifdef PNG_WRITE_pCAL_SUPPORTED
   1562 /* Write the pCAL chunk (described in the PNG extensions document) */
   1563 void /* PRIVATE */
   1564 png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
   1565    png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
   1566 {
   1567 #ifdef PNG_USE_LOCAL_ARRAYS
   1568    PNG_pCAL;
   1569 #endif
   1570    png_size_t purpose_len, units_len, total_len;
   1571    png_uint_32p params_len;
   1572    png_byte buf[10];
   1573    png_charp new_purpose;
   1574    int i;
   1575 
   1576    png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
   1577 
   1578    if (type >= PNG_EQUATION_LAST)
   1579       png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
   1580 
   1581    purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
   1582    png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
   1583    units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
   1584    png_debug1(3, "pCAL units length = %d", (int)units_len);
   1585    total_len = purpose_len + units_len + 10;
   1586 
   1587    params_len = (png_uint_32p)png_malloc(png_ptr,
   1588       (png_uint_32)(nparams * png_sizeof(png_uint_32)));
   1589 
   1590    /* Find the length of each parameter, making sure we don't count the
   1591       null terminator for the last parameter. */
   1592    for (i = 0; i < nparams; i++)
   1593    {
   1594       params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
   1595       png_debug2(3, "pCAL parameter %d length = %lu", i,
   1596         (unsigned long) params_len[i]);
   1597       total_len += (png_size_t)params_len[i];
   1598    }
   1599 
   1600    png_debug1(3, "pCAL total length = %d", (int)total_len);
   1601    png_write_chunk_start(png_ptr, (png_bytep)png_pCAL, (png_uint_32)total_len);
   1602    png_write_chunk_data(png_ptr, (png_bytep)new_purpose,
   1603      (png_size_t)purpose_len);
   1604    png_save_int_32(buf, X0);
   1605    png_save_int_32(buf + 4, X1);
   1606    buf[8] = (png_byte)type;
   1607    buf[9] = (png_byte)nparams;
   1608    png_write_chunk_data(png_ptr, buf, (png_size_t)10);
   1609    png_write_chunk_data(png_ptr, (png_bytep)units, (png_size_t)units_len);
   1610 
   1611    png_free(png_ptr, new_purpose);
   1612 
   1613    for (i = 0; i < nparams; i++)
   1614    {
   1615       png_write_chunk_data(png_ptr, (png_bytep)params[i],
   1616          (png_size_t)params_len[i]);
   1617    }
   1618 
   1619    png_free(png_ptr, params_len);
   1620    png_write_chunk_end(png_ptr);
   1621 }
   1622 #endif
   1623 
   1624 #ifdef PNG_WRITE_sCAL_SUPPORTED
   1625 /* Write the sCAL chunk */
   1626 #if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
   1627 void /* PRIVATE */
   1628 png_write_sCAL(png_structp png_ptr, int unit, double width, double height)
   1629 {
   1630 #ifdef PNG_USE_LOCAL_ARRAYS
   1631    PNG_sCAL;
   1632 #endif
   1633    char buf[64];
   1634    png_size_t total_len;
   1635 
   1636    png_debug(1, "in png_write_sCAL");
   1637 
   1638    buf[0] = (char)unit;
   1639 #ifdef _WIN32_WCE
   1640 /* sprintf() function is not supported on WindowsCE */
   1641    {
   1642       wchar_t wc_buf[32];
   1643       size_t wc_len;
   1644       swprintf(wc_buf, TEXT("%12.12e"), width);
   1645       wc_len = wcslen(wc_buf);
   1646       WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL,
   1647           NULL);
   1648       total_len = wc_len + 2;
   1649       swprintf(wc_buf, TEXT("%12.12e"), height);
   1650       wc_len = wcslen(wc_buf);
   1651       WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len,
   1652          NULL, NULL);
   1653       total_len += wc_len;
   1654    }
   1655 #else
   1656    png_snprintf(buf + 1, 63, "%12.12e", width);
   1657    total_len = 1 + png_strlen(buf + 1) + 1;
   1658    png_snprintf(buf + total_len, 64-total_len, "%12.12e", height);
   1659    total_len += png_strlen(buf + total_len);
   1660 #endif
   1661 
   1662    png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
   1663    png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len);
   1664 }
   1665 #else
   1666 #ifdef PNG_FIXED_POINT_SUPPORTED
   1667 void /* PRIVATE */
   1668 png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
   1669    png_charp height)
   1670 {
   1671 #ifdef PNG_USE_LOCAL_ARRAYS
   1672    PNG_sCAL;
   1673 #endif
   1674    png_byte buf[64];
   1675    png_size_t wlen, hlen, total_len;
   1676 
   1677    png_debug(1, "in png_write_sCAL_s");
   1678 
   1679    wlen = png_strlen(width);
   1680    hlen = png_strlen(height);
   1681    total_len = wlen + hlen + 2;
   1682    if (total_len > 64)
   1683    {
   1684       png_warning(png_ptr, "Can't write sCAL (buffer too small)");
   1685       return;
   1686    }
   1687 
   1688    buf[0] = (png_byte)unit;
   1689    png_memcpy(buf + 1, width, wlen + 1);      /* Append the '\0' here */
   1690    png_memcpy(buf + wlen + 2, height, hlen);  /* Do NOT append the '\0' here */
   1691 
   1692    png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
   1693    png_write_chunk(png_ptr, (png_bytep)png_sCAL, buf, total_len);
   1694 }
   1695 #endif
   1696 #endif
   1697 #endif
   1698 
   1699 #ifdef PNG_WRITE_pHYs_SUPPORTED
   1700 /* Write the pHYs chunk */
   1701 void /* PRIVATE */
   1702 png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
   1703    png_uint_32 y_pixels_per_unit,
   1704    int unit_type)
   1705 {
   1706 #ifdef PNG_USE_LOCAL_ARRAYS
   1707    PNG_pHYs;
   1708 #endif
   1709    png_byte buf[9];
   1710 
   1711    png_debug(1, "in png_write_pHYs");
   1712 
   1713    if (unit_type >= PNG_RESOLUTION_LAST)
   1714       png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
   1715 
   1716    png_save_uint_32(buf, x_pixels_per_unit);
   1717    png_save_uint_32(buf + 4, y_pixels_per_unit);
   1718    buf[8] = (png_byte)unit_type;
   1719 
   1720    png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9);
   1721 }
   1722 #endif
   1723 
   1724 #ifdef PNG_WRITE_tIME_SUPPORTED
   1725 /* Write the tIME chunk.  Use either png_convert_from_struct_tm()
   1726  * or png_convert_from_time_t(), or fill in the structure yourself.
   1727  */
   1728 void /* PRIVATE */
   1729 png_write_tIME(png_structp png_ptr, png_timep mod_time)
   1730 {
   1731 #ifdef PNG_USE_LOCAL_ARRAYS
   1732    PNG_tIME;
   1733 #endif
   1734    png_byte buf[7];
   1735 
   1736    png_debug(1, "in png_write_tIME");
   1737 
   1738    if (mod_time->month  > 12 || mod_time->month  < 1 ||
   1739        mod_time->day    > 31 || mod_time->day    < 1 ||
   1740        mod_time->hour   > 23 || mod_time->second > 60)
   1741    {
   1742       png_warning(png_ptr, "Invalid time specified for tIME chunk");
   1743       return;
   1744    }
   1745 
   1746    png_save_uint_16(buf, mod_time->year);
   1747    buf[2] = mod_time->month;
   1748    buf[3] = mod_time->day;
   1749    buf[4] = mod_time->hour;
   1750    buf[5] = mod_time->minute;
   1751    buf[6] = mod_time->second;
   1752 
   1753    png_write_chunk(png_ptr, (png_bytep)png_tIME, buf, (png_size_t)7);
   1754 }
   1755 #endif
   1756 
   1757 /* Initializes the row writing capability of libpng */
   1758 void /* PRIVATE */
   1759 png_write_start_row(png_structp png_ptr)
   1760 {
   1761 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
   1762    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
   1763 
   1764    /* Start of interlace block */
   1765    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
   1766 
   1767    /* Offset to next interlace block */
   1768    int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
   1769 
   1770    /* Start of interlace block in the y direction */
   1771    int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
   1772 
   1773    /* Offset to next interlace block in the y direction */
   1774    int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
   1775 #endif
   1776 
   1777    png_size_t buf_size;
   1778 
   1779    png_debug(1, "in png_write_start_row");
   1780 
   1781    buf_size = (png_size_t)(PNG_ROWBYTES(
   1782       png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1);
   1783 
   1784    /* Set up row buffer */
   1785    png_ptr->row_buf = (png_bytep)png_malloc(png_ptr,
   1786      (png_uint_32)buf_size);
   1787    png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
   1788 
   1789 #ifdef PNG_WRITE_FILTER_SUPPORTED
   1790    /* Set up filtering buffer, if using this filter */
   1791    if (png_ptr->do_filter & PNG_FILTER_SUB)
   1792    {
   1793       png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
   1794          (png_uint_32)(png_ptr->rowbytes + 1));
   1795       png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
   1796    }
   1797 
   1798    /* We only need to keep the previous row if we are using one of these. */
   1799    if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
   1800    {
   1801       /* Set up previous row buffer */
   1802       png_ptr->prev_row = (png_bytep)png_calloc(png_ptr,
   1803          (png_uint_32)buf_size);
   1804 
   1805       if (png_ptr->do_filter & PNG_FILTER_UP)
   1806       {
   1807          png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
   1808             (png_uint_32)(png_ptr->rowbytes + 1));
   1809          png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
   1810       }
   1811 
   1812       if (png_ptr->do_filter & PNG_FILTER_AVG)
   1813       {
   1814          png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
   1815             (png_uint_32)(png_ptr->rowbytes + 1));
   1816          png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
   1817       }
   1818 
   1819       if (png_ptr->do_filter & PNG_FILTER_PAETH)
   1820       {
   1821          png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
   1822             (png_uint_32)(png_ptr->rowbytes + 1));
   1823          png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
   1824       }
   1825    }
   1826 #endif /* PNG_WRITE_FILTER_SUPPORTED */
   1827 
   1828 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
   1829    /* If interlaced, we need to set up width and height of pass */
   1830    if (png_ptr->interlaced)
   1831    {
   1832       if (!(png_ptr->transformations & PNG_INTERLACE))
   1833       {
   1834          png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
   1835             png_pass_ystart[0]) / png_pass_yinc[0];
   1836          png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
   1837             png_pass_start[0]) / png_pass_inc[0];
   1838       }
   1839       else
   1840       {
   1841          png_ptr->num_rows = png_ptr->height;
   1842          png_ptr->usr_width = png_ptr->width;
   1843       }
   1844    }
   1845    else
   1846 #endif
   1847    {
   1848       png_ptr->num_rows = png_ptr->height;
   1849       png_ptr->usr_width = png_ptr->width;
   1850    }
   1851    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
   1852    png_ptr->zstream.next_out = png_ptr->zbuf;
   1853 }
   1854 
   1855 /* Internal use only.  Called when finished processing a row of data. */
   1856 void /* PRIVATE */
   1857 png_write_finish_row(png_structp png_ptr)
   1858 {
   1859 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
   1860    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
   1861 
   1862    /* Start of interlace block */
   1863    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
   1864 
   1865    /* Offset to next interlace block */
   1866    int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
   1867 
   1868    /* Start of interlace block in the y direction */
   1869    int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
   1870 
   1871    /* Offset to next interlace block in the y direction */
   1872    int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
   1873 #endif
   1874 
   1875    int ret;
   1876 
   1877    png_debug(1, "in png_write_finish_row");
   1878 
   1879    /* Next row */
   1880    png_ptr->row_number++;
   1881 
   1882    /* See if we are done */
   1883    if (png_ptr->row_number < png_ptr->num_rows)
   1884       return;
   1885 
   1886 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
   1887    /* If interlaced, go to next pass */
   1888    if (png_ptr->interlaced)
   1889    {
   1890       png_ptr->row_number = 0;
   1891       if (png_ptr->transformations & PNG_INTERLACE)
   1892       {
   1893          png_ptr->pass++;
   1894       }
   1895       else
   1896       {
   1897          /* Loop until we find a non-zero width or height pass */
   1898          do
   1899          {
   1900             png_ptr->pass++;
   1901             if (png_ptr->pass >= 7)
   1902                break;
   1903             png_ptr->usr_width = (png_ptr->width +
   1904                png_pass_inc[png_ptr->pass] - 1 -
   1905                png_pass_start[png_ptr->pass]) /
   1906                png_pass_inc[png_ptr->pass];
   1907             png_ptr->num_rows = (png_ptr->height +
   1908                png_pass_yinc[png_ptr->pass] - 1 -
   1909                png_pass_ystart[png_ptr->pass]) /
   1910                png_pass_yinc[png_ptr->pass];
   1911             if (png_ptr->transformations & PNG_INTERLACE)
   1912                break;
   1913          } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
   1914 
   1915       }
   1916 
   1917       /* Reset the row above the image for the next pass */
   1918       if (png_ptr->pass < 7)
   1919       {
   1920          if (png_ptr->prev_row != NULL)
   1921             png_memset(png_ptr->prev_row, 0,
   1922                (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
   1923                png_ptr->usr_bit_depth, png_ptr->width)) + 1);
   1924          return;
   1925       }
   1926    }
   1927 #endif
   1928 
   1929    /* If we get here, we've just written the last row, so we need
   1930       to flush the compressor */
   1931    do
   1932    {
   1933       /* Tell the compressor we are done */
   1934       ret = deflate(&png_ptr->zstream, Z_FINISH);
   1935       /* Check for an error */
   1936       if (ret == Z_OK)
   1937       {
   1938          /* Check to see if we need more room */
   1939          if (!(png_ptr->zstream.avail_out))
   1940          {
   1941             png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
   1942             png_ptr->zstream.next_out = png_ptr->zbuf;
   1943             png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
   1944          }
   1945       }
   1946       else if (ret != Z_STREAM_END)
   1947       {
   1948          if (png_ptr->zstream.msg != NULL)
   1949             png_error(png_ptr, png_ptr->zstream.msg);
   1950          else
   1951             png_error(png_ptr, "zlib error");
   1952       }
   1953    } while (ret != Z_STREAM_END);
   1954 
   1955    /* Write any extra space */
   1956    if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
   1957    {
   1958       png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
   1959          png_ptr->zstream.avail_out);
   1960    }
   1961 
   1962    deflateReset(&png_ptr->zstream);
   1963    png_ptr->zstream.data_type = Z_BINARY;
   1964 }
   1965 
   1966 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
   1967 /* Pick out the correct pixels for the interlace pass.
   1968  * The basic idea here is to go through the row with a source
   1969  * pointer and a destination pointer (sp and dp), and copy the
   1970  * correct pixels for the pass.  As the row gets compacted,
   1971  * sp will always be >= dp, so we should never overwrite anything.
   1972  * See the default: case for the easiest code to understand.
   1973  */
   1974 void /* PRIVATE */
   1975 png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
   1976 {
   1977    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
   1978 
   1979    /* Start of interlace block */
   1980    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
   1981 
   1982    /* Offset to next interlace block */
   1983    int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
   1984 
   1985    png_debug(1, "in png_do_write_interlace");
   1986 
   1987    /* We don't have to do anything on the last pass (6) */
   1988 #ifdef PNG_USELESS_TESTS_SUPPORTED
   1989    if (row != NULL && row_info != NULL && pass < 6)
   1990 #else
   1991    if (pass < 6)
   1992 #endif
   1993    {
   1994       /* Each pixel depth is handled separately */
   1995       switch (row_info->pixel_depth)
   1996       {
   1997          case 1:
   1998          {
   1999             png_bytep sp;
   2000             png_bytep dp;
   2001             int shift;
   2002             int d;
   2003             int value;
   2004             png_uint_32 i;
   2005             png_uint_32 row_width = row_info->width;
   2006 
   2007             dp = row;
   2008             d = 0;
   2009             shift = 7;
   2010             for (i = png_pass_start[pass]; i < row_width;
   2011                i += png_pass_inc[pass])
   2012             {
   2013                sp = row + (png_size_t)(i >> 3);
   2014                value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
   2015                d |= (value << shift);
   2016 
   2017                if (shift == 0)
   2018                {
   2019                   shift = 7;
   2020                   *dp++ = (png_byte)d;
   2021                   d = 0;
   2022                }
   2023                else
   2024                   shift--;
   2025 
   2026             }
   2027             if (shift != 7)
   2028                *dp = (png_byte)d;
   2029             break;
   2030          }
   2031          case 2:
   2032          {
   2033             png_bytep sp;
   2034             png_bytep dp;
   2035             int shift;
   2036             int d;
   2037             int value;
   2038             png_uint_32 i;
   2039             png_uint_32 row_width = row_info->width;
   2040 
   2041             dp = row;
   2042             shift = 6;
   2043             d = 0;
   2044             for (i = png_pass_start[pass]; i < row_width;
   2045                i += png_pass_inc[pass])
   2046             {
   2047                sp = row + (png_size_t)(i >> 2);
   2048                value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
   2049                d |= (value << shift);
   2050 
   2051                if (shift == 0)
   2052                {
   2053                   shift = 6;
   2054                   *dp++ = (png_byte)d;
   2055                   d = 0;
   2056                }
   2057                else
   2058                   shift -= 2;
   2059             }
   2060             if (shift != 6)
   2061                    *dp = (png_byte)d;
   2062             break;
   2063          }
   2064          case 4:
   2065          {
   2066             png_bytep sp;
   2067             png_bytep dp;
   2068             int shift;
   2069             int d;
   2070             int value;
   2071             png_uint_32 i;
   2072             png_uint_32 row_width = row_info->width;
   2073 
   2074             dp = row;
   2075             shift = 4;
   2076             d = 0;
   2077             for (i = png_pass_start[pass]; i < row_width;
   2078                i += png_pass_inc[pass])
   2079             {
   2080                sp = row + (png_size_t)(i >> 1);
   2081                value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
   2082                d |= (value << shift);
   2083 
   2084                if (shift == 0)
   2085                {
   2086                   shift = 4;
   2087                   *dp++ = (png_byte)d;
   2088                   d = 0;
   2089                }
   2090                else
   2091                   shift -= 4;
   2092             }
   2093             if (shift != 4)
   2094                *dp = (png_byte)d;
   2095             break;
   2096          }
   2097          default:
   2098          {
   2099             png_bytep sp;
   2100             png_bytep dp;
   2101             png_uint_32 i;
   2102             png_uint_32 row_width = row_info->width;
   2103             png_size_t pixel_bytes;
   2104 
   2105             /* Start at the beginning */
   2106             dp = row;
   2107             /* Find out how many bytes each pixel takes up */
   2108             pixel_bytes = (row_info->pixel_depth >> 3);
   2109             /* Loop through the row, only looking at the pixels that
   2110                matter */
   2111             for (i = png_pass_start[pass]; i < row_width;
   2112                i += png_pass_inc[pass])
   2113             {
   2114                /* Find out where the original pixel is */
   2115                sp = row + (png_size_t)i * pixel_bytes;
   2116                /* Move the pixel */
   2117                if (dp != sp)
   2118                   png_memcpy(dp, sp, pixel_bytes);
   2119                /* Next pixel */
   2120                dp += pixel_bytes;
   2121             }
   2122             break;
   2123          }
   2124       }
   2125       /* Set new row width */
   2126       row_info->width = (row_info->width +
   2127          png_pass_inc[pass] - 1 -
   2128          png_pass_start[pass]) /
   2129          png_pass_inc[pass];
   2130          row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
   2131             row_info->width);
   2132    }
   2133 }
   2134 #endif
   2135 
   2136 /* This filters the row, chooses which filter to use, if it has not already
   2137  * been specified by the application, and then writes the row out with the
   2138  * chosen filter.
   2139  */
   2140 #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
   2141 #define PNG_HISHIFT 10
   2142 #define PNG_LOMASK ((png_uint_32)0xffffL)
   2143 #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
   2144 void /* PRIVATE */
   2145 png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
   2146 {
   2147    png_bytep best_row;
   2148 #ifdef PNG_WRITE_FILTER_SUPPORTED
   2149    png_bytep prev_row, row_buf;
   2150    png_uint_32 mins, bpp;
   2151    png_byte filter_to_do = png_ptr->do_filter;
   2152    png_uint_32 row_bytes = row_info->rowbytes;
   2153 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2154    int num_p_filters = (int)png_ptr->num_prev_filters;
   2155 #endif
   2156 
   2157    png_debug(1, "in png_write_find_filter");
   2158 
   2159 #ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2160   if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
   2161   {
   2162       /* These will never be selected so we need not test them. */
   2163       filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
   2164   }
   2165 #endif
   2166 
   2167    /* Find out how many bytes offset each pixel is */
   2168    bpp = (row_info->pixel_depth + 7) >> 3;
   2169 
   2170    prev_row = png_ptr->prev_row;
   2171 #endif
   2172    best_row = png_ptr->row_buf;
   2173 #ifdef PNG_WRITE_FILTER_SUPPORTED
   2174    row_buf = best_row;
   2175    mins = PNG_MAXSUM;
   2176 
   2177    /* The prediction method we use is to find which method provides the
   2178     * smallest value when summing the absolute values of the distances
   2179     * from zero, using anything >= 128 as negative numbers.  This is known
   2180     * as the "minimum sum of absolute differences" heuristic.  Other
   2181     * heuristics are the "weighted minimum sum of absolute differences"
   2182     * (experimental and can in theory improve compression), and the "zlib
   2183     * predictive" method (not implemented yet), which does test compressions
   2184     * of lines using different filter methods, and then chooses the
   2185     * (series of) filter(s) that give minimum compressed data size (VERY
   2186     * computationally expensive).
   2187     *
   2188     * GRR 980525:  consider also
   2189     *   (1) minimum sum of absolute differences from running average (i.e.,
   2190     *       keep running sum of non-absolute differences & count of bytes)
   2191     *       [track dispersion, too?  restart average if dispersion too large?]
   2192     *  (1b) minimum sum of absolute differences from sliding average, probably
   2193     *       with window size <= deflate window (usually 32K)
   2194     *   (2) minimum sum of squared differences from zero or running average
   2195     *       (i.e., ~ root-mean-square approach)
   2196     */
   2197 
   2198 
   2199    /* We don't need to test the 'no filter' case if this is the only filter
   2200     * that has been chosen, as it doesn't actually do anything to the data.
   2201     */
   2202    if ((filter_to_do & PNG_FILTER_NONE) &&
   2203        filter_to_do != PNG_FILTER_NONE)
   2204    {
   2205       png_bytep rp;
   2206       png_uint_32 sum = 0;
   2207       png_uint_32 i;
   2208       int v;
   2209 
   2210       for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
   2211       {
   2212          v = *rp;
   2213          sum += (v < 128) ? v : 256 - v;
   2214       }
   2215 
   2216 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2217       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   2218       {
   2219          png_uint_32 sumhi, sumlo;
   2220          int j;
   2221          sumlo = sum & PNG_LOMASK;
   2222          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
   2223 
   2224          /* Reduce the sum if we match any of the previous rows */
   2225          for (j = 0; j < num_p_filters; j++)
   2226          {
   2227             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
   2228             {
   2229                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
   2230                   PNG_WEIGHT_SHIFT;
   2231                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
   2232                   PNG_WEIGHT_SHIFT;
   2233             }
   2234          }
   2235 
   2236          /* Factor in the cost of this filter (this is here for completeness,
   2237           * but it makes no sense to have a "cost" for the NONE filter, as
   2238           * it has the minimum possible computational cost - none).
   2239           */
   2240          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
   2241             PNG_COST_SHIFT;
   2242          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
   2243             PNG_COST_SHIFT;
   2244 
   2245          if (sumhi > PNG_HIMASK)
   2246             sum = PNG_MAXSUM;
   2247          else
   2248             sum = (sumhi << PNG_HISHIFT) + sumlo;
   2249       }
   2250 #endif
   2251       mins = sum;
   2252    }
   2253 
   2254    /* Sub filter */
   2255    if (filter_to_do == PNG_FILTER_SUB)
   2256    /* It's the only filter so no testing is needed */
   2257    {
   2258       png_bytep rp, lp, dp;
   2259       png_uint_32 i;
   2260       for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
   2261            i++, rp++, dp++)
   2262       {
   2263          *dp = *rp;
   2264       }
   2265       for (lp = row_buf + 1; i < row_bytes;
   2266          i++, rp++, lp++, dp++)
   2267       {
   2268          *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
   2269       }
   2270       best_row = png_ptr->sub_row;
   2271    }
   2272 
   2273    else if (filter_to_do & PNG_FILTER_SUB)
   2274    {
   2275       png_bytep rp, dp, lp;
   2276       png_uint_32 sum = 0, lmins = mins;
   2277       png_uint_32 i;
   2278       int v;
   2279 
   2280 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2281       /* We temporarily increase the "minimum sum" by the factor we
   2282        * would reduce the sum of this filter, so that we can do the
   2283        * early exit comparison without scaling the sum each time.
   2284        */
   2285       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   2286       {
   2287          int j;
   2288          png_uint_32 lmhi, lmlo;
   2289          lmlo = lmins & PNG_LOMASK;
   2290          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
   2291 
   2292          for (j = 0; j < num_p_filters; j++)
   2293          {
   2294             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
   2295             {
   2296                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
   2297                   PNG_WEIGHT_SHIFT;
   2298                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
   2299                   PNG_WEIGHT_SHIFT;
   2300             }
   2301          }
   2302 
   2303          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
   2304             PNG_COST_SHIFT;
   2305          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
   2306             PNG_COST_SHIFT;
   2307 
   2308          if (lmhi > PNG_HIMASK)
   2309             lmins = PNG_MAXSUM;
   2310          else
   2311             lmins = (lmhi << PNG_HISHIFT) + lmlo;
   2312       }
   2313 #endif
   2314 
   2315       for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
   2316            i++, rp++, dp++)
   2317       {
   2318          v = *dp = *rp;
   2319 
   2320          sum += (v < 128) ? v : 256 - v;
   2321       }
   2322       for (lp = row_buf + 1; i < row_bytes;
   2323          i++, rp++, lp++, dp++)
   2324       {
   2325          v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
   2326 
   2327          sum += (v < 128) ? v : 256 - v;
   2328 
   2329          if (sum > lmins)  /* We are already worse, don't continue. */
   2330             break;
   2331       }
   2332 
   2333 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2334       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   2335       {
   2336          int j;
   2337          png_uint_32 sumhi, sumlo;
   2338          sumlo = sum & PNG_LOMASK;
   2339          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
   2340 
   2341          for (j = 0; j < num_p_filters; j++)
   2342          {
   2343             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
   2344             {
   2345                sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
   2346                   PNG_WEIGHT_SHIFT;
   2347                sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
   2348                   PNG_WEIGHT_SHIFT;
   2349             }
   2350          }
   2351 
   2352          sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
   2353             PNG_COST_SHIFT;
   2354          sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
   2355             PNG_COST_SHIFT;
   2356 
   2357          if (sumhi > PNG_HIMASK)
   2358             sum = PNG_MAXSUM;
   2359          else
   2360             sum = (sumhi << PNG_HISHIFT) + sumlo;
   2361       }
   2362 #endif
   2363 
   2364       if (sum < mins)
   2365       {
   2366          mins = sum;
   2367          best_row = png_ptr->sub_row;
   2368       }
   2369    }
   2370 
   2371    /* Up filter */
   2372    if (filter_to_do == PNG_FILTER_UP)
   2373    {
   2374       png_bytep rp, dp, pp;
   2375       png_uint_32 i;
   2376 
   2377       for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
   2378            pp = prev_row + 1; i < row_bytes;
   2379            i++, rp++, pp++, dp++)
   2380       {
   2381          *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
   2382       }
   2383       best_row = png_ptr->up_row;
   2384    }
   2385 
   2386    else if (filter_to_do & PNG_FILTER_UP)
   2387    {
   2388       png_bytep rp, dp, pp;
   2389       png_uint_32 sum = 0, lmins = mins;
   2390       png_uint_32 i;
   2391       int v;
   2392 
   2393 
   2394 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2395       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   2396       {
   2397          int j;
   2398          png_uint_32 lmhi, lmlo;
   2399          lmlo = lmins & PNG_LOMASK;
   2400          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
   2401 
   2402          for (j = 0; j < num_p_filters; j++)
   2403          {
   2404             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
   2405             {
   2406                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
   2407                   PNG_WEIGHT_SHIFT;
   2408                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
   2409                   PNG_WEIGHT_SHIFT;
   2410             }
   2411          }
   2412 
   2413          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
   2414             PNG_COST_SHIFT;
   2415          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
   2416             PNG_COST_SHIFT;
   2417 
   2418          if (lmhi > PNG_HIMASK)
   2419             lmins = PNG_MAXSUM;
   2420          else
   2421             lmins = (lmhi << PNG_HISHIFT) + lmlo;
   2422       }
   2423 #endif
   2424 
   2425       for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
   2426            pp = prev_row + 1; i < row_bytes; i++)
   2427       {
   2428          v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
   2429 
   2430          sum += (v < 128) ? v : 256 - v;
   2431 
   2432          if (sum > lmins)  /* We are already worse, don't continue. */
   2433             break;
   2434       }
   2435 
   2436 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2437       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   2438       {
   2439          int j;
   2440          png_uint_32 sumhi, sumlo;
   2441          sumlo = sum & PNG_LOMASK;
   2442          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
   2443 
   2444          for (j = 0; j < num_p_filters; j++)
   2445          {
   2446             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
   2447             {
   2448                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
   2449                   PNG_WEIGHT_SHIFT;
   2450                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
   2451                   PNG_WEIGHT_SHIFT;
   2452             }
   2453          }
   2454 
   2455          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
   2456             PNG_COST_SHIFT;
   2457          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
   2458             PNG_COST_SHIFT;
   2459 
   2460          if (sumhi > PNG_HIMASK)
   2461             sum = PNG_MAXSUM;
   2462          else
   2463             sum = (sumhi << PNG_HISHIFT) + sumlo;
   2464       }
   2465 #endif
   2466 
   2467       if (sum < mins)
   2468       {
   2469          mins = sum;
   2470          best_row = png_ptr->up_row;
   2471       }
   2472    }
   2473 
   2474    /* Avg filter */
   2475    if (filter_to_do == PNG_FILTER_AVG)
   2476    {
   2477       png_bytep rp, dp, pp, lp;
   2478       png_uint_32 i;
   2479       for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
   2480            pp = prev_row + 1; i < bpp; i++)
   2481       {
   2482          *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
   2483       }
   2484       for (lp = row_buf + 1; i < row_bytes; i++)
   2485       {
   2486          *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
   2487                  & 0xff);
   2488       }
   2489       best_row = png_ptr->avg_row;
   2490    }
   2491 
   2492    else if (filter_to_do & PNG_FILTER_AVG)
   2493    {
   2494       png_bytep rp, dp, pp, lp;
   2495       png_uint_32 sum = 0, lmins = mins;
   2496       png_uint_32 i;
   2497       int v;
   2498 
   2499 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2500       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   2501       {
   2502          int j;
   2503          png_uint_32 lmhi, lmlo;
   2504          lmlo = lmins & PNG_LOMASK;
   2505          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
   2506 
   2507          for (j = 0; j < num_p_filters; j++)
   2508          {
   2509             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
   2510             {
   2511                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
   2512                   PNG_WEIGHT_SHIFT;
   2513                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
   2514                   PNG_WEIGHT_SHIFT;
   2515             }
   2516          }
   2517 
   2518          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
   2519             PNG_COST_SHIFT;
   2520          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
   2521             PNG_COST_SHIFT;
   2522 
   2523          if (lmhi > PNG_HIMASK)
   2524             lmins = PNG_MAXSUM;
   2525          else
   2526             lmins = (lmhi << PNG_HISHIFT) + lmlo;
   2527       }
   2528 #endif
   2529 
   2530       for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
   2531            pp = prev_row + 1; i < bpp; i++)
   2532       {
   2533          v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
   2534 
   2535          sum += (v < 128) ? v : 256 - v;
   2536       }
   2537       for (lp = row_buf + 1; i < row_bytes; i++)
   2538       {
   2539          v = *dp++ =
   2540           (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
   2541 
   2542          sum += (v < 128) ? v : 256 - v;
   2543 
   2544          if (sum > lmins)  /* We are already worse, don't continue. */
   2545             break;
   2546       }
   2547 
   2548 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2549       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   2550       {
   2551          int j;
   2552          png_uint_32 sumhi, sumlo;
   2553          sumlo = sum & PNG_LOMASK;
   2554          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
   2555 
   2556          for (j = 0; j < num_p_filters; j++)
   2557          {
   2558             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
   2559             {
   2560                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
   2561                   PNG_WEIGHT_SHIFT;
   2562                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
   2563                   PNG_WEIGHT_SHIFT;
   2564             }
   2565          }
   2566 
   2567          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
   2568             PNG_COST_SHIFT;
   2569          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
   2570             PNG_COST_SHIFT;
   2571 
   2572          if (sumhi > PNG_HIMASK)
   2573             sum = PNG_MAXSUM;
   2574          else
   2575             sum = (sumhi << PNG_HISHIFT) + sumlo;
   2576       }
   2577 #endif
   2578 
   2579       if (sum < mins)
   2580       {
   2581          mins = sum;
   2582          best_row = png_ptr->avg_row;
   2583       }
   2584    }
   2585 
   2586    /* Paeth filter */
   2587    if (filter_to_do == PNG_FILTER_PAETH)
   2588    {
   2589       png_bytep rp, dp, pp, cp, lp;
   2590       png_uint_32 i;
   2591       for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
   2592            pp = prev_row + 1; i < bpp; i++)
   2593       {
   2594          *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
   2595       }
   2596 
   2597       for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
   2598       {
   2599          int a, b, c, pa, pb, pc, p;
   2600 
   2601          b = *pp++;
   2602          c = *cp++;
   2603          a = *lp++;
   2604 
   2605          p = b - c;
   2606          pc = a - c;
   2607 
   2608 #ifdef PNG_USE_ABS
   2609          pa = abs(p);
   2610          pb = abs(pc);
   2611          pc = abs(p + pc);
   2612 #else
   2613          pa = p < 0 ? -p : p;
   2614          pb = pc < 0 ? -pc : pc;
   2615          pc = (p + pc) < 0 ? -(p + pc) : p + pc;
   2616 #endif
   2617 
   2618          p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
   2619 
   2620          *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
   2621       }
   2622       best_row = png_ptr->paeth_row;
   2623    }
   2624 
   2625    else if (filter_to_do & PNG_FILTER_PAETH)
   2626    {
   2627       png_bytep rp, dp, pp, cp, lp;
   2628       png_uint_32 sum = 0, lmins = mins;
   2629       png_uint_32 i;
   2630       int v;
   2631 
   2632 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2633       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   2634       {
   2635          int j;
   2636          png_uint_32 lmhi, lmlo;
   2637          lmlo = lmins & PNG_LOMASK;
   2638          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
   2639 
   2640          for (j = 0; j < num_p_filters; j++)
   2641          {
   2642             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
   2643             {
   2644                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
   2645                   PNG_WEIGHT_SHIFT;
   2646                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
   2647                   PNG_WEIGHT_SHIFT;
   2648             }
   2649          }
   2650 
   2651          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
   2652             PNG_COST_SHIFT;
   2653          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
   2654             PNG_COST_SHIFT;
   2655 
   2656          if (lmhi > PNG_HIMASK)
   2657             lmins = PNG_MAXSUM;
   2658          else
   2659             lmins = (lmhi << PNG_HISHIFT) + lmlo;
   2660       }
   2661 #endif
   2662 
   2663       for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
   2664            pp = prev_row + 1; i < bpp; i++)
   2665       {
   2666          v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
   2667 
   2668          sum += (v < 128) ? v : 256 - v;
   2669       }
   2670 
   2671       for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
   2672       {
   2673          int a, b, c, pa, pb, pc, p;
   2674 
   2675          b = *pp++;
   2676          c = *cp++;
   2677          a = *lp++;
   2678 
   2679 #ifndef PNG_SLOW_PAETH
   2680          p = b - c;
   2681          pc = a - c;
   2682 #ifdef PNG_USE_ABS
   2683          pa = abs(p);
   2684          pb = abs(pc);
   2685          pc = abs(p + pc);
   2686 #else
   2687          pa = p < 0 ? -p : p;
   2688          pb = pc < 0 ? -pc : pc;
   2689          pc = (p + pc) < 0 ? -(p + pc) : p + pc;
   2690 #endif
   2691          p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
   2692 #else /* PNG_SLOW_PAETH */
   2693          p = a + b - c;
   2694          pa = abs(p - a);
   2695          pb = abs(p - b);
   2696          pc = abs(p - c);
   2697          if (pa <= pb && pa <= pc)
   2698             p = a;
   2699          else if (pb <= pc)
   2700             p = b;
   2701          else
   2702             p = c;
   2703 #endif /* PNG_SLOW_PAETH */
   2704 
   2705          v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
   2706 
   2707          sum += (v < 128) ? v : 256 - v;
   2708 
   2709          if (sum > lmins)  /* We are already worse, don't continue. */
   2710             break;
   2711       }
   2712 
   2713 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2714       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
   2715       {
   2716          int j;
   2717          png_uint_32 sumhi, sumlo;
   2718          sumlo = sum & PNG_LOMASK;
   2719          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
   2720 
   2721          for (j = 0; j < num_p_filters; j++)
   2722          {
   2723             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
   2724             {
   2725                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
   2726                   PNG_WEIGHT_SHIFT;
   2727                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
   2728                   PNG_WEIGHT_SHIFT;
   2729             }
   2730          }
   2731 
   2732          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
   2733             PNG_COST_SHIFT;
   2734          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
   2735             PNG_COST_SHIFT;
   2736 
   2737          if (sumhi > PNG_HIMASK)
   2738             sum = PNG_MAXSUM;
   2739          else
   2740             sum = (sumhi << PNG_HISHIFT) + sumlo;
   2741       }
   2742 #endif
   2743 
   2744       if (sum < mins)
   2745       {
   2746          best_row = png_ptr->paeth_row;
   2747       }
   2748    }
   2749 #endif /* PNG_WRITE_FILTER_SUPPORTED */
   2750    /* Do the actual writing of the filtered row data from the chosen filter. */
   2751 
   2752    png_write_filtered_row(png_ptr, best_row);
   2753 
   2754 #ifdef PNG_WRITE_FILTER_SUPPORTED
   2755 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
   2756    /* Save the type of filter we picked this time for future calculations */
   2757    if (png_ptr->num_prev_filters > 0)
   2758    {
   2759       int j;
   2760       for (j = 1; j < num_p_filters; j++)
   2761       {
   2762          png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
   2763       }
   2764       png_ptr->prev_filters[j] = best_row[0];
   2765    }
   2766 #endif
   2767 #endif /* PNG_WRITE_FILTER_SUPPORTED */
   2768 }
   2769 
   2770 
   2771 /* Do the actual writing of a previously filtered row. */
   2772 void /* PRIVATE */
   2773 png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row)
   2774 {
   2775    png_debug(1, "in png_write_filtered_row");
   2776 
   2777    png_debug1(2, "filter = %d", filtered_row[0]);
   2778    /* Set up the zlib input buffer */
   2779 
   2780    png_ptr->zstream.next_in = filtered_row;
   2781    png_ptr->zstream.avail_in = (uInt)png_ptr->row_info.rowbytes + 1;
   2782    /* Repeat until we have compressed all the data */
   2783    do
   2784    {
   2785       int ret; /* Return of zlib */
   2786 
   2787       /* Compress the data */
   2788       ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
   2789       /* Check for compression errors */
   2790       if (ret != Z_OK)
   2791       {
   2792          if (png_ptr->zstream.msg != NULL)
   2793             png_error(png_ptr, png_ptr->zstream.msg);
   2794          else
   2795             png_error(png_ptr, "zlib error");
   2796       }
   2797 
   2798       /* See if it is time to write another IDAT */
   2799       if (!(png_ptr->zstream.avail_out))
   2800       {
   2801          /* Write the IDAT and reset the zlib output buffer */
   2802          png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
   2803          png_ptr->zstream.next_out = png_ptr->zbuf;
   2804          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
   2805       }
   2806    /* Repeat until all data has been compressed */
   2807    } while (png_ptr->zstream.avail_in);
   2808 
   2809    /* Swap the current and previous rows */
   2810    if (png_ptr->prev_row != NULL)
   2811    {
   2812       png_bytep tptr;
   2813 
   2814       tptr = png_ptr->prev_row;
   2815       png_ptr->prev_row = png_ptr->row_buf;
   2816       png_ptr->row_buf = tptr;
   2817    }
   2818 
   2819    /* Finish row - updates counters and flushes zlib if last row */
   2820    png_write_finish_row(png_ptr);
   2821 
   2822 #ifdef PNG_WRITE_FLUSH_SUPPORTED
   2823    png_ptr->flush_rows++;
   2824 
   2825    if (png_ptr->flush_dist > 0 &&
   2826        png_ptr->flush_rows >= png_ptr->flush_dist)
   2827    {
   2828       png_write_flush(png_ptr);
   2829    }
   2830 #endif
   2831 }
   2832 #endif /* PNG_WRITE_SUPPORTED */
   2833