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