LCOV - code coverage report
Current view: top level - media/libpng - pngwutil.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 386 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 27 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13