LCOV - code coverage report
Current view: directory - media/libpng - pngwutil.c (source / functions) Found Hit Coverage
Test: app.info Lines: 356 241 67.7 %
Date: 2012-06-02 Functions: 24 20 83.3 %

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

Generated by: LCOV version 1.7