media/libpng/pngwutil.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/media/libpng/pngwutil.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,3156 @@
     1.4 +
     1.5 +/* pngwutil.c - utilities to write a PNG file
     1.6 + *
     1.7 + * Last changed in libpng 1.6.2 [April 25, 2013]
     1.8 + * Copyright (c) 1998-2013 Glenn Randers-Pehrson
     1.9 + * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
    1.10 + * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
    1.11 + *
    1.12 + * This code is released under the libpng license.
    1.13 + * For conditions of distribution and use, see the disclaimer
    1.14 + * and license in png.h
    1.15 + */
    1.16 +
    1.17 +#include "pngpriv.h"
    1.18 +
    1.19 +#ifdef PNG_WRITE_SUPPORTED
    1.20 +
    1.21 +#ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
    1.22 +/* Place a 32-bit number into a buffer in PNG byte order.  We work
    1.23 + * with unsigned numbers for convenience, although one supported
    1.24 + * ancillary chunk uses signed (two's complement) numbers.
    1.25 + */
    1.26 +void PNGAPI
    1.27 +png_save_uint_32(png_bytep buf, png_uint_32 i)
    1.28 +{
    1.29 +   buf[0] = (png_byte)((i >> 24) & 0xff);
    1.30 +   buf[1] = (png_byte)((i >> 16) & 0xff);
    1.31 +   buf[2] = (png_byte)((i >> 8) & 0xff);
    1.32 +   buf[3] = (png_byte)(i & 0xff);
    1.33 +}
    1.34 +
    1.35 +/* Place a 16-bit number into a buffer in PNG byte order.
    1.36 + * The parameter is declared unsigned int, not png_uint_16,
    1.37 + * just to avoid potential problems on pre-ANSI C compilers.
    1.38 + */
    1.39 +void PNGAPI
    1.40 +png_save_uint_16(png_bytep buf, unsigned int i)
    1.41 +{
    1.42 +   buf[0] = (png_byte)((i >> 8) & 0xff);
    1.43 +   buf[1] = (png_byte)(i & 0xff);
    1.44 +}
    1.45 +#endif
    1.46 +
    1.47 +/* Simple function to write the signature.  If we have already written
    1.48 + * the magic bytes of the signature, or more likely, the PNG stream is
    1.49 + * being embedded into another stream and doesn't need its own signature,
    1.50 + * we should call png_set_sig_bytes() to tell libpng how many of the
    1.51 + * bytes have already been written.
    1.52 + */
    1.53 +void PNGAPI
    1.54 +png_write_sig(png_structrp png_ptr)
    1.55 +{
    1.56 +   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
    1.57 +
    1.58 +#ifdef PNG_IO_STATE_SUPPORTED
    1.59 +   /* Inform the I/O callback that the signature is being written */
    1.60 +   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE;
    1.61 +#endif
    1.62 +
    1.63 +   /* Write the rest of the 8 byte signature */
    1.64 +   png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
    1.65 +      (png_size_t)(8 - png_ptr->sig_bytes));
    1.66 +
    1.67 +   if (png_ptr->sig_bytes < 3)
    1.68 +      png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
    1.69 +}
    1.70 +
    1.71 +/* Write the start of a PNG chunk.  The type is the chunk type.
    1.72 + * The total_length is the sum of the lengths of all the data you will be
    1.73 + * passing in png_write_chunk_data().
    1.74 + */
    1.75 +static void
    1.76 +png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name,
    1.77 +    png_uint_32 length)
    1.78 +{
    1.79 +   png_byte buf[8];
    1.80 +
    1.81 +#if defined(PNG_DEBUG) && (PNG_DEBUG > 0)
    1.82 +   PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
    1.83 +   png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
    1.84 +#endif
    1.85 +
    1.86 +   if (png_ptr == NULL)
    1.87 +      return;
    1.88 +
    1.89 +#ifdef PNG_IO_STATE_SUPPORTED
    1.90 +   /* Inform the I/O callback that the chunk header is being written.
    1.91 +    * PNG_IO_CHUNK_HDR requires a single I/O call.
    1.92 +    */
    1.93 +   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR;
    1.94 +#endif
    1.95 +
    1.96 +   /* Write the length and the chunk name */
    1.97 +   png_save_uint_32(buf, length);
    1.98 +   png_save_uint_32(buf + 4, chunk_name);
    1.99 +   png_write_data(png_ptr, buf, 8);
   1.100 +
   1.101 +   /* Put the chunk name into png_ptr->chunk_name */
   1.102 +   png_ptr->chunk_name = chunk_name;
   1.103 +
   1.104 +   /* Reset the crc and run it over the chunk name */
   1.105 +   png_reset_crc(png_ptr);
   1.106 +
   1.107 +   png_calculate_crc(png_ptr, buf + 4, 4);
   1.108 +
   1.109 +#ifdef PNG_IO_STATE_SUPPORTED
   1.110 +   /* Inform the I/O callback that chunk data will (possibly) be written.
   1.111 +    * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
   1.112 +    */
   1.113 +   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA;
   1.114 +#endif
   1.115 +}
   1.116 +
   1.117 +void PNGAPI
   1.118 +png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
   1.119 +    png_uint_32 length)
   1.120 +{
   1.121 +   png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
   1.122 +}
   1.123 +
   1.124 +/* Write the data of a PNG chunk started with png_write_chunk_header().
   1.125 + * Note that multiple calls to this function are allowed, and that the
   1.126 + * sum of the lengths from these calls *must* add up to the total_length
   1.127 + * given to png_write_chunk_header().
   1.128 + */
   1.129 +void PNGAPI
   1.130 +png_write_chunk_data(png_structrp png_ptr, png_const_bytep data,
   1.131 +    png_size_t length)
   1.132 +{
   1.133 +   /* Write the data, and run the CRC over it */
   1.134 +   if (png_ptr == NULL)
   1.135 +      return;
   1.136 +
   1.137 +   if (data != NULL && length > 0)
   1.138 +   {
   1.139 +      png_write_data(png_ptr, data, length);
   1.140 +
   1.141 +      /* Update the CRC after writing the data,
   1.142 +       * in case that the user I/O routine alters it.
   1.143 +       */
   1.144 +      png_calculate_crc(png_ptr, data, length);
   1.145 +   }
   1.146 +}
   1.147 +
   1.148 +/* Finish a chunk started with png_write_chunk_header(). */
   1.149 +void PNGAPI
   1.150 +png_write_chunk_end(png_structrp png_ptr)
   1.151 +{
   1.152 +   png_byte buf[4];
   1.153 +
   1.154 +   if (png_ptr == NULL) return;
   1.155 +
   1.156 +#ifdef PNG_IO_STATE_SUPPORTED
   1.157 +   /* Inform the I/O callback that the chunk CRC is being written.
   1.158 +    * PNG_IO_CHUNK_CRC requires a single I/O function call.
   1.159 +    */
   1.160 +   png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC;
   1.161 +#endif
   1.162 +
   1.163 +   /* Write the crc in a single operation */
   1.164 +   png_save_uint_32(buf, png_ptr->crc);
   1.165 +
   1.166 +   png_write_data(png_ptr, buf, (png_size_t)4);
   1.167 +}
   1.168 +
   1.169 +/* Write a PNG chunk all at once.  The type is an array of ASCII characters
   1.170 + * representing the chunk name.  The array must be at least 4 bytes in
   1.171 + * length, and does not need to be null terminated.  To be safe, pass the
   1.172 + * pre-defined chunk names here, and if you need a new one, define it
   1.173 + * where the others are defined.  The length is the length of the data.
   1.174 + * All the data must be present.  If that is not possible, use the
   1.175 + * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
   1.176 + * functions instead.
   1.177 + */
   1.178 +static void
   1.179 +png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
   1.180 +   png_const_bytep data, png_size_t length)
   1.181 +{
   1.182 +   if (png_ptr == NULL)
   1.183 +      return;
   1.184 +
   1.185 +   /* On 64 bit architectures 'length' may not fit in a png_uint_32. */
   1.186 +   if (length > PNG_UINT_31_MAX)
   1.187 +      png_error(png_ptr, "length exceeds PNG maxima");
   1.188 +
   1.189 +   png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
   1.190 +   png_write_chunk_data(png_ptr, data, length);
   1.191 +   png_write_chunk_end(png_ptr);
   1.192 +}
   1.193 +
   1.194 +/* This is the API that calls the internal function above. */
   1.195 +void PNGAPI
   1.196 +png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
   1.197 +   png_const_bytep data, png_size_t length)
   1.198 +{
   1.199 +   png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
   1.200 +      length);
   1.201 +}
   1.202 +
   1.203 +/* This is used below to find the size of an image to pass to png_deflate_claim,
   1.204 + * so it only needs to be accurate if the size is less than 16384 bytes (the
   1.205 + * point at which a lower LZ window size can be used.)
   1.206 + */
   1.207 +static png_alloc_size_t
   1.208 +png_image_size(png_structrp png_ptr)
   1.209 +{
   1.210 +   /* Only return sizes up to the maximum of a png_uint_32, do this by limiting
   1.211 +    * the width and height used to 15 bits.
   1.212 +    */
   1.213 +   png_uint_32 h = png_ptr->height;
   1.214 +
   1.215 +   if (png_ptr->rowbytes < 32768 && h < 32768)
   1.216 +   {
   1.217 +      if (png_ptr->interlaced)
   1.218 +      {
   1.219 +         /* Interlacing makes the image larger because of the replication of
   1.220 +          * both the filter byte and the padding to a byte boundary.
   1.221 +          */
   1.222 +         png_uint_32 w = png_ptr->width;
   1.223 +         unsigned int pd = png_ptr->pixel_depth;
   1.224 +         png_alloc_size_t cb_base;
   1.225 +         int pass;
   1.226 +
   1.227 +         for (cb_base=0, pass=0; pass<=6; ++pass)
   1.228 +         {
   1.229 +            png_uint_32 pw = PNG_PASS_COLS(w, pass);
   1.230 +
   1.231 +            if (pw > 0)
   1.232 +               cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass);
   1.233 +         }
   1.234 +
   1.235 +         return cb_base;
   1.236 +      }
   1.237 +
   1.238 +      else
   1.239 +         return (png_ptr->rowbytes+1) * h;
   1.240 +   }
   1.241 +
   1.242 +   else
   1.243 +      return 0xffffffffU;
   1.244 +}
   1.245 +
   1.246 +#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
   1.247 +   /* This is the code to hack the first two bytes of the deflate stream (the
   1.248 +    * deflate header) to correct the windowBits value to match the actual data
   1.249 +    * size.  Note that the second argument is the *uncompressed* size but the
   1.250 +    * first argument is the *compressed* data (and it must be deflate
   1.251 +    * compressed.)
   1.252 +    */
   1.253 +static void
   1.254 +optimize_cmf(png_bytep data, png_alloc_size_t data_size)
   1.255 +{
   1.256 +   /* Optimize the CMF field in the zlib stream.  The resultant zlib stream is
   1.257 +    * still compliant to the stream specification.
   1.258 +    */
   1.259 +   if (data_size <= 16384) /* else windowBits must be 15 */
   1.260 +   {
   1.261 +      unsigned int z_cmf = data[0];  /* zlib compression method and flags */
   1.262 +
   1.263 +      if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
   1.264 +      {
   1.265 +         unsigned int z_cinfo;
   1.266 +         unsigned int half_z_window_size;
   1.267 +
   1.268 +         z_cinfo = z_cmf >> 4;
   1.269 +         half_z_window_size = 1U << (z_cinfo + 7);
   1.270 +
   1.271 +         if (data_size <= half_z_window_size) /* else no change */
   1.272 +         {
   1.273 +            unsigned int tmp;
   1.274 +
   1.275 +            do
   1.276 +            {
   1.277 +               half_z_window_size >>= 1;
   1.278 +               --z_cinfo;
   1.279 +            }
   1.280 +            while (z_cinfo > 0 && data_size <= half_z_window_size);
   1.281 +
   1.282 +            z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
   1.283 +
   1.284 +            data[0] = (png_byte)z_cmf;
   1.285 +            tmp = data[1] & 0xe0;
   1.286 +            tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
   1.287 +            data[1] = (png_byte)tmp;
   1.288 +         }
   1.289 +      }
   1.290 +   }
   1.291 +}
   1.292 +#else
   1.293 +#  define optimize_cmf(dp,dl) ((void)0)
   1.294 +#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
   1.295 +
   1.296 +/* Initialize the compressor for the appropriate type of compression. */
   1.297 +static int
   1.298 +png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
   1.299 +   png_alloc_size_t data_size)
   1.300 +{
   1.301 +   if (png_ptr->zowner != 0)
   1.302 +   {
   1.303 +      char msg[64];
   1.304 +
   1.305 +      PNG_STRING_FROM_CHUNK(msg, owner);
   1.306 +      msg[4] = ':';
   1.307 +      msg[5] = ' ';
   1.308 +      PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner);
   1.309 +      /* So the message that results is "<chunk> using zstream"; this is an
   1.310 +       * internal error, but is very useful for debugging.  i18n requirements
   1.311 +       * are minimal.
   1.312 +       */
   1.313 +      (void)png_safecat(msg, (sizeof msg), 10, " using zstream");
   1.314 +#     if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
   1.315 +         png_warning(png_ptr, msg);
   1.316 +
   1.317 +         /* Attempt sane error recovery */
   1.318 +         if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */
   1.319 +         {
   1.320 +            png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT");
   1.321 +            return Z_STREAM_ERROR;
   1.322 +         }
   1.323 +
   1.324 +         png_ptr->zowner = 0;
   1.325 +#     else
   1.326 +         png_error(png_ptr, msg);
   1.327 +#     endif
   1.328 +   }
   1.329 +
   1.330 +   {
   1.331 +      int level = png_ptr->zlib_level;
   1.332 +      int method = png_ptr->zlib_method;
   1.333 +      int windowBits = png_ptr->zlib_window_bits;
   1.334 +      int memLevel = png_ptr->zlib_mem_level;
   1.335 +      int strategy; /* set below */
   1.336 +      int ret; /* zlib return code */
   1.337 +
   1.338 +      if (owner == png_IDAT)
   1.339 +      {
   1.340 +         if (png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)
   1.341 +            strategy = png_ptr->zlib_strategy;
   1.342 +
   1.343 +         else if (png_ptr->do_filter != PNG_FILTER_NONE)
   1.344 +            strategy = PNG_Z_DEFAULT_STRATEGY;
   1.345 +
   1.346 +         else
   1.347 +            strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY;
   1.348 +      }
   1.349 +
   1.350 +      else
   1.351 +      {
   1.352 +#        ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
   1.353 +            level = png_ptr->zlib_text_level;
   1.354 +            method = png_ptr->zlib_text_method;
   1.355 +            windowBits = png_ptr->zlib_text_window_bits;
   1.356 +            memLevel = png_ptr->zlib_text_mem_level;
   1.357 +            strategy = png_ptr->zlib_text_strategy;
   1.358 +#        else
   1.359 +            /* If customization is not supported the values all come from the
   1.360 +             * IDAT values except for the strategy, which is fixed to the
   1.361 +             * default.  (This is the pre-1.6.0 behavior too, although it was
   1.362 +             * implemented in a very different way.)
   1.363 +             */
   1.364 +            strategy = Z_DEFAULT_STRATEGY;
   1.365 +#        endif
   1.366 +      }
   1.367 +
   1.368 +      /* Adjust 'windowBits' down if larger than 'data_size'; to stop this
   1.369 +       * happening just pass 32768 as the data_size parameter.  Notice that zlib
   1.370 +       * requires an extra 262 bytes in the window in addition to the data to be
   1.371 +       * able to see the whole of the data, so if data_size+262 takes us to the
   1.372 +       * next windowBits size we need to fix up the value later.  (Because even
   1.373 +       * though deflate needs the extra window, inflate does not!)
   1.374 +       */
   1.375 +      if (data_size <= 16384)
   1.376 +      {
   1.377 +         /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to
   1.378 +          * work round a Microsoft Visual C misbehavior which, contrary to C-90,
   1.379 +          * widens the result of the following shift to 64-bits if (and,
   1.380 +          * apparently, only if) it is used in a test.
   1.381 +          */
   1.382 +         unsigned int half_window_size = 1U << (windowBits-1);
   1.383 +
   1.384 +         while (data_size + 262 <= half_window_size)
   1.385 +         {
   1.386 +            half_window_size >>= 1;
   1.387 +            --windowBits;
   1.388 +         }
   1.389 +      }
   1.390 +
   1.391 +      /* Check against the previous initialized values, if any. */
   1.392 +      if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) &&
   1.393 +         (png_ptr->zlib_set_level != level ||
   1.394 +         png_ptr->zlib_set_method != method ||
   1.395 +         png_ptr->zlib_set_window_bits != windowBits ||
   1.396 +         png_ptr->zlib_set_mem_level != memLevel ||
   1.397 +         png_ptr->zlib_set_strategy != strategy))
   1.398 +      {
   1.399 +         if (deflateEnd(&png_ptr->zstream) != Z_OK)
   1.400 +            png_warning(png_ptr, "deflateEnd failed (ignored)");
   1.401 +
   1.402 +         png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED;
   1.403 +      }
   1.404 +
   1.405 +      /* For safety clear out the input and output pointers (currently zlib
   1.406 +       * doesn't use them on Init, but it might in the future).
   1.407 +       */
   1.408 +      png_ptr->zstream.next_in = NULL;
   1.409 +      png_ptr->zstream.avail_in = 0;
   1.410 +      png_ptr->zstream.next_out = NULL;
   1.411 +      png_ptr->zstream.avail_out = 0;
   1.412 +
   1.413 +      /* Now initialize if required, setting the new parameters, otherwise just
   1.414 +       * to a simple reset to the previous parameters.
   1.415 +       */
   1.416 +      if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED)
   1.417 +         ret = deflateReset(&png_ptr->zstream);
   1.418 +
   1.419 +      else
   1.420 +      {
   1.421 +         ret = deflateInit2(&png_ptr->zstream, level, method, windowBits,
   1.422 +            memLevel, strategy);
   1.423 +
   1.424 +         if (ret == Z_OK)
   1.425 +            png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
   1.426 +      }
   1.427 +
   1.428 +      /* The return code is from either deflateReset or deflateInit2; they have
   1.429 +       * pretty much the same set of error codes.
   1.430 +       */
   1.431 +      if (ret == Z_OK)
   1.432 +         png_ptr->zowner = owner;
   1.433 +
   1.434 +      else
   1.435 +         png_zstream_error(png_ptr, ret);
   1.436 +
   1.437 +      return ret;
   1.438 +   }
   1.439 +}
   1.440 +
   1.441 +/* Clean up (or trim) a linked list of compression buffers. */
   1.442 +void /* PRIVATE */
   1.443 +png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp)
   1.444 +{
   1.445 +   png_compression_bufferp list = *listp;
   1.446 +
   1.447 +   if (list != NULL)
   1.448 +   {
   1.449 +      *listp = NULL;
   1.450 +
   1.451 +      do
   1.452 +      {
   1.453 +         png_compression_bufferp next = list->next;
   1.454 +
   1.455 +         png_free(png_ptr, list);
   1.456 +         list = next;
   1.457 +      }
   1.458 +      while (list != NULL);
   1.459 +   }
   1.460 +}
   1.461 +
   1.462 +#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
   1.463 +/* This pair of functions encapsulates the operation of (a) compressing a
   1.464 + * text string, and (b) issuing it later as a series of chunk data writes.
   1.465 + * The compression_state structure is shared context for these functions
   1.466 + * set up by the caller to allow access to the relevant local variables.
   1.467 + *
   1.468 + * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size
   1.469 + * temporary buffers.  From 1.6.0 it is retained in png_struct so that it will
   1.470 + * be correctly freed in the event of a write error (previous implementations
   1.471 + * just leaked memory.)
   1.472 + */
   1.473 +typedef struct
   1.474 +{
   1.475 +   png_const_bytep      input;        /* The uncompressed input data */
   1.476 +   png_alloc_size_t     input_len;    /* Its length */
   1.477 +   png_uint_32          output_len;   /* Final compressed length */
   1.478 +   png_byte             output[1024]; /* First block of output */
   1.479 +} compression_state;
   1.480 +
   1.481 +static void
   1.482 +png_text_compress_init(compression_state *comp, png_const_bytep input,
   1.483 +   png_alloc_size_t input_len)
   1.484 +{
   1.485 +   comp->input = input;
   1.486 +   comp->input_len = input_len;
   1.487 +   comp->output_len = 0;
   1.488 +}
   1.489 +
   1.490 +/* Compress the data in the compression state input */
   1.491 +static int
   1.492 +png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
   1.493 +   compression_state *comp, png_uint_32 prefix_len)
   1.494 +{
   1.495 +   int ret;
   1.496 +
   1.497 +   /* To find the length of the output it is necessary to first compress the
   1.498 +    * input, the result is buffered rather than using the two-pass algorithm
   1.499 +    * that is used on the inflate side; deflate is assumed to be slower and a
   1.500 +    * PNG writer is assumed to have more memory available than a PNG reader.
   1.501 +    *
   1.502 +    * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an
   1.503 +    * upper limit on the output size, but it is always bigger than the input
   1.504 +    * size so it is likely to be more efficient to use this linked-list
   1.505 +    * approach.
   1.506 +    */
   1.507 +   ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len);
   1.508 +
   1.509 +   if (ret != Z_OK)
   1.510 +      return ret;
   1.511 +
   1.512 +   /* Set up the compression buffers, we need a loop here to avoid overflowing a
   1.513 +    * uInt.  Use ZLIB_IO_MAX to limit the input.  The output is always limited
   1.514 +    * by the output buffer size, so there is no need to check that.  Since this
   1.515 +    * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits
   1.516 +    * in size.
   1.517 +    */
   1.518 +   {
   1.519 +      png_compression_bufferp *end = &png_ptr->zbuffer_list;
   1.520 +      png_alloc_size_t input_len = comp->input_len; /* may be zero! */
   1.521 +      png_uint_32 output_len;
   1.522 +
   1.523 +      /* zlib updates these for us: */
   1.524 +      png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input);
   1.525 +      png_ptr->zstream.avail_in = 0; /* Set below */
   1.526 +      png_ptr->zstream.next_out = comp->output;
   1.527 +      png_ptr->zstream.avail_out = (sizeof comp->output);
   1.528 +
   1.529 +      output_len = png_ptr->zstream.avail_out;
   1.530 +
   1.531 +      do
   1.532 +      {
   1.533 +         uInt avail_in = ZLIB_IO_MAX;
   1.534 +
   1.535 +         if (avail_in > input_len)
   1.536 +            avail_in = (uInt)input_len;
   1.537 +
   1.538 +         input_len -= avail_in;
   1.539 +
   1.540 +         png_ptr->zstream.avail_in = avail_in;
   1.541 +
   1.542 +         if (png_ptr->zstream.avail_out == 0)
   1.543 +         {
   1.544 +            png_compression_buffer *next;
   1.545 +
   1.546 +            /* Chunk data is limited to 2^31 bytes in length, so the prefix
   1.547 +             * length must be counted here.
   1.548 +             */
   1.549 +            if (output_len + prefix_len > PNG_UINT_31_MAX)
   1.550 +            {
   1.551 +               ret = Z_MEM_ERROR;
   1.552 +               break;
   1.553 +            }
   1.554 +
   1.555 +            /* Need a new (malloc'ed) buffer, but there may be one present
   1.556 +             * already.
   1.557 +             */
   1.558 +            next = *end;
   1.559 +            if (next == NULL)
   1.560 +            {
   1.561 +               next = png_voidcast(png_compression_bufferp, png_malloc_base
   1.562 +                  (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
   1.563 +
   1.564 +               if (next == NULL)
   1.565 +               {
   1.566 +                  ret = Z_MEM_ERROR;
   1.567 +                  break;
   1.568 +               }
   1.569 +
   1.570 +               /* Link in this buffer (so that it will be freed later) */
   1.571 +               next->next = NULL;
   1.572 +               *end = next;
   1.573 +            }
   1.574 +
   1.575 +            png_ptr->zstream.next_out = next->output;
   1.576 +            png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
   1.577 +            output_len += png_ptr->zstream.avail_out;
   1.578 +
   1.579 +            /* Move 'end' to the next buffer pointer. */
   1.580 +            end = &next->next;
   1.581 +         }
   1.582 +
   1.583 +         /* Compress the data */
   1.584 +         ret = deflate(&png_ptr->zstream,
   1.585 +            input_len > 0 ? Z_NO_FLUSH : Z_FINISH);
   1.586 +
   1.587 +         /* Claw back input data that was not consumed (because avail_in is
   1.588 +          * reset above every time round the loop).
   1.589 +          */
   1.590 +         input_len += png_ptr->zstream.avail_in;
   1.591 +         png_ptr->zstream.avail_in = 0; /* safety */
   1.592 +      }
   1.593 +      while (ret == Z_OK);
   1.594 +
   1.595 +      /* There may be some space left in the last output buffer, this needs to
   1.596 +       * be subtracted from output_len.
   1.597 +       */
   1.598 +      output_len -= png_ptr->zstream.avail_out;
   1.599 +      png_ptr->zstream.avail_out = 0; /* safety */
   1.600 +      comp->output_len = output_len;
   1.601 +
   1.602 +      /* Now double check the output length, put in a custom message if it is
   1.603 +       * too long.  Otherwise ensure the z_stream::msg pointer is set to
   1.604 +       * something.
   1.605 +       */
   1.606 +      if (output_len + prefix_len >= PNG_UINT_31_MAX)
   1.607 +      {
   1.608 +         png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long");
   1.609 +         ret = Z_MEM_ERROR;
   1.610 +      }
   1.611 +
   1.612 +      else
   1.613 +         png_zstream_error(png_ptr, ret);
   1.614 +
   1.615 +      /* Reset zlib for another zTXt/iTXt or image data */
   1.616 +      png_ptr->zowner = 0;
   1.617 +
   1.618 +      /* The only success case is Z_STREAM_END, input_len must be 0, if not this
   1.619 +       * is an internal error.
   1.620 +       */
   1.621 +      if (ret == Z_STREAM_END && input_len == 0)
   1.622 +      {
   1.623 +         /* Fix up the deflate header, if required */
   1.624 +         optimize_cmf(comp->output, comp->input_len);
   1.625 +
   1.626 +         /* But Z_OK is returned, not Z_STREAM_END; this allows the claim
   1.627 +          * function above to return Z_STREAM_END on an error (though it never
   1.628 +          * does in the current versions of zlib.)
   1.629 +          */
   1.630 +         return Z_OK;
   1.631 +      }
   1.632 +
   1.633 +      else
   1.634 +         return ret;
   1.635 +   }
   1.636 +}
   1.637 +
   1.638 +/* Ship the compressed text out via chunk writes */
   1.639 +static void
   1.640 +png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
   1.641 +{
   1.642 +   png_uint_32 output_len = comp->output_len;
   1.643 +   png_const_bytep output = comp->output;
   1.644 +   png_uint_32 avail = (sizeof comp->output);
   1.645 +   png_compression_buffer *next = png_ptr->zbuffer_list;
   1.646 +
   1.647 +   for (;;)
   1.648 +   {
   1.649 +      if (avail > output_len)
   1.650 +         avail = output_len;
   1.651 +
   1.652 +      png_write_chunk_data(png_ptr, output, avail);
   1.653 +
   1.654 +      output_len -= avail;
   1.655 +
   1.656 +      if (output_len == 0 || next == NULL)
   1.657 +         break;
   1.658 +
   1.659 +      avail = png_ptr->zbuffer_size;
   1.660 +      output = next->output;
   1.661 +      next = next->next;
   1.662 +   }
   1.663 +
   1.664 +   /* This is an internal error; 'next' must have been NULL! */
   1.665 +   if (output_len > 0)
   1.666 +      png_error(png_ptr, "error writing ancillary chunked compressed data");
   1.667 +}
   1.668 +#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
   1.669 +
   1.670 +#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
   1.671 +    defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
   1.672 +/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
   1.673 + * and if invalid, correct the keyword rather than discarding the entire
   1.674 + * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
   1.675 + * length, forbids leading or trailing whitespace, multiple internal spaces,
   1.676 + * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
   1.677 + *
   1.678 + * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
   1.679 + * trailing '\0').  If this routine returns 0 then there was no keyword, or a
   1.680 + * valid one could not be generated, and the caller must png_error.
   1.681 + */
   1.682 +static png_uint_32
   1.683 +png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
   1.684 +{
   1.685 +   png_const_charp orig_key = key;
   1.686 +   png_uint_32 key_len = 0;
   1.687 +   int bad_character = 0;
   1.688 +   int space = 1;
   1.689 +
   1.690 +   png_debug(1, "in png_check_keyword");
   1.691 +
   1.692 +   if (key == NULL)
   1.693 +   {
   1.694 +      *new_key = 0;
   1.695 +      return 0;
   1.696 +   }
   1.697 +
   1.698 +   while (*key && key_len < 79)
   1.699 +   {
   1.700 +      png_byte ch = (png_byte)(0xff & *key++);
   1.701 +
   1.702 +      if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
   1.703 +         *new_key++ = ch, ++key_len, space = 0;
   1.704 +
   1.705 +      else if (!space)
   1.706 +      {
   1.707 +         /* A space or an invalid character when one wasn't seen immediately
   1.708 +          * before; output just a space.
   1.709 +          */
   1.710 +         *new_key++ = 32, ++key_len, space = 1;
   1.711 +
   1.712 +         /* If the character was not a space then it is invalid. */
   1.713 +         if (ch != 32)
   1.714 +            bad_character = ch;
   1.715 +      }
   1.716 +
   1.717 +      else if (!bad_character)
   1.718 +         bad_character = ch; /* just skip it, record the first error */
   1.719 +   }
   1.720 +
   1.721 +   if (key_len > 0 && space) /* trailing space */
   1.722 +   {
   1.723 +      --key_len, --new_key;
   1.724 +      if (!bad_character)
   1.725 +         bad_character = 32;
   1.726 +   }
   1.727 +
   1.728 +   /* Terminate the keyword */
   1.729 +   *new_key = 0;
   1.730 +
   1.731 +   if (key_len == 0)
   1.732 +      return 0;
   1.733 +
   1.734 +   /* Try to only output one warning per keyword: */
   1.735 +   if (*key) /* keyword too long */
   1.736 +      png_warning(png_ptr, "keyword truncated");
   1.737 +
   1.738 +   else if (bad_character)
   1.739 +   {
   1.740 +      PNG_WARNING_PARAMETERS(p)
   1.741 +
   1.742 +      png_warning_parameter(p, 1, orig_key);
   1.743 +      png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
   1.744 +
   1.745 +      png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
   1.746 +   }
   1.747 +
   1.748 +   return key_len;
   1.749 +}
   1.750 +#endif
   1.751 +
   1.752 +/* Write the IHDR chunk, and update the png_struct with the necessary
   1.753 + * information.  Note that the rest of this code depends upon this
   1.754 + * information being correct.
   1.755 + */
   1.756 +void /* PRIVATE */
   1.757 +png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
   1.758 +    int bit_depth, int color_type, int compression_type, int filter_type,
   1.759 +    int interlace_type)
   1.760 +{
   1.761 +   png_byte buf[13]; /* Buffer to store the IHDR info */
   1.762 +
   1.763 +   png_debug(1, "in png_write_IHDR");
   1.764 +
   1.765 +   /* Check that we have valid input data from the application info */
   1.766 +   switch (color_type)
   1.767 +   {
   1.768 +      case PNG_COLOR_TYPE_GRAY:
   1.769 +         switch (bit_depth)
   1.770 +         {
   1.771 +            case 1:
   1.772 +            case 2:
   1.773 +            case 4:
   1.774 +            case 8:
   1.775 +#ifdef PNG_WRITE_16BIT_SUPPORTED
   1.776 +            case 16:
   1.777 +#endif
   1.778 +               png_ptr->channels = 1; break;
   1.779 +
   1.780 +            default:
   1.781 +               png_error(png_ptr,
   1.782 +                   "Invalid bit depth for grayscale image");
   1.783 +         }
   1.784 +         break;
   1.785 +
   1.786 +      case PNG_COLOR_TYPE_RGB:
   1.787 +#ifdef PNG_WRITE_16BIT_SUPPORTED
   1.788 +         if (bit_depth != 8 && bit_depth != 16)
   1.789 +#else
   1.790 +         if (bit_depth != 8)
   1.791 +#endif
   1.792 +            png_error(png_ptr, "Invalid bit depth for RGB image");
   1.793 +
   1.794 +         png_ptr->channels = 3;
   1.795 +         break;
   1.796 +
   1.797 +      case PNG_COLOR_TYPE_PALETTE:
   1.798 +         switch (bit_depth)
   1.799 +         {
   1.800 +            case 1:
   1.801 +            case 2:
   1.802 +            case 4:
   1.803 +            case 8:
   1.804 +               png_ptr->channels = 1;
   1.805 +               break;
   1.806 +
   1.807 +            default:
   1.808 +               png_error(png_ptr, "Invalid bit depth for paletted image");
   1.809 +         }
   1.810 +         break;
   1.811 +
   1.812 +      case PNG_COLOR_TYPE_GRAY_ALPHA:
   1.813 +         if (bit_depth != 8 && bit_depth != 16)
   1.814 +            png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
   1.815 +
   1.816 +         png_ptr->channels = 2;
   1.817 +         break;
   1.818 +
   1.819 +      case PNG_COLOR_TYPE_RGB_ALPHA:
   1.820 +#ifdef PNG_WRITE_16BIT_SUPPORTED
   1.821 +         if (bit_depth != 8 && bit_depth != 16)
   1.822 +#else
   1.823 +         if (bit_depth != 8)
   1.824 +#endif
   1.825 +            png_error(png_ptr, "Invalid bit depth for RGBA image");
   1.826 +
   1.827 +         png_ptr->channels = 4;
   1.828 +         break;
   1.829 +
   1.830 +      default:
   1.831 +         png_error(png_ptr, "Invalid image color type specified");
   1.832 +   }
   1.833 +
   1.834 +   if (compression_type != PNG_COMPRESSION_TYPE_BASE)
   1.835 +   {
   1.836 +      png_warning(png_ptr, "Invalid compression type specified");
   1.837 +      compression_type = PNG_COMPRESSION_TYPE_BASE;
   1.838 +   }
   1.839 +
   1.840 +   /* Write filter_method 64 (intrapixel differencing) only if
   1.841 +    * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
   1.842 +    * 2. Libpng did not write a PNG signature (this filter_method is only
   1.843 +    *    used in PNG datastreams that are embedded in MNG datastreams) and
   1.844 +    * 3. The application called png_permit_mng_features with a mask that
   1.845 +    *    included PNG_FLAG_MNG_FILTER_64 and
   1.846 +    * 4. The filter_method is 64 and
   1.847 +    * 5. The color_type is RGB or RGBA
   1.848 +    */
   1.849 +   if (
   1.850 +#ifdef PNG_MNG_FEATURES_SUPPORTED
   1.851 +       !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
   1.852 +       ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
   1.853 +       (color_type == PNG_COLOR_TYPE_RGB ||
   1.854 +        color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
   1.855 +       (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
   1.856 +#endif
   1.857 +       filter_type != PNG_FILTER_TYPE_BASE)
   1.858 +   {
   1.859 +      png_warning(png_ptr, "Invalid filter type specified");
   1.860 +      filter_type = PNG_FILTER_TYPE_BASE;
   1.861 +   }
   1.862 +
   1.863 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED
   1.864 +   if (interlace_type != PNG_INTERLACE_NONE &&
   1.865 +       interlace_type != PNG_INTERLACE_ADAM7)
   1.866 +   {
   1.867 +      png_warning(png_ptr, "Invalid interlace type specified");
   1.868 +      interlace_type = PNG_INTERLACE_ADAM7;
   1.869 +   }
   1.870 +#else
   1.871 +   interlace_type=PNG_INTERLACE_NONE;
   1.872 +#endif
   1.873 +
   1.874 +   /* Save the relevent information */
   1.875 +   png_ptr->bit_depth = (png_byte)bit_depth;
   1.876 +   png_ptr->color_type = (png_byte)color_type;
   1.877 +   png_ptr->interlaced = (png_byte)interlace_type;
   1.878 +#ifdef PNG_MNG_FEATURES_SUPPORTED
   1.879 +   png_ptr->filter_type = (png_byte)filter_type;
   1.880 +#endif
   1.881 +   png_ptr->compression_type = (png_byte)compression_type;
   1.882 +   png_ptr->width = width;
   1.883 +   png_ptr->height = height;
   1.884 +
   1.885 +   png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
   1.886 +   png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
   1.887 +   /* Set the usr info, so any transformations can modify it */
   1.888 +   png_ptr->usr_width = png_ptr->width;
   1.889 +   png_ptr->usr_bit_depth = png_ptr->bit_depth;
   1.890 +   png_ptr->usr_channels = png_ptr->channels;
   1.891 +
   1.892 +   /* Pack the header information into the buffer */
   1.893 +   png_save_uint_32(buf, width);
   1.894 +   png_save_uint_32(buf + 4, height);
   1.895 +   buf[8] = (png_byte)bit_depth;
   1.896 +   buf[9] = (png_byte)color_type;
   1.897 +   buf[10] = (png_byte)compression_type;
   1.898 +   buf[11] = (png_byte)filter_type;
   1.899 +   buf[12] = (png_byte)interlace_type;
   1.900 +
   1.901 +   /* Write the chunk */
   1.902 +   png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
   1.903 +
   1.904 +#ifdef PNG_WRITE_APNG_SUPPORTED
   1.905 +   png_ptr->first_frame_width = width;
   1.906 +   png_ptr->first_frame_height = height;
   1.907 +#endif
   1.908 +
   1.909 +   if (!(png_ptr->do_filter))
   1.910 +   {
   1.911 +      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
   1.912 +          png_ptr->bit_depth < 8)
   1.913 +         png_ptr->do_filter = PNG_FILTER_NONE;
   1.914 +
   1.915 +      else
   1.916 +         png_ptr->do_filter = PNG_ALL_FILTERS;
   1.917 +   }
   1.918 +
   1.919 +   png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
   1.920 +}
   1.921 +
   1.922 +/* Write the palette.  We are careful not to trust png_color to be in the
   1.923 + * correct order for PNG, so people can redefine it to any convenient
   1.924 + * structure.
   1.925 + */
   1.926 +void /* PRIVATE */
   1.927 +png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
   1.928 +    png_uint_32 num_pal)
   1.929 +{
   1.930 +   png_uint_32 i;
   1.931 +   png_const_colorp pal_ptr;
   1.932 +   png_byte buf[3];
   1.933 +
   1.934 +   png_debug(1, "in png_write_PLTE");
   1.935 +
   1.936 +   if ((
   1.937 +#ifdef PNG_MNG_FEATURES_SUPPORTED
   1.938 +       !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
   1.939 +#endif
   1.940 +       num_pal == 0) || num_pal > 256)
   1.941 +   {
   1.942 +      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   1.943 +      {
   1.944 +         png_error(png_ptr, "Invalid number of colors in palette");
   1.945 +      }
   1.946 +
   1.947 +      else
   1.948 +      {
   1.949 +         png_warning(png_ptr, "Invalid number of colors in palette");
   1.950 +         return;
   1.951 +      }
   1.952 +   }
   1.953 +
   1.954 +   if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
   1.955 +   {
   1.956 +      png_warning(png_ptr,
   1.957 +          "Ignoring request to write a PLTE chunk in grayscale PNG");
   1.958 +
   1.959 +      return;
   1.960 +   }
   1.961 +
   1.962 +   png_ptr->num_palette = (png_uint_16)num_pal;
   1.963 +   png_debug1(3, "num_palette = %d", png_ptr->num_palette);
   1.964 +
   1.965 +   png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
   1.966 +#ifdef PNG_POINTER_INDEXING_SUPPORTED
   1.967 +
   1.968 +   for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
   1.969 +   {
   1.970 +      buf[0] = pal_ptr->red;
   1.971 +      buf[1] = pal_ptr->green;
   1.972 +      buf[2] = pal_ptr->blue;
   1.973 +      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
   1.974 +   }
   1.975 +
   1.976 +#else
   1.977 +   /* This is a little slower but some buggy compilers need to do this
   1.978 +    * instead
   1.979 +    */
   1.980 +   pal_ptr=palette;
   1.981 +
   1.982 +   for (i = 0; i < num_pal; i++)
   1.983 +   {
   1.984 +      buf[0] = pal_ptr[i].red;
   1.985 +      buf[1] = pal_ptr[i].green;
   1.986 +      buf[2] = pal_ptr[i].blue;
   1.987 +      png_write_chunk_data(png_ptr, buf, (png_size_t)3);
   1.988 +   }
   1.989 +
   1.990 +#endif
   1.991 +   png_write_chunk_end(png_ptr);
   1.992 +   png_ptr->mode |= PNG_HAVE_PLTE;
   1.993 +}
   1.994 +
   1.995 +/* This is similar to png_text_compress, above, except that it does not require
   1.996 + * all of the data at once and, instead of buffering the compressed result,
   1.997 + * writes it as IDAT chunks.  Unlike png_text_compress it *can* png_error out
   1.998 + * because it calls the write interface.  As a result it does its own error
   1.999 + * reporting and does not return an error code.  In the event of error it will
  1.1000 + * just call png_error.  The input data length may exceed 32-bits.  The 'flush'
  1.1001 + * parameter is exactly the same as that to deflate, with the following
  1.1002 + * meanings:
  1.1003 + *
  1.1004 + * Z_NO_FLUSH: normal incremental output of compressed data
  1.1005 + * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush
  1.1006 + * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
  1.1007 + *
  1.1008 + * The routine manages the acquire and release of the png_ptr->zstream by
  1.1009 + * checking and (at the end) clearing png_ptr->zowner, it does some sanity
  1.1010 + * checks on the 'mode' flags while doing this.
  1.1011 + */
  1.1012 +void /* PRIVATE */
  1.1013 +png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
  1.1014 +   png_alloc_size_t input_len, int flush)
  1.1015 +{
  1.1016 +   if (png_ptr->zowner != png_IDAT)
  1.1017 +   {
  1.1018 +      /* First time.   Ensure we have a temporary buffer for compression and
  1.1019 +       * trim the buffer list if it has more than one entry to free memory.
  1.1020 +       * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been
  1.1021 +       * created at this point, but the check here is quick and safe.
  1.1022 +       */
  1.1023 +      if (png_ptr->zbuffer_list == NULL)
  1.1024 +      {
  1.1025 +         png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp,
  1.1026 +            png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
  1.1027 +         png_ptr->zbuffer_list->next = NULL;
  1.1028 +      }
  1.1029 +
  1.1030 +      else
  1.1031 +         png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next);
  1.1032 +
  1.1033 +      /* It is a terminal error if we can't claim the zstream. */
  1.1034 +      if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK)
  1.1035 +         png_error(png_ptr, png_ptr->zstream.msg);
  1.1036 +
  1.1037 +      /* The output state is maintained in png_ptr->zstream, so it must be
  1.1038 +       * initialized here after the claim.
  1.1039 +       */
  1.1040 +      png_ptr->zstream.next_out = png_ptr->zbuffer_list->output;
  1.1041 +      png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
  1.1042 +   }
  1.1043 +
  1.1044 +   /* Now loop reading and writing until all the input is consumed or an error
  1.1045 +    * terminates the operation.  The _out values are maintained across calls to
  1.1046 +    * this function, but the input must be reset each time.
  1.1047 +    */
  1.1048 +   png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
  1.1049 +   png_ptr->zstream.avail_in = 0; /* set below */
  1.1050 +   for (;;)
  1.1051 +   {
  1.1052 +      int ret;
  1.1053 +
  1.1054 +      /* INPUT: from the row data */
  1.1055 +      uInt avail = ZLIB_IO_MAX;
  1.1056 +
  1.1057 +      if (avail > input_len)
  1.1058 +         avail = (uInt)input_len; /* safe because of the check */
  1.1059 +
  1.1060 +      png_ptr->zstream.avail_in = avail;
  1.1061 +      input_len -= avail;
  1.1062 +
  1.1063 +      ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush);
  1.1064 +
  1.1065 +      /* Include as-yet unconsumed input */
  1.1066 +      input_len += png_ptr->zstream.avail_in;
  1.1067 +      png_ptr->zstream.avail_in = 0;
  1.1068 +
  1.1069 +      /* OUTPUT: write complete IDAT chunks when avail_out drops to zero, note
  1.1070 +       * that these two zstream fields are preserved across the calls, therefore
  1.1071 +       * there is no need to set these up on entry to the loop.
  1.1072 +       */
  1.1073 +      if (png_ptr->zstream.avail_out == 0)
  1.1074 +      {
  1.1075 +         png_bytep data = png_ptr->zbuffer_list->output;
  1.1076 +         uInt size = png_ptr->zbuffer_size;
  1.1077 +
  1.1078 +         /* Write an IDAT containing the data then reset the buffer.  The
  1.1079 +          * first IDAT may need deflate header optimization.
  1.1080 +          */
  1.1081 +#        ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
  1.1082 +            if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
  1.1083 +               png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
  1.1084 +               optimize_cmf(data, png_image_size(png_ptr));
  1.1085 +#        endif
  1.1086 +
  1.1087 +#        ifdef PNG_WRITE_APNG_SUPPORTED
  1.1088 +         if (png_ptr->num_frames_written == 0)
  1.1089 +#        endif
  1.1090 +         png_write_complete_chunk(png_ptr, png_IDAT, data, size);
  1.1091 +#        ifdef PNG_WRITE_APNG_SUPPORTED
  1.1092 +         else
  1.1093 +            png_write_fdAT(png_ptr, data, size);
  1.1094 +#        endif /* PNG_WRITE_APNG_SUPPORTED */
  1.1095 +
  1.1096 +         png_ptr->mode |= PNG_HAVE_IDAT;
  1.1097 +
  1.1098 +         png_ptr->zstream.next_out = data;
  1.1099 +         png_ptr->zstream.avail_out = size;
  1.1100 +
  1.1101 +         /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with
  1.1102 +          * the same flush parameter until it has finished output, for NO_FLUSH
  1.1103 +          * it doesn't matter.
  1.1104 +          */
  1.1105 +         if (ret == Z_OK && flush != Z_NO_FLUSH)
  1.1106 +            continue;
  1.1107 +      }
  1.1108 +
  1.1109 +      /* The order of these checks doesn't matter much; it just effect which
  1.1110 +       * possible error might be detected if multiple things go wrong at once.
  1.1111 +       */
  1.1112 +      if (ret == Z_OK) /* most likely return code! */
  1.1113 +      {
  1.1114 +         /* If all the input has been consumed then just return.  If Z_FINISH
  1.1115 +          * was used as the flush parameter something has gone wrong if we get
  1.1116 +          * here.
  1.1117 +          */
  1.1118 +         if (input_len == 0)
  1.1119 +         {
  1.1120 +            if (flush == Z_FINISH)
  1.1121 +               png_error(png_ptr, "Z_OK on Z_FINISH with output space");
  1.1122 +
  1.1123 +            return;
  1.1124 +         }
  1.1125 +      }
  1.1126 +
  1.1127 +      else if (ret == Z_STREAM_END && flush == Z_FINISH)
  1.1128 +      {
  1.1129 +         /* This is the end of the IDAT data; any pending output must be
  1.1130 +          * flushed.  For small PNG files we may still be at the beginning.
  1.1131 +          */
  1.1132 +         png_bytep data = png_ptr->zbuffer_list->output;
  1.1133 +         uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out;
  1.1134 +
  1.1135 +#        ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
  1.1136 +            if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
  1.1137 +               png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
  1.1138 +               optimize_cmf(data, png_image_size(png_ptr));
  1.1139 +#        endif
  1.1140 +
  1.1141 +#        ifdef PNG_WRITE_APNG_SUPPORTED
  1.1142 +         if (png_ptr->num_frames_written == 0)
  1.1143 +#        endif
  1.1144 +         png_write_complete_chunk(png_ptr, png_IDAT, data, size);
  1.1145 +#        ifdef PNG_WRITE_APNG_SUPPORTED
  1.1146 +         else
  1.1147 +            png_write_fdAT(png_ptr, data, size);
  1.1148 +#        endif /* PNG_WRITE_APNG_SUPPORTED */
  1.1149 +
  1.1150 +         png_ptr->zstream.avail_out = 0;
  1.1151 +         png_ptr->zstream.next_out = NULL;
  1.1152 +         png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
  1.1153 +
  1.1154 +         png_ptr->zowner = 0; /* Release the stream */
  1.1155 +         return;
  1.1156 +      }
  1.1157 +
  1.1158 +      else
  1.1159 +      {
  1.1160 +         /* This is an error condition. */
  1.1161 +         png_zstream_error(png_ptr, ret);
  1.1162 +         png_error(png_ptr, png_ptr->zstream.msg);
  1.1163 +      }
  1.1164 +   }
  1.1165 +}
  1.1166 +
  1.1167 +/* Write an IEND chunk */
  1.1168 +void /* PRIVATE */
  1.1169 +png_write_IEND(png_structrp png_ptr)
  1.1170 +{
  1.1171 +   png_debug(1, "in png_write_IEND");
  1.1172 +
  1.1173 +   png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0);
  1.1174 +   png_ptr->mode |= PNG_HAVE_IEND;
  1.1175 +}
  1.1176 +
  1.1177 +#ifdef PNG_WRITE_gAMA_SUPPORTED
  1.1178 +/* Write a gAMA chunk */
  1.1179 +void /* PRIVATE */
  1.1180 +png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
  1.1181 +{
  1.1182 +   png_byte buf[4];
  1.1183 +
  1.1184 +   png_debug(1, "in png_write_gAMA");
  1.1185 +
  1.1186 +   /* file_gamma is saved in 1/100,000ths */
  1.1187 +   png_save_uint_32(buf, (png_uint_32)file_gamma);
  1.1188 +   png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
  1.1189 +}
  1.1190 +#endif
  1.1191 +
  1.1192 +#ifdef PNG_WRITE_sRGB_SUPPORTED
  1.1193 +/* Write a sRGB chunk */
  1.1194 +void /* PRIVATE */
  1.1195 +png_write_sRGB(png_structrp png_ptr, int srgb_intent)
  1.1196 +{
  1.1197 +   png_byte buf[1];
  1.1198 +
  1.1199 +   png_debug(1, "in png_write_sRGB");
  1.1200 +
  1.1201 +   if (srgb_intent >= PNG_sRGB_INTENT_LAST)
  1.1202 +      png_warning(png_ptr,
  1.1203 +          "Invalid sRGB rendering intent specified");
  1.1204 +
  1.1205 +   buf[0]=(png_byte)srgb_intent;
  1.1206 +   png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1);
  1.1207 +}
  1.1208 +#endif
  1.1209 +
  1.1210 +#ifdef PNG_WRITE_iCCP_SUPPORTED
  1.1211 +/* Write an iCCP chunk */
  1.1212 +void /* PRIVATE */
  1.1213 +png_write_iCCP(png_structrp png_ptr, png_const_charp name,
  1.1214 +    png_const_bytep profile)
  1.1215 +{
  1.1216 +   png_uint_32 name_len;
  1.1217 +   png_uint_32 profile_len;
  1.1218 +   png_byte new_name[81]; /* 1 byte for the compression byte */
  1.1219 +   compression_state comp;
  1.1220 +
  1.1221 +   png_debug(1, "in png_write_iCCP");
  1.1222 +
  1.1223 +   /* These are all internal problems: the profile should have been checked
  1.1224 +    * before when it was stored.
  1.1225 +    */
  1.1226 +   if (profile == NULL)
  1.1227 +      png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */
  1.1228 +
  1.1229 +   profile_len = png_get_uint_32(profile);
  1.1230 +
  1.1231 +   if (profile_len < 132)
  1.1232 +      png_error(png_ptr, "ICC profile too short");
  1.1233 +
  1.1234 +   if (profile_len & 0x03)
  1.1235 +      png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
  1.1236 +
  1.1237 +   {
  1.1238 +      png_uint_32 embedded_profile_len = png_get_uint_32(profile);
  1.1239 +
  1.1240 +      if (profile_len != embedded_profile_len)
  1.1241 +         png_error(png_ptr, "Profile length does not match profile");
  1.1242 +   }
  1.1243 +
  1.1244 +   name_len = png_check_keyword(png_ptr, name, new_name);
  1.1245 +
  1.1246 +   if (name_len == 0)
  1.1247 +      png_error(png_ptr, "iCCP: invalid keyword");
  1.1248 +
  1.1249 +   new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE;
  1.1250 +
  1.1251 +   /* Make sure we include the NULL after the name and the compression type */
  1.1252 +   ++name_len;
  1.1253 +
  1.1254 +   png_text_compress_init(&comp, profile, profile_len);
  1.1255 +
  1.1256 +   /* Allow for keyword terminator and compression byte */
  1.1257 +   if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK)
  1.1258 +      png_error(png_ptr, png_ptr->zstream.msg);
  1.1259 +
  1.1260 +   png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);
  1.1261 +
  1.1262 +   png_write_chunk_data(png_ptr, new_name, name_len);
  1.1263 +
  1.1264 +   png_write_compressed_data_out(png_ptr, &comp);
  1.1265 +
  1.1266 +   png_write_chunk_end(png_ptr);
  1.1267 +}
  1.1268 +#endif
  1.1269 +
  1.1270 +#ifdef PNG_WRITE_sPLT_SUPPORTED
  1.1271 +/* Write a sPLT chunk */
  1.1272 +void /* PRIVATE */
  1.1273 +png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
  1.1274 +{
  1.1275 +   png_uint_32 name_len;
  1.1276 +   png_byte new_name[80];
  1.1277 +   png_byte entrybuf[10];
  1.1278 +   png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
  1.1279 +   png_size_t palette_size = entry_size * spalette->nentries;
  1.1280 +   png_sPLT_entryp ep;
  1.1281 +#ifndef PNG_POINTER_INDEXING_SUPPORTED
  1.1282 +   int i;
  1.1283 +#endif
  1.1284 +
  1.1285 +   png_debug(1, "in png_write_sPLT");
  1.1286 +
  1.1287 +   name_len = png_check_keyword(png_ptr, spalette->name, new_name);
  1.1288 +
  1.1289 +   if (name_len == 0)
  1.1290 +      png_error(png_ptr, "sPLT: invalid keyword");
  1.1291 +
  1.1292 +   /* Make sure we include the NULL after the name */
  1.1293 +   png_write_chunk_header(png_ptr, png_sPLT,
  1.1294 +       (png_uint_32)(name_len + 2 + palette_size));
  1.1295 +
  1.1296 +   png_write_chunk_data(png_ptr, (png_bytep)new_name,
  1.1297 +       (png_size_t)(name_len + 1));
  1.1298 +
  1.1299 +   png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1);
  1.1300 +
  1.1301 +   /* Loop through each palette entry, writing appropriately */
  1.1302 +#ifdef PNG_POINTER_INDEXING_SUPPORTED
  1.1303 +   for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
  1.1304 +   {
  1.1305 +      if (spalette->depth == 8)
  1.1306 +      {
  1.1307 +         entrybuf[0] = (png_byte)ep->red;
  1.1308 +         entrybuf[1] = (png_byte)ep->green;
  1.1309 +         entrybuf[2] = (png_byte)ep->blue;
  1.1310 +         entrybuf[3] = (png_byte)ep->alpha;
  1.1311 +         png_save_uint_16(entrybuf + 4, ep->frequency);
  1.1312 +      }
  1.1313 +
  1.1314 +      else
  1.1315 +      {
  1.1316 +         png_save_uint_16(entrybuf + 0, ep->red);
  1.1317 +         png_save_uint_16(entrybuf + 2, ep->green);
  1.1318 +         png_save_uint_16(entrybuf + 4, ep->blue);
  1.1319 +         png_save_uint_16(entrybuf + 6, ep->alpha);
  1.1320 +         png_save_uint_16(entrybuf + 8, ep->frequency);
  1.1321 +      }
  1.1322 +
  1.1323 +      png_write_chunk_data(png_ptr, entrybuf, entry_size);
  1.1324 +   }
  1.1325 +#else
  1.1326 +   ep=spalette->entries;
  1.1327 +   for (i = 0; i>spalette->nentries; i++)
  1.1328 +   {
  1.1329 +      if (spalette->depth == 8)
  1.1330 +      {
  1.1331 +         entrybuf[0] = (png_byte)ep[i].red;
  1.1332 +         entrybuf[1] = (png_byte)ep[i].green;
  1.1333 +         entrybuf[2] = (png_byte)ep[i].blue;
  1.1334 +         entrybuf[3] = (png_byte)ep[i].alpha;
  1.1335 +         png_save_uint_16(entrybuf + 4, ep[i].frequency);
  1.1336 +      }
  1.1337 +
  1.1338 +      else
  1.1339 +      {
  1.1340 +         png_save_uint_16(entrybuf + 0, ep[i].red);
  1.1341 +         png_save_uint_16(entrybuf + 2, ep[i].green);
  1.1342 +         png_save_uint_16(entrybuf + 4, ep[i].blue);
  1.1343 +         png_save_uint_16(entrybuf + 6, ep[i].alpha);
  1.1344 +         png_save_uint_16(entrybuf + 8, ep[i].frequency);
  1.1345 +      }
  1.1346 +
  1.1347 +      png_write_chunk_data(png_ptr, entrybuf, entry_size);
  1.1348 +   }
  1.1349 +#endif
  1.1350 +
  1.1351 +   png_write_chunk_end(png_ptr);
  1.1352 +}
  1.1353 +#endif
  1.1354 +
  1.1355 +#ifdef PNG_WRITE_sBIT_SUPPORTED
  1.1356 +/* Write the sBIT chunk */
  1.1357 +void /* PRIVATE */
  1.1358 +png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
  1.1359 +{
  1.1360 +   png_byte buf[4];
  1.1361 +   png_size_t size;
  1.1362 +
  1.1363 +   png_debug(1, "in png_write_sBIT");
  1.1364 +
  1.1365 +   /* Make sure we don't depend upon the order of PNG_COLOR_8 */
  1.1366 +   if (color_type & PNG_COLOR_MASK_COLOR)
  1.1367 +   {
  1.1368 +      png_byte maxbits;
  1.1369 +
  1.1370 +      maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
  1.1371 +          png_ptr->usr_bit_depth);
  1.1372 +
  1.1373 +      if (sbit->red == 0 || sbit->red > maxbits ||
  1.1374 +          sbit->green == 0 || sbit->green > maxbits ||
  1.1375 +          sbit->blue == 0 || sbit->blue > maxbits)
  1.1376 +      {
  1.1377 +         png_warning(png_ptr, "Invalid sBIT depth specified");
  1.1378 +         return;
  1.1379 +      }
  1.1380 +
  1.1381 +      buf[0] = sbit->red;
  1.1382 +      buf[1] = sbit->green;
  1.1383 +      buf[2] = sbit->blue;
  1.1384 +      size = 3;
  1.1385 +   }
  1.1386 +
  1.1387 +   else
  1.1388 +   {
  1.1389 +      if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
  1.1390 +      {
  1.1391 +         png_warning(png_ptr, "Invalid sBIT depth specified");
  1.1392 +         return;
  1.1393 +      }
  1.1394 +
  1.1395 +      buf[0] = sbit->gray;
  1.1396 +      size = 1;
  1.1397 +   }
  1.1398 +
  1.1399 +   if (color_type & PNG_COLOR_MASK_ALPHA)
  1.1400 +   {
  1.1401 +      if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
  1.1402 +      {
  1.1403 +         png_warning(png_ptr, "Invalid sBIT depth specified");
  1.1404 +         return;
  1.1405 +      }
  1.1406 +
  1.1407 +      buf[size++] = sbit->alpha;
  1.1408 +   }
  1.1409 +
  1.1410 +   png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
  1.1411 +}
  1.1412 +#endif
  1.1413 +
  1.1414 +#ifdef PNG_WRITE_cHRM_SUPPORTED
  1.1415 +/* Write the cHRM chunk */
  1.1416 +void /* PRIVATE */
  1.1417 +png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy)
  1.1418 +{
  1.1419 +   png_byte buf[32];
  1.1420 +
  1.1421 +   png_debug(1, "in png_write_cHRM");
  1.1422 +
  1.1423 +   /* Each value is saved in 1/100,000ths */
  1.1424 +   png_save_int_32(buf,      xy->whitex);
  1.1425 +   png_save_int_32(buf +  4, xy->whitey);
  1.1426 +
  1.1427 +   png_save_int_32(buf +  8, xy->redx);
  1.1428 +   png_save_int_32(buf + 12, xy->redy);
  1.1429 +
  1.1430 +   png_save_int_32(buf + 16, xy->greenx);
  1.1431 +   png_save_int_32(buf + 20, xy->greeny);
  1.1432 +
  1.1433 +   png_save_int_32(buf + 24, xy->bluex);
  1.1434 +   png_save_int_32(buf + 28, xy->bluey);
  1.1435 +
  1.1436 +   png_write_complete_chunk(png_ptr, png_cHRM, buf, 32);
  1.1437 +}
  1.1438 +#endif
  1.1439 +
  1.1440 +#ifdef PNG_WRITE_tRNS_SUPPORTED
  1.1441 +/* Write the tRNS chunk */
  1.1442 +void /* PRIVATE */
  1.1443 +png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
  1.1444 +    png_const_color_16p tran, int num_trans, int color_type)
  1.1445 +{
  1.1446 +   png_byte buf[6];
  1.1447 +
  1.1448 +   png_debug(1, "in png_write_tRNS");
  1.1449 +
  1.1450 +   if (color_type == PNG_COLOR_TYPE_PALETTE)
  1.1451 +   {
  1.1452 +      if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
  1.1453 +      {
  1.1454 +         png_app_warning(png_ptr,
  1.1455 +             "Invalid number of transparent colors specified");
  1.1456 +         return;
  1.1457 +      }
  1.1458 +
  1.1459 +      /* Write the chunk out as it is */
  1.1460 +      png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
  1.1461 +         (png_size_t)num_trans);
  1.1462 +   }
  1.1463 +
  1.1464 +   else if (color_type == PNG_COLOR_TYPE_GRAY)
  1.1465 +   {
  1.1466 +      /* One 16 bit value */
  1.1467 +      if (tran->gray >= (1 << png_ptr->bit_depth))
  1.1468 +      {
  1.1469 +         png_app_warning(png_ptr,
  1.1470 +             "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
  1.1471 +
  1.1472 +         return;
  1.1473 +      }
  1.1474 +
  1.1475 +      png_save_uint_16(buf, tran->gray);
  1.1476 +      png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
  1.1477 +   }
  1.1478 +
  1.1479 +   else if (color_type == PNG_COLOR_TYPE_RGB)
  1.1480 +   {
  1.1481 +      /* Three 16 bit values */
  1.1482 +      png_save_uint_16(buf, tran->red);
  1.1483 +      png_save_uint_16(buf + 2, tran->green);
  1.1484 +      png_save_uint_16(buf + 4, tran->blue);
  1.1485 +#ifdef PNG_WRITE_16BIT_SUPPORTED
  1.1486 +      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
  1.1487 +#else
  1.1488 +      if (buf[0] | buf[2] | buf[4])
  1.1489 +#endif
  1.1490 +      {
  1.1491 +         png_app_warning(png_ptr,
  1.1492 +           "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
  1.1493 +         return;
  1.1494 +      }
  1.1495 +
  1.1496 +      png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
  1.1497 +   }
  1.1498 +
  1.1499 +   else
  1.1500 +   {
  1.1501 +      png_app_warning(png_ptr, "Can't write tRNS with an alpha channel");
  1.1502 +   }
  1.1503 +}
  1.1504 +#endif
  1.1505 +
  1.1506 +#ifdef PNG_WRITE_bKGD_SUPPORTED
  1.1507 +/* Write the background chunk */
  1.1508 +void /* PRIVATE */
  1.1509 +png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
  1.1510 +{
  1.1511 +   png_byte buf[6];
  1.1512 +
  1.1513 +   png_debug(1, "in png_write_bKGD");
  1.1514 +
  1.1515 +   if (color_type == PNG_COLOR_TYPE_PALETTE)
  1.1516 +   {
  1.1517 +      if (
  1.1518 +#ifdef PNG_MNG_FEATURES_SUPPORTED
  1.1519 +          (png_ptr->num_palette ||
  1.1520 +          (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
  1.1521 +#endif
  1.1522 +         back->index >= png_ptr->num_palette)
  1.1523 +      {
  1.1524 +         png_warning(png_ptr, "Invalid background palette index");
  1.1525 +         return;
  1.1526 +      }
  1.1527 +
  1.1528 +      buf[0] = back->index;
  1.1529 +      png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
  1.1530 +   }
  1.1531 +
  1.1532 +   else if (color_type & PNG_COLOR_MASK_COLOR)
  1.1533 +   {
  1.1534 +      png_save_uint_16(buf, back->red);
  1.1535 +      png_save_uint_16(buf + 2, back->green);
  1.1536 +      png_save_uint_16(buf + 4, back->blue);
  1.1537 +#ifdef PNG_WRITE_16BIT_SUPPORTED
  1.1538 +      if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
  1.1539 +#else
  1.1540 +      if (buf[0] | buf[2] | buf[4])
  1.1541 +#endif
  1.1542 +      {
  1.1543 +         png_warning(png_ptr,
  1.1544 +             "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
  1.1545 +
  1.1546 +         return;
  1.1547 +      }
  1.1548 +
  1.1549 +      png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
  1.1550 +   }
  1.1551 +
  1.1552 +   else
  1.1553 +   {
  1.1554 +      if (back->gray >= (1 << png_ptr->bit_depth))
  1.1555 +      {
  1.1556 +         png_warning(png_ptr,
  1.1557 +             "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
  1.1558 +
  1.1559 +         return;
  1.1560 +      }
  1.1561 +
  1.1562 +      png_save_uint_16(buf, back->gray);
  1.1563 +      png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
  1.1564 +   }
  1.1565 +}
  1.1566 +#endif
  1.1567 +
  1.1568 +#ifdef PNG_WRITE_hIST_SUPPORTED
  1.1569 +/* Write the histogram */
  1.1570 +void /* PRIVATE */
  1.1571 +png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
  1.1572 +{
  1.1573 +   int i;
  1.1574 +   png_byte buf[3];
  1.1575 +
  1.1576 +   png_debug(1, "in png_write_hIST");
  1.1577 +
  1.1578 +   if (num_hist > (int)png_ptr->num_palette)
  1.1579 +   {
  1.1580 +      png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
  1.1581 +          png_ptr->num_palette);
  1.1582 +
  1.1583 +      png_warning(png_ptr, "Invalid number of histogram entries specified");
  1.1584 +      return;
  1.1585 +   }
  1.1586 +
  1.1587 +   png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
  1.1588 +
  1.1589 +   for (i = 0; i < num_hist; i++)
  1.1590 +   {
  1.1591 +      png_save_uint_16(buf, hist[i]);
  1.1592 +      png_write_chunk_data(png_ptr, buf, (png_size_t)2);
  1.1593 +   }
  1.1594 +
  1.1595 +   png_write_chunk_end(png_ptr);
  1.1596 +}
  1.1597 +#endif
  1.1598 +
  1.1599 +#ifdef PNG_WRITE_tEXt_SUPPORTED
  1.1600 +/* Write a tEXt chunk */
  1.1601 +void /* PRIVATE */
  1.1602 +png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
  1.1603 +    png_size_t text_len)
  1.1604 +{
  1.1605 +   png_uint_32 key_len;
  1.1606 +   png_byte new_key[80];
  1.1607 +
  1.1608 +   png_debug(1, "in png_write_tEXt");
  1.1609 +
  1.1610 +   key_len = png_check_keyword(png_ptr, key, new_key);
  1.1611 +
  1.1612 +   if (key_len == 0)
  1.1613 +      png_error(png_ptr, "tEXt: invalid keyword");
  1.1614 +
  1.1615 +   if (text == NULL || *text == '\0')
  1.1616 +      text_len = 0;
  1.1617 +
  1.1618 +   else
  1.1619 +      text_len = strlen(text);
  1.1620 +
  1.1621 +   if (text_len > PNG_UINT_31_MAX - (key_len+1))
  1.1622 +      png_error(png_ptr, "tEXt: text too long");
  1.1623 +
  1.1624 +   /* Make sure we include the 0 after the key */
  1.1625 +   png_write_chunk_header(png_ptr, png_tEXt,
  1.1626 +       (png_uint_32)/*checked above*/(key_len + text_len + 1));
  1.1627 +   /*
  1.1628 +    * We leave it to the application to meet PNG-1.0 requirements on the
  1.1629 +    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
  1.1630 +    * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
  1.1631 +    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
  1.1632 +    */
  1.1633 +   png_write_chunk_data(png_ptr, new_key, key_len + 1);
  1.1634 +
  1.1635 +   if (text_len)
  1.1636 +      png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len);
  1.1637 +
  1.1638 +   png_write_chunk_end(png_ptr);
  1.1639 +}
  1.1640 +#endif
  1.1641 +
  1.1642 +#ifdef PNG_WRITE_zTXt_SUPPORTED
  1.1643 +/* Write a compressed text chunk */
  1.1644 +void /* PRIVATE */
  1.1645 +png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
  1.1646 +    png_size_t text_len, int compression)
  1.1647 +{
  1.1648 +   png_uint_32 key_len;
  1.1649 +   png_byte new_key[81];
  1.1650 +   compression_state comp;
  1.1651 +
  1.1652 +   png_debug(1, "in png_write_zTXt");
  1.1653 +   PNG_UNUSED(text_len) /* Always use strlen */
  1.1654 +
  1.1655 +   if (compression == PNG_TEXT_COMPRESSION_NONE)
  1.1656 +   {
  1.1657 +      png_write_tEXt(png_ptr, key, text, 0);
  1.1658 +      return;
  1.1659 +   }
  1.1660 +
  1.1661 +   if (compression != PNG_TEXT_COMPRESSION_zTXt)
  1.1662 +      png_error(png_ptr, "zTXt: invalid compression type");
  1.1663 +
  1.1664 +   key_len = png_check_keyword(png_ptr, key, new_key);
  1.1665 +
  1.1666 +   if (key_len == 0)
  1.1667 +      png_error(png_ptr, "zTXt: invalid keyword");
  1.1668 +
  1.1669 +   /* Add the compression method and 1 for the keyword separator. */
  1.1670 +   new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
  1.1671 +   ++key_len;
  1.1672 +
  1.1673 +   /* Compute the compressed data; do it now for the length */
  1.1674 +   png_text_compress_init(&comp, (png_const_bytep)text,
  1.1675 +      text == NULL ? 0 : strlen(text));
  1.1676 +
  1.1677 +   if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
  1.1678 +      png_error(png_ptr, png_ptr->zstream.msg);
  1.1679 +
  1.1680 +   /* Write start of chunk */
  1.1681 +   png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
  1.1682 +
  1.1683 +   /* Write key */
  1.1684 +   png_write_chunk_data(png_ptr, new_key, key_len);
  1.1685 +
  1.1686 +   /* Write the compressed data */
  1.1687 +   png_write_compressed_data_out(png_ptr, &comp);
  1.1688 +
  1.1689 +   /* Close the chunk */
  1.1690 +   png_write_chunk_end(png_ptr);
  1.1691 +}
  1.1692 +#endif
  1.1693 +
  1.1694 +#ifdef PNG_WRITE_iTXt_SUPPORTED
  1.1695 +/* Write an iTXt chunk */
  1.1696 +void /* PRIVATE */
  1.1697 +png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
  1.1698 +    png_const_charp lang, png_const_charp lang_key, png_const_charp text)
  1.1699 +{
  1.1700 +   png_uint_32 key_len, prefix_len;
  1.1701 +   png_size_t lang_len, lang_key_len;
  1.1702 +   png_byte new_key[82];
  1.1703 +   compression_state comp;
  1.1704 +
  1.1705 +   png_debug(1, "in png_write_iTXt");
  1.1706 +
  1.1707 +   key_len = png_check_keyword(png_ptr, key, new_key);
  1.1708 +
  1.1709 +   if (key_len == 0)
  1.1710 +      png_error(png_ptr, "iTXt: invalid keyword");
  1.1711 +
  1.1712 +   /* Set the compression flag */
  1.1713 +   switch (compression)
  1.1714 +   {
  1.1715 +      case PNG_ITXT_COMPRESSION_NONE:
  1.1716 +      case PNG_TEXT_COMPRESSION_NONE:
  1.1717 +         compression = new_key[++key_len] = 0; /* no compression */
  1.1718 +         break;
  1.1719 +
  1.1720 +      case PNG_TEXT_COMPRESSION_zTXt:
  1.1721 +      case PNG_ITXT_COMPRESSION_zTXt:
  1.1722 +         compression = new_key[++key_len] = 1; /* compressed */
  1.1723 +         break;
  1.1724 +
  1.1725 +      default:
  1.1726 +         png_error(png_ptr, "iTXt: invalid compression");
  1.1727 +   }
  1.1728 +
  1.1729 +   new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
  1.1730 +   ++key_len; /* for the keywod separator */
  1.1731 +
  1.1732 +   /* We leave it to the application to meet PNG-1.0 requirements on the
  1.1733 +    * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
  1.1734 +    * any non-Latin-1 characters except for NEWLINE.  ISO PNG, however,
  1.1735 +    * specifies that the text is UTF-8 and this really doesn't require any
  1.1736 +    * checking.
  1.1737 +    *
  1.1738 +    * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
  1.1739 +    *
  1.1740 +    * TODO: validate the language tag correctly (see the spec.)
  1.1741 +    */
  1.1742 +   if (lang == NULL) lang = ""; /* empty language is valid */
  1.1743 +   lang_len = strlen(lang)+1;
  1.1744 +   if (lang_key == NULL) lang_key = ""; /* may be empty */
  1.1745 +   lang_key_len = strlen(lang_key)+1;
  1.1746 +   if (text == NULL) text = ""; /* may be empty */
  1.1747 +
  1.1748 +   prefix_len = key_len;
  1.1749 +   if (lang_len > PNG_UINT_31_MAX-prefix_len)
  1.1750 +      prefix_len = PNG_UINT_31_MAX;
  1.1751 +   else
  1.1752 +      prefix_len = (png_uint_32)(prefix_len + lang_len);
  1.1753 +
  1.1754 +   if (lang_key_len > PNG_UINT_31_MAX-prefix_len)
  1.1755 +      prefix_len = PNG_UINT_31_MAX;
  1.1756 +   else
  1.1757 +      prefix_len = (png_uint_32)(prefix_len + lang_key_len);
  1.1758 +
  1.1759 +   png_text_compress_init(&comp, (png_const_bytep)text, strlen(text));
  1.1760 +
  1.1761 +   if (compression)
  1.1762 +   {
  1.1763 +      if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
  1.1764 +         png_error(png_ptr, png_ptr->zstream.msg);
  1.1765 +   }
  1.1766 +
  1.1767 +   else
  1.1768 +   {
  1.1769 +      if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
  1.1770 +         png_error(png_ptr, "iTXt: uncompressed text too long");
  1.1771 +
  1.1772 +      /* So the string will fit in a chunk: */
  1.1773 +      comp.output_len = (png_uint_32)/*SAFE*/comp.input_len;
  1.1774 +   }
  1.1775 +
  1.1776 +   png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);
  1.1777 +
  1.1778 +   png_write_chunk_data(png_ptr, new_key, key_len);
  1.1779 +
  1.1780 +   png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len);
  1.1781 +
  1.1782 +   png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len);
  1.1783 +
  1.1784 +   if (compression)
  1.1785 +      png_write_compressed_data_out(png_ptr, &comp);
  1.1786 +
  1.1787 +   else
  1.1788 +      png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.input_len);
  1.1789 +
  1.1790 +   png_write_chunk_end(png_ptr);
  1.1791 +}
  1.1792 +#endif
  1.1793 +
  1.1794 +#ifdef PNG_WRITE_oFFs_SUPPORTED
  1.1795 +/* Write the oFFs chunk */
  1.1796 +void /* PRIVATE */
  1.1797 +png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
  1.1798 +    int unit_type)
  1.1799 +{
  1.1800 +   png_byte buf[9];
  1.1801 +
  1.1802 +   png_debug(1, "in png_write_oFFs");
  1.1803 +
  1.1804 +   if (unit_type >= PNG_OFFSET_LAST)
  1.1805 +      png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
  1.1806 +
  1.1807 +   png_save_int_32(buf, x_offset);
  1.1808 +   png_save_int_32(buf + 4, y_offset);
  1.1809 +   buf[8] = (png_byte)unit_type;
  1.1810 +
  1.1811 +   png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9);
  1.1812 +}
  1.1813 +#endif
  1.1814 +#ifdef PNG_WRITE_pCAL_SUPPORTED
  1.1815 +/* Write the pCAL chunk (described in the PNG extensions document) */
  1.1816 +void /* PRIVATE */
  1.1817 +png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
  1.1818 +    png_int_32 X1, int type, int nparams, png_const_charp units,
  1.1819 +    png_charpp params)
  1.1820 +{
  1.1821 +   png_uint_32 purpose_len;
  1.1822 +   png_size_t units_len, total_len;
  1.1823 +   png_size_tp params_len;
  1.1824 +   png_byte buf[10];
  1.1825 +   png_byte new_purpose[80];
  1.1826 +   int i;
  1.1827 +
  1.1828 +   png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
  1.1829 +
  1.1830 +   if (type >= PNG_EQUATION_LAST)
  1.1831 +      png_error(png_ptr, "Unrecognized equation type for pCAL chunk");
  1.1832 +
  1.1833 +   purpose_len = png_check_keyword(png_ptr, purpose, new_purpose);
  1.1834 +
  1.1835 +   if (purpose_len == 0)
  1.1836 +      png_error(png_ptr, "pCAL: invalid keyword");
  1.1837 +
  1.1838 +   ++purpose_len; /* terminator */
  1.1839 +
  1.1840 +   png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
  1.1841 +   units_len = strlen(units) + (nparams == 0 ? 0 : 1);
  1.1842 +   png_debug1(3, "pCAL units length = %d", (int)units_len);
  1.1843 +   total_len = purpose_len + units_len + 10;
  1.1844 +
  1.1845 +   params_len = (png_size_tp)png_malloc(png_ptr,
  1.1846 +       (png_alloc_size_t)(nparams * (sizeof (png_size_t))));
  1.1847 +
  1.1848 +   /* Find the length of each parameter, making sure we don't count the
  1.1849 +    * null terminator for the last parameter.
  1.1850 +    */
  1.1851 +   for (i = 0; i < nparams; i++)
  1.1852 +   {
  1.1853 +      params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
  1.1854 +      png_debug2(3, "pCAL parameter %d length = %lu", i,
  1.1855 +          (unsigned long)params_len[i]);
  1.1856 +      total_len += params_len[i];
  1.1857 +   }
  1.1858 +
  1.1859 +   png_debug1(3, "pCAL total length = %d", (int)total_len);
  1.1860 +   png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
  1.1861 +   png_write_chunk_data(png_ptr, new_purpose, purpose_len);
  1.1862 +   png_save_int_32(buf, X0);
  1.1863 +   png_save_int_32(buf + 4, X1);
  1.1864 +   buf[8] = (png_byte)type;
  1.1865 +   buf[9] = (png_byte)nparams;
  1.1866 +   png_write_chunk_data(png_ptr, buf, (png_size_t)10);
  1.1867 +   png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len);
  1.1868 +
  1.1869 +   for (i = 0; i < nparams; i++)
  1.1870 +   {
  1.1871 +      png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
  1.1872 +   }
  1.1873 +
  1.1874 +   png_free(png_ptr, params_len);
  1.1875 +   png_write_chunk_end(png_ptr);
  1.1876 +}
  1.1877 +#endif
  1.1878 +
  1.1879 +#ifdef PNG_WRITE_sCAL_SUPPORTED
  1.1880 +/* Write the sCAL chunk */
  1.1881 +void /* PRIVATE */
  1.1882 +png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
  1.1883 +    png_const_charp height)
  1.1884 +{
  1.1885 +   png_byte buf[64];
  1.1886 +   png_size_t wlen, hlen, total_len;
  1.1887 +
  1.1888 +   png_debug(1, "in png_write_sCAL_s");
  1.1889 +
  1.1890 +   wlen = strlen(width);
  1.1891 +   hlen = strlen(height);
  1.1892 +   total_len = wlen + hlen + 2;
  1.1893 +
  1.1894 +   if (total_len > 64)
  1.1895 +   {
  1.1896 +      png_warning(png_ptr, "Can't write sCAL (buffer too small)");
  1.1897 +      return;
  1.1898 +   }
  1.1899 +
  1.1900 +   buf[0] = (png_byte)unit;
  1.1901 +   memcpy(buf + 1, width, wlen + 1);      /* Append the '\0' here */
  1.1902 +   memcpy(buf + wlen + 2, height, hlen);  /* Do NOT append the '\0' here */
  1.1903 +
  1.1904 +   png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
  1.1905 +   png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
  1.1906 +}
  1.1907 +#endif
  1.1908 +
  1.1909 +#ifdef PNG_WRITE_pHYs_SUPPORTED
  1.1910 +/* Write the pHYs chunk */
  1.1911 +void /* PRIVATE */
  1.1912 +png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
  1.1913 +    png_uint_32 y_pixels_per_unit,
  1.1914 +    int unit_type)
  1.1915 +{
  1.1916 +   png_byte buf[9];
  1.1917 +
  1.1918 +   png_debug(1, "in png_write_pHYs");
  1.1919 +
  1.1920 +   if (unit_type >= PNG_RESOLUTION_LAST)
  1.1921 +      png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
  1.1922 +
  1.1923 +   png_save_uint_32(buf, x_pixels_per_unit);
  1.1924 +   png_save_uint_32(buf + 4, y_pixels_per_unit);
  1.1925 +   buf[8] = (png_byte)unit_type;
  1.1926 +
  1.1927 +   png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
  1.1928 +}
  1.1929 +#endif
  1.1930 +
  1.1931 +#ifdef PNG_WRITE_tIME_SUPPORTED
  1.1932 +/* Write the tIME chunk.  Use either png_convert_from_struct_tm()
  1.1933 + * or png_convert_from_time_t(), or fill in the structure yourself.
  1.1934 + */
  1.1935 +void /* PRIVATE */
  1.1936 +png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
  1.1937 +{
  1.1938 +   png_byte buf[7];
  1.1939 +
  1.1940 +   png_debug(1, "in png_write_tIME");
  1.1941 +
  1.1942 +   if (mod_time->month  > 12 || mod_time->month  < 1 ||
  1.1943 +       mod_time->day    > 31 || mod_time->day    < 1 ||
  1.1944 +       mod_time->hour   > 23 || mod_time->second > 60)
  1.1945 +   {
  1.1946 +      png_warning(png_ptr, "Invalid time specified for tIME chunk");
  1.1947 +      return;
  1.1948 +   }
  1.1949 +
  1.1950 +   png_save_uint_16(buf, mod_time->year);
  1.1951 +   buf[2] = mod_time->month;
  1.1952 +   buf[3] = mod_time->day;
  1.1953 +   buf[4] = mod_time->hour;
  1.1954 +   buf[5] = mod_time->minute;
  1.1955 +   buf[6] = mod_time->second;
  1.1956 +
  1.1957 +   png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
  1.1958 +}
  1.1959 +#endif
  1.1960 +
  1.1961 +#ifdef PNG_WRITE_APNG_SUPPORTED
  1.1962 +void /* PRIVATE */
  1.1963 +png_write_acTL(png_structp png_ptr,
  1.1964 +    png_uint_32 num_frames, png_uint_32 num_plays)
  1.1965 +{
  1.1966 +    png_byte buf[8];
  1.1967 +
  1.1968 +    png_debug(1, "in png_write_acTL");
  1.1969 +
  1.1970 +    png_ptr->num_frames_to_write = num_frames;
  1.1971 +
  1.1972 +    if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN)
  1.1973 +        num_frames--;
  1.1974 +
  1.1975 +    png_save_uint_32(buf, num_frames);
  1.1976 +    png_save_uint_32(buf + 4, num_plays);
  1.1977 +
  1.1978 +    png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8);
  1.1979 +}
  1.1980 +
  1.1981 +void /* PRIVATE */
  1.1982 +png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
  1.1983 +    png_uint_32 x_offset, png_uint_32 y_offset,
  1.1984 +    png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
  1.1985 +    png_byte blend_op)
  1.1986 +{
  1.1987 +    png_byte buf[26];
  1.1988 +
  1.1989 +    png_debug(1, "in png_write_fcTL");
  1.1990 +
  1.1991 +    if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0))
  1.1992 +        png_error(png_ptr, "x and/or y offset for the first frame aren't 0");
  1.1993 +    if (png_ptr->num_frames_written == 0 &&
  1.1994 +        (width != png_ptr->first_frame_width ||
  1.1995 +         height != png_ptr->first_frame_height))
  1.1996 +        png_error(png_ptr, "width and/or height in the first frame's fcTL "
  1.1997 +                           "don't match the ones in IHDR");
  1.1998 +
  1.1999 +    /* more error checking */
  1.2000 +    png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
  1.2001 +                             delay_num, delay_den, dispose_op, blend_op);
  1.2002 +
  1.2003 +    png_save_uint_32(buf, png_ptr->next_seq_num);
  1.2004 +    png_save_uint_32(buf + 4, width);
  1.2005 +    png_save_uint_32(buf + 8, height);
  1.2006 +    png_save_uint_32(buf + 12, x_offset);
  1.2007 +    png_save_uint_32(buf + 16, y_offset);
  1.2008 +    png_save_uint_16(buf + 20, delay_num);
  1.2009 +    png_save_uint_16(buf + 22, delay_den);
  1.2010 +    buf[24] = dispose_op;
  1.2011 +    buf[25] = blend_op;
  1.2012 +
  1.2013 +    png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26);
  1.2014 +
  1.2015 +    png_ptr->next_seq_num++;
  1.2016 +}
  1.2017 +
  1.2018 +void /* PRIVATE */
  1.2019 +png_write_fdAT(png_structp png_ptr,
  1.2020 +    png_const_bytep data, png_size_t length)
  1.2021 +{
  1.2022 +    png_byte buf[4];
  1.2023 +
  1.2024 +    png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length));
  1.2025 +
  1.2026 +    png_save_uint_32(buf, png_ptr->next_seq_num);
  1.2027 +    png_write_chunk_data(png_ptr, buf, 4);
  1.2028 +
  1.2029 +    png_write_chunk_data(png_ptr, data, length);
  1.2030 +
  1.2031 +    png_write_chunk_end(png_ptr);
  1.2032 +
  1.2033 +    png_ptr->next_seq_num++;
  1.2034 +}
  1.2035 +#endif /* PNG_WRITE_APNG_SUPPORTED */
  1.2036 +
  1.2037 +/* Initializes the row writing capability of libpng */
  1.2038 +void /* PRIVATE */
  1.2039 +png_write_start_row(png_structrp png_ptr)
  1.2040 +{
  1.2041 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1.2042 +   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  1.2043 +
  1.2044 +   /* Start of interlace block */
  1.2045 +   static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  1.2046 +
  1.2047 +   /* Offset to next interlace block */
  1.2048 +   static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
  1.2049 +
  1.2050 +   /* Start of interlace block in the y direction */
  1.2051 +   static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
  1.2052 +
  1.2053 +   /* Offset to next interlace block in the y direction */
  1.2054 +   static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
  1.2055 +#endif
  1.2056 +
  1.2057 +   png_alloc_size_t buf_size;
  1.2058 +   int usr_pixel_depth;
  1.2059 +
  1.2060 +   png_debug(1, "in png_write_start_row");
  1.2061 +
  1.2062 +   usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth;
  1.2063 +   buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1;
  1.2064 +
  1.2065 +   /* 1.5.6: added to allow checking in the row write code. */
  1.2066 +   png_ptr->transformed_pixel_depth = png_ptr->pixel_depth;
  1.2067 +   png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
  1.2068 +
  1.2069 +   /* Set up row buffer */
  1.2070 +   png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size);
  1.2071 +
  1.2072 +   png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
  1.2073 +
  1.2074 +#ifdef PNG_WRITE_FILTER_SUPPORTED
  1.2075 +   /* Set up filtering buffer, if using this filter */
  1.2076 +   if (png_ptr->do_filter & PNG_FILTER_SUB)
  1.2077 +   {
  1.2078 +      png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1);
  1.2079 +
  1.2080 +      png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
  1.2081 +   }
  1.2082 +
  1.2083 +   /* We only need to keep the previous row if we are using one of these. */
  1.2084 +   if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
  1.2085 +   {
  1.2086 +      /* Set up previous row buffer */
  1.2087 +      png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size);
  1.2088 +
  1.2089 +      if (png_ptr->do_filter & PNG_FILTER_UP)
  1.2090 +      {
  1.2091 +         png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
  1.2092 +            png_ptr->rowbytes + 1);
  1.2093 +
  1.2094 +         png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
  1.2095 +      }
  1.2096 +
  1.2097 +      if (png_ptr->do_filter & PNG_FILTER_AVG)
  1.2098 +      {
  1.2099 +         png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
  1.2100 +             png_ptr->rowbytes + 1);
  1.2101 +
  1.2102 +         png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
  1.2103 +      }
  1.2104 +
  1.2105 +      if (png_ptr->do_filter & PNG_FILTER_PAETH)
  1.2106 +      {
  1.2107 +         png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
  1.2108 +             png_ptr->rowbytes + 1);
  1.2109 +
  1.2110 +         png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
  1.2111 +      }
  1.2112 +   }
  1.2113 +#endif /* PNG_WRITE_FILTER_SUPPORTED */
  1.2114 +
  1.2115 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1.2116 +   /* If interlaced, we need to set up width and height of pass */
  1.2117 +   if (png_ptr->interlaced)
  1.2118 +   {
  1.2119 +      if (!(png_ptr->transformations & PNG_INTERLACE))
  1.2120 +      {
  1.2121 +         png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
  1.2122 +             png_pass_ystart[0]) / png_pass_yinc[0];
  1.2123 +
  1.2124 +         png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
  1.2125 +             png_pass_start[0]) / png_pass_inc[0];
  1.2126 +      }
  1.2127 +
  1.2128 +      else
  1.2129 +      {
  1.2130 +         png_ptr->num_rows = png_ptr->height;
  1.2131 +         png_ptr->usr_width = png_ptr->width;
  1.2132 +      }
  1.2133 +   }
  1.2134 +
  1.2135 +   else
  1.2136 +#endif
  1.2137 +   {
  1.2138 +      png_ptr->num_rows = png_ptr->height;
  1.2139 +      png_ptr->usr_width = png_ptr->width;
  1.2140 +   }
  1.2141 +}
  1.2142 +
  1.2143 +/* Internal use only.  Called when finished processing a row of data. */
  1.2144 +void /* PRIVATE */
  1.2145 +png_write_finish_row(png_structrp png_ptr)
  1.2146 +{
  1.2147 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1.2148 +   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  1.2149 +
  1.2150 +   /* Start of interlace block */
  1.2151 +   static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  1.2152 +
  1.2153 +   /* Offset to next interlace block */
  1.2154 +   static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
  1.2155 +
  1.2156 +   /* Start of interlace block in the y direction */
  1.2157 +   static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
  1.2158 +
  1.2159 +   /* Offset to next interlace block in the y direction */
  1.2160 +   static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
  1.2161 +#endif
  1.2162 +
  1.2163 +   png_debug(1, "in png_write_finish_row");
  1.2164 +
  1.2165 +   /* Next row */
  1.2166 +   png_ptr->row_number++;
  1.2167 +
  1.2168 +   /* See if we are done */
  1.2169 +   if (png_ptr->row_number < png_ptr->num_rows)
  1.2170 +      return;
  1.2171 +
  1.2172 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1.2173 +   /* If interlaced, go to next pass */
  1.2174 +   if (png_ptr->interlaced)
  1.2175 +   {
  1.2176 +      png_ptr->row_number = 0;
  1.2177 +      if (png_ptr->transformations & PNG_INTERLACE)
  1.2178 +      {
  1.2179 +         png_ptr->pass++;
  1.2180 +      }
  1.2181 +
  1.2182 +      else
  1.2183 +      {
  1.2184 +         /* Loop until we find a non-zero width or height pass */
  1.2185 +         do
  1.2186 +         {
  1.2187 +            png_ptr->pass++;
  1.2188 +
  1.2189 +            if (png_ptr->pass >= 7)
  1.2190 +               break;
  1.2191 +
  1.2192 +            png_ptr->usr_width = (png_ptr->width +
  1.2193 +                png_pass_inc[png_ptr->pass] - 1 -
  1.2194 +                png_pass_start[png_ptr->pass]) /
  1.2195 +                png_pass_inc[png_ptr->pass];
  1.2196 +
  1.2197 +            png_ptr->num_rows = (png_ptr->height +
  1.2198 +                png_pass_yinc[png_ptr->pass] - 1 -
  1.2199 +                png_pass_ystart[png_ptr->pass]) /
  1.2200 +                png_pass_yinc[png_ptr->pass];
  1.2201 +
  1.2202 +            if (png_ptr->transformations & PNG_INTERLACE)
  1.2203 +               break;
  1.2204 +
  1.2205 +         } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
  1.2206 +
  1.2207 +      }
  1.2208 +
  1.2209 +      /* Reset the row above the image for the next pass */
  1.2210 +      if (png_ptr->pass < 7)
  1.2211 +      {
  1.2212 +         if (png_ptr->prev_row != NULL)
  1.2213 +            memset(png_ptr->prev_row, 0,
  1.2214 +                (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
  1.2215 +                png_ptr->usr_bit_depth, png_ptr->width)) + 1);
  1.2216 +
  1.2217 +         return;
  1.2218 +      }
  1.2219 +   }
  1.2220 +#endif
  1.2221 +
  1.2222 +   /* If we get here, we've just written the last row, so we need
  1.2223 +      to flush the compressor */
  1.2224 +   png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH);
  1.2225 +}
  1.2226 +
  1.2227 +#ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1.2228 +/* Pick out the correct pixels for the interlace pass.
  1.2229 + * The basic idea here is to go through the row with a source
  1.2230 + * pointer and a destination pointer (sp and dp), and copy the
  1.2231 + * correct pixels for the pass.  As the row gets compacted,
  1.2232 + * sp will always be >= dp, so we should never overwrite anything.
  1.2233 + * See the default: case for the easiest code to understand.
  1.2234 + */
  1.2235 +void /* PRIVATE */
  1.2236 +png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
  1.2237 +{
  1.2238 +   /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  1.2239 +
  1.2240 +   /* Start of interlace block */
  1.2241 +   static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  1.2242 +
  1.2243 +   /* Offset to next interlace block */
  1.2244 +   static PNG_CONST png_byte  png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
  1.2245 +
  1.2246 +   png_debug(1, "in png_do_write_interlace");
  1.2247 +
  1.2248 +   /* We don't have to do anything on the last pass (6) */
  1.2249 +   if (pass < 6)
  1.2250 +   {
  1.2251 +      /* Each pixel depth is handled separately */
  1.2252 +      switch (row_info->pixel_depth)
  1.2253 +      {
  1.2254 +         case 1:
  1.2255 +         {
  1.2256 +            png_bytep sp;
  1.2257 +            png_bytep dp;
  1.2258 +            int shift;
  1.2259 +            int d;
  1.2260 +            int value;
  1.2261 +            png_uint_32 i;
  1.2262 +            png_uint_32 row_width = row_info->width;
  1.2263 +
  1.2264 +            dp = row;
  1.2265 +            d = 0;
  1.2266 +            shift = 7;
  1.2267 +
  1.2268 +            for (i = png_pass_start[pass]; i < row_width;
  1.2269 +               i += png_pass_inc[pass])
  1.2270 +            {
  1.2271 +               sp = row + (png_size_t)(i >> 3);
  1.2272 +               value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
  1.2273 +               d |= (value << shift);
  1.2274 +
  1.2275 +               if (shift == 0)
  1.2276 +               {
  1.2277 +                  shift = 7;
  1.2278 +                  *dp++ = (png_byte)d;
  1.2279 +                  d = 0;
  1.2280 +               }
  1.2281 +
  1.2282 +               else
  1.2283 +                  shift--;
  1.2284 +
  1.2285 +            }
  1.2286 +            if (shift != 7)
  1.2287 +               *dp = (png_byte)d;
  1.2288 +
  1.2289 +            break;
  1.2290 +         }
  1.2291 +
  1.2292 +         case 2:
  1.2293 +         {
  1.2294 +            png_bytep sp;
  1.2295 +            png_bytep dp;
  1.2296 +            int shift;
  1.2297 +            int d;
  1.2298 +            int value;
  1.2299 +            png_uint_32 i;
  1.2300 +            png_uint_32 row_width = row_info->width;
  1.2301 +
  1.2302 +            dp = row;
  1.2303 +            shift = 6;
  1.2304 +            d = 0;
  1.2305 +
  1.2306 +            for (i = png_pass_start[pass]; i < row_width;
  1.2307 +               i += png_pass_inc[pass])
  1.2308 +            {
  1.2309 +               sp = row + (png_size_t)(i >> 2);
  1.2310 +               value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
  1.2311 +               d |= (value << shift);
  1.2312 +
  1.2313 +               if (shift == 0)
  1.2314 +               {
  1.2315 +                  shift = 6;
  1.2316 +                  *dp++ = (png_byte)d;
  1.2317 +                  d = 0;
  1.2318 +               }
  1.2319 +
  1.2320 +               else
  1.2321 +                  shift -= 2;
  1.2322 +            }
  1.2323 +            if (shift != 6)
  1.2324 +               *dp = (png_byte)d;
  1.2325 +
  1.2326 +            break;
  1.2327 +         }
  1.2328 +
  1.2329 +         case 4:
  1.2330 +         {
  1.2331 +            png_bytep sp;
  1.2332 +            png_bytep dp;
  1.2333 +            int shift;
  1.2334 +            int d;
  1.2335 +            int value;
  1.2336 +            png_uint_32 i;
  1.2337 +            png_uint_32 row_width = row_info->width;
  1.2338 +
  1.2339 +            dp = row;
  1.2340 +            shift = 4;
  1.2341 +            d = 0;
  1.2342 +            for (i = png_pass_start[pass]; i < row_width;
  1.2343 +                i += png_pass_inc[pass])
  1.2344 +            {
  1.2345 +               sp = row + (png_size_t)(i >> 1);
  1.2346 +               value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
  1.2347 +               d |= (value << shift);
  1.2348 +
  1.2349 +               if (shift == 0)
  1.2350 +               {
  1.2351 +                  shift = 4;
  1.2352 +                  *dp++ = (png_byte)d;
  1.2353 +                  d = 0;
  1.2354 +               }
  1.2355 +
  1.2356 +               else
  1.2357 +                  shift -= 4;
  1.2358 +            }
  1.2359 +            if (shift != 4)
  1.2360 +               *dp = (png_byte)d;
  1.2361 +
  1.2362 +            break;
  1.2363 +         }
  1.2364 +
  1.2365 +         default:
  1.2366 +         {
  1.2367 +            png_bytep sp;
  1.2368 +            png_bytep dp;
  1.2369 +            png_uint_32 i;
  1.2370 +            png_uint_32 row_width = row_info->width;
  1.2371 +            png_size_t pixel_bytes;
  1.2372 +
  1.2373 +            /* Start at the beginning */
  1.2374 +            dp = row;
  1.2375 +
  1.2376 +            /* Find out how many bytes each pixel takes up */
  1.2377 +            pixel_bytes = (row_info->pixel_depth >> 3);
  1.2378 +
  1.2379 +            /* Loop through the row, only looking at the pixels that matter */
  1.2380 +            for (i = png_pass_start[pass]; i < row_width;
  1.2381 +               i += png_pass_inc[pass])
  1.2382 +            {
  1.2383 +               /* Find out where the original pixel is */
  1.2384 +               sp = row + (png_size_t)i * pixel_bytes;
  1.2385 +
  1.2386 +               /* Move the pixel */
  1.2387 +               if (dp != sp)
  1.2388 +                  memcpy(dp, sp, pixel_bytes);
  1.2389 +
  1.2390 +               /* Next pixel */
  1.2391 +               dp += pixel_bytes;
  1.2392 +            }
  1.2393 +            break;
  1.2394 +         }
  1.2395 +      }
  1.2396 +      /* Set new row width */
  1.2397 +      row_info->width = (row_info->width +
  1.2398 +          png_pass_inc[pass] - 1 -
  1.2399 +          png_pass_start[pass]) /
  1.2400 +          png_pass_inc[pass];
  1.2401 +
  1.2402 +      row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
  1.2403 +          row_info->width);
  1.2404 +   }
  1.2405 +}
  1.2406 +#endif
  1.2407 +
  1.2408 +/* This filters the row, chooses which filter to use, if it has not already
  1.2409 + * been specified by the application, and then writes the row out with the
  1.2410 + * chosen filter.
  1.2411 + */
  1.2412 +static void
  1.2413 +png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
  1.2414 +   png_size_t row_bytes);
  1.2415 +
  1.2416 +#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
  1.2417 +#define PNG_HISHIFT 10
  1.2418 +#define PNG_LOMASK ((png_uint_32)0xffffL)
  1.2419 +#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
  1.2420 +void /* PRIVATE */
  1.2421 +png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
  1.2422 +{
  1.2423 +   png_bytep best_row;
  1.2424 +#ifdef PNG_WRITE_FILTER_SUPPORTED
  1.2425 +   png_bytep prev_row, row_buf;
  1.2426 +   png_uint_32 mins, bpp;
  1.2427 +   png_byte filter_to_do = png_ptr->do_filter;
  1.2428 +   png_size_t row_bytes = row_info->rowbytes;
  1.2429 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.2430 +   int num_p_filters = png_ptr->num_prev_filters;
  1.2431 +#endif
  1.2432 +
  1.2433 +   png_debug(1, "in png_write_find_filter");
  1.2434 +
  1.2435 +#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.2436 +  if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
  1.2437 +  {
  1.2438 +     /* These will never be selected so we need not test them. */
  1.2439 +     filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
  1.2440 +  }
  1.2441 +#endif
  1.2442 +
  1.2443 +   /* Find out how many bytes offset each pixel is */
  1.2444 +   bpp = (row_info->pixel_depth + 7) >> 3;
  1.2445 +
  1.2446 +   prev_row = png_ptr->prev_row;
  1.2447 +#endif
  1.2448 +   best_row = png_ptr->row_buf;
  1.2449 +#ifdef PNG_WRITE_FILTER_SUPPORTED
  1.2450 +   row_buf = best_row;
  1.2451 +   mins = PNG_MAXSUM;
  1.2452 +
  1.2453 +   /* The prediction method we use is to find which method provides the
  1.2454 +    * smallest value when summing the absolute values of the distances
  1.2455 +    * from zero, using anything >= 128 as negative numbers.  This is known
  1.2456 +    * as the "minimum sum of absolute differences" heuristic.  Other
  1.2457 +    * heuristics are the "weighted minimum sum of absolute differences"
  1.2458 +    * (experimental and can in theory improve compression), and the "zlib
  1.2459 +    * predictive" method (not implemented yet), which does test compressions
  1.2460 +    * of lines using different filter methods, and then chooses the
  1.2461 +    * (series of) filter(s) that give minimum compressed data size (VERY
  1.2462 +    * computationally expensive).
  1.2463 +    *
  1.2464 +    * GRR 980525:  consider also
  1.2465 +    *
  1.2466 +    *   (1) minimum sum of absolute differences from running average (i.e.,
  1.2467 +    *       keep running sum of non-absolute differences & count of bytes)
  1.2468 +    *       [track dispersion, too?  restart average if dispersion too large?]
  1.2469 +    *
  1.2470 +    *  (1b) minimum sum of absolute differences from sliding average, probably
  1.2471 +    *       with window size <= deflate window (usually 32K)
  1.2472 +    *
  1.2473 +    *   (2) minimum sum of squared differences from zero or running average
  1.2474 +    *       (i.e., ~ root-mean-square approach)
  1.2475 +    */
  1.2476 +
  1.2477 +
  1.2478 +   /* We don't need to test the 'no filter' case if this is the only filter
  1.2479 +    * that has been chosen, as it doesn't actually do anything to the data.
  1.2480 +    */
  1.2481 +   if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE)
  1.2482 +   {
  1.2483 +      png_bytep rp;
  1.2484 +      png_uint_32 sum = 0;
  1.2485 +      png_size_t i;
  1.2486 +      int v;
  1.2487 +
  1.2488 +      for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
  1.2489 +      {
  1.2490 +         v = *rp;
  1.2491 +         sum += (v < 128) ? v : 256 - v;
  1.2492 +      }
  1.2493 +
  1.2494 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.2495 +      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1.2496 +      {
  1.2497 +         png_uint_32 sumhi, sumlo;
  1.2498 +         int j;
  1.2499 +         sumlo = sum & PNG_LOMASK;
  1.2500 +         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
  1.2501 +
  1.2502 +         /* Reduce the sum if we match any of the previous rows */
  1.2503 +         for (j = 0; j < num_p_filters; j++)
  1.2504 +         {
  1.2505 +            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
  1.2506 +            {
  1.2507 +               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
  1.2508 +                   PNG_WEIGHT_SHIFT;
  1.2509 +
  1.2510 +               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
  1.2511 +                   PNG_WEIGHT_SHIFT;
  1.2512 +            }
  1.2513 +         }
  1.2514 +
  1.2515 +         /* Factor in the cost of this filter (this is here for completeness,
  1.2516 +          * but it makes no sense to have a "cost" for the NONE filter, as
  1.2517 +          * it has the minimum possible computational cost - none).
  1.2518 +          */
  1.2519 +         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
  1.2520 +             PNG_COST_SHIFT;
  1.2521 +
  1.2522 +         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
  1.2523 +             PNG_COST_SHIFT;
  1.2524 +
  1.2525 +         if (sumhi > PNG_HIMASK)
  1.2526 +            sum = PNG_MAXSUM;
  1.2527 +
  1.2528 +         else
  1.2529 +            sum = (sumhi << PNG_HISHIFT) + sumlo;
  1.2530 +      }
  1.2531 +#endif
  1.2532 +      mins = sum;
  1.2533 +   }
  1.2534 +
  1.2535 +   /* Sub filter */
  1.2536 +   if (filter_to_do == PNG_FILTER_SUB)
  1.2537 +   /* It's the only filter so no testing is needed */
  1.2538 +   {
  1.2539 +      png_bytep rp, lp, dp;
  1.2540 +      png_size_t i;
  1.2541 +
  1.2542 +      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
  1.2543 +           i++, rp++, dp++)
  1.2544 +      {
  1.2545 +         *dp = *rp;
  1.2546 +      }
  1.2547 +
  1.2548 +      for (lp = row_buf + 1; i < row_bytes;
  1.2549 +         i++, rp++, lp++, dp++)
  1.2550 +      {
  1.2551 +         *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
  1.2552 +      }
  1.2553 +
  1.2554 +      best_row = png_ptr->sub_row;
  1.2555 +   }
  1.2556 +
  1.2557 +   else if (filter_to_do & PNG_FILTER_SUB)
  1.2558 +   {
  1.2559 +      png_bytep rp, dp, lp;
  1.2560 +      png_uint_32 sum = 0, lmins = mins;
  1.2561 +      png_size_t i;
  1.2562 +      int v;
  1.2563 +
  1.2564 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.2565 +      /* We temporarily increase the "minimum sum" by the factor we
  1.2566 +       * would reduce the sum of this filter, so that we can do the
  1.2567 +       * early exit comparison without scaling the sum each time.
  1.2568 +       */
  1.2569 +      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1.2570 +      {
  1.2571 +         int j;
  1.2572 +         png_uint_32 lmhi, lmlo;
  1.2573 +         lmlo = lmins & PNG_LOMASK;
  1.2574 +         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  1.2575 +
  1.2576 +         for (j = 0; j < num_p_filters; j++)
  1.2577 +         {
  1.2578 +            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
  1.2579 +            {
  1.2580 +               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
  1.2581 +                   PNG_WEIGHT_SHIFT;
  1.2582 +
  1.2583 +               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
  1.2584 +                   PNG_WEIGHT_SHIFT;
  1.2585 +            }
  1.2586 +         }
  1.2587 +
  1.2588 +         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  1.2589 +             PNG_COST_SHIFT;
  1.2590 +
  1.2591 +         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  1.2592 +             PNG_COST_SHIFT;
  1.2593 +
  1.2594 +         if (lmhi > PNG_HIMASK)
  1.2595 +            lmins = PNG_MAXSUM;
  1.2596 +
  1.2597 +         else
  1.2598 +            lmins = (lmhi << PNG_HISHIFT) + lmlo;
  1.2599 +      }
  1.2600 +#endif
  1.2601 +
  1.2602 +      for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
  1.2603 +           i++, rp++, dp++)
  1.2604 +      {
  1.2605 +         v = *dp = *rp;
  1.2606 +
  1.2607 +         sum += (v < 128) ? v : 256 - v;
  1.2608 +      }
  1.2609 +
  1.2610 +      for (lp = row_buf + 1; i < row_bytes;
  1.2611 +         i++, rp++, lp++, dp++)
  1.2612 +      {
  1.2613 +         v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
  1.2614 +
  1.2615 +         sum += (v < 128) ? v : 256 - v;
  1.2616 +
  1.2617 +         if (sum > lmins)  /* We are already worse, don't continue. */
  1.2618 +            break;
  1.2619 +      }
  1.2620 +
  1.2621 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.2622 +      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1.2623 +      {
  1.2624 +         int j;
  1.2625 +         png_uint_32 sumhi, sumlo;
  1.2626 +         sumlo = sum & PNG_LOMASK;
  1.2627 +         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  1.2628 +
  1.2629 +         for (j = 0; j < num_p_filters; j++)
  1.2630 +         {
  1.2631 +            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
  1.2632 +            {
  1.2633 +               sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
  1.2634 +                   PNG_WEIGHT_SHIFT;
  1.2635 +
  1.2636 +               sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
  1.2637 +                   PNG_WEIGHT_SHIFT;
  1.2638 +            }
  1.2639 +         }
  1.2640 +
  1.2641 +         sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  1.2642 +             PNG_COST_SHIFT;
  1.2643 +
  1.2644 +         sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  1.2645 +             PNG_COST_SHIFT;
  1.2646 +
  1.2647 +         if (sumhi > PNG_HIMASK)
  1.2648 +            sum = PNG_MAXSUM;
  1.2649 +
  1.2650 +         else
  1.2651 +            sum = (sumhi << PNG_HISHIFT) + sumlo;
  1.2652 +      }
  1.2653 +#endif
  1.2654 +
  1.2655 +      if (sum < mins)
  1.2656 +      {
  1.2657 +         mins = sum;
  1.2658 +         best_row = png_ptr->sub_row;
  1.2659 +      }
  1.2660 +   }
  1.2661 +
  1.2662 +   /* Up filter */
  1.2663 +   if (filter_to_do == PNG_FILTER_UP)
  1.2664 +   {
  1.2665 +      png_bytep rp, dp, pp;
  1.2666 +      png_size_t i;
  1.2667 +
  1.2668 +      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
  1.2669 +          pp = prev_row + 1; i < row_bytes;
  1.2670 +          i++, rp++, pp++, dp++)
  1.2671 +      {
  1.2672 +         *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
  1.2673 +      }
  1.2674 +
  1.2675 +      best_row = png_ptr->up_row;
  1.2676 +   }
  1.2677 +
  1.2678 +   else if (filter_to_do & PNG_FILTER_UP)
  1.2679 +   {
  1.2680 +      png_bytep rp, dp, pp;
  1.2681 +      png_uint_32 sum = 0, lmins = mins;
  1.2682 +      png_size_t i;
  1.2683 +      int v;
  1.2684 +
  1.2685 +
  1.2686 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.2687 +      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1.2688 +      {
  1.2689 +         int j;
  1.2690 +         png_uint_32 lmhi, lmlo;
  1.2691 +         lmlo = lmins & PNG_LOMASK;
  1.2692 +         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  1.2693 +
  1.2694 +         for (j = 0; j < num_p_filters; j++)
  1.2695 +         {
  1.2696 +            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
  1.2697 +            {
  1.2698 +               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
  1.2699 +                   PNG_WEIGHT_SHIFT;
  1.2700 +
  1.2701 +               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
  1.2702 +                   PNG_WEIGHT_SHIFT;
  1.2703 +            }
  1.2704 +         }
  1.2705 +
  1.2706 +         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
  1.2707 +             PNG_COST_SHIFT;
  1.2708 +
  1.2709 +         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
  1.2710 +             PNG_COST_SHIFT;
  1.2711 +
  1.2712 +         if (lmhi > PNG_HIMASK)
  1.2713 +            lmins = PNG_MAXSUM;
  1.2714 +
  1.2715 +         else
  1.2716 +            lmins = (lmhi << PNG_HISHIFT) + lmlo;
  1.2717 +      }
  1.2718 +#endif
  1.2719 +
  1.2720 +      for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
  1.2721 +          pp = prev_row + 1; i < row_bytes; i++)
  1.2722 +      {
  1.2723 +         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
  1.2724 +
  1.2725 +         sum += (v < 128) ? v : 256 - v;
  1.2726 +
  1.2727 +         if (sum > lmins)  /* We are already worse, don't continue. */
  1.2728 +            break;
  1.2729 +      }
  1.2730 +
  1.2731 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.2732 +      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1.2733 +      {
  1.2734 +         int j;
  1.2735 +         png_uint_32 sumhi, sumlo;
  1.2736 +         sumlo = sum & PNG_LOMASK;
  1.2737 +         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  1.2738 +
  1.2739 +         for (j = 0; j < num_p_filters; j++)
  1.2740 +         {
  1.2741 +            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
  1.2742 +            {
  1.2743 +               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
  1.2744 +                   PNG_WEIGHT_SHIFT;
  1.2745 +
  1.2746 +               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
  1.2747 +                   PNG_WEIGHT_SHIFT;
  1.2748 +            }
  1.2749 +         }
  1.2750 +
  1.2751 +         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
  1.2752 +             PNG_COST_SHIFT;
  1.2753 +
  1.2754 +         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
  1.2755 +             PNG_COST_SHIFT;
  1.2756 +
  1.2757 +         if (sumhi > PNG_HIMASK)
  1.2758 +            sum = PNG_MAXSUM;
  1.2759 +
  1.2760 +         else
  1.2761 +            sum = (sumhi << PNG_HISHIFT) + sumlo;
  1.2762 +      }
  1.2763 +#endif
  1.2764 +
  1.2765 +      if (sum < mins)
  1.2766 +      {
  1.2767 +         mins = sum;
  1.2768 +         best_row = png_ptr->up_row;
  1.2769 +      }
  1.2770 +   }
  1.2771 +
  1.2772 +   /* Avg filter */
  1.2773 +   if (filter_to_do == PNG_FILTER_AVG)
  1.2774 +   {
  1.2775 +      png_bytep rp, dp, pp, lp;
  1.2776 +      png_uint_32 i;
  1.2777 +
  1.2778 +      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
  1.2779 +           pp = prev_row + 1; i < bpp; i++)
  1.2780 +      {
  1.2781 +         *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
  1.2782 +      }
  1.2783 +
  1.2784 +      for (lp = row_buf + 1; i < row_bytes; i++)
  1.2785 +      {
  1.2786 +         *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
  1.2787 +                 & 0xff);
  1.2788 +      }
  1.2789 +      best_row = png_ptr->avg_row;
  1.2790 +   }
  1.2791 +
  1.2792 +   else if (filter_to_do & PNG_FILTER_AVG)
  1.2793 +   {
  1.2794 +      png_bytep rp, dp, pp, lp;
  1.2795 +      png_uint_32 sum = 0, lmins = mins;
  1.2796 +      png_size_t i;
  1.2797 +      int v;
  1.2798 +
  1.2799 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.2800 +      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1.2801 +      {
  1.2802 +         int j;
  1.2803 +         png_uint_32 lmhi, lmlo;
  1.2804 +         lmlo = lmins & PNG_LOMASK;
  1.2805 +         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  1.2806 +
  1.2807 +         for (j = 0; j < num_p_filters; j++)
  1.2808 +         {
  1.2809 +            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
  1.2810 +            {
  1.2811 +               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
  1.2812 +                   PNG_WEIGHT_SHIFT;
  1.2813 +
  1.2814 +               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
  1.2815 +                   PNG_WEIGHT_SHIFT;
  1.2816 +            }
  1.2817 +         }
  1.2818 +
  1.2819 +         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
  1.2820 +             PNG_COST_SHIFT;
  1.2821 +
  1.2822 +         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
  1.2823 +             PNG_COST_SHIFT;
  1.2824 +
  1.2825 +         if (lmhi > PNG_HIMASK)
  1.2826 +            lmins = PNG_MAXSUM;
  1.2827 +
  1.2828 +         else
  1.2829 +            lmins = (lmhi << PNG_HISHIFT) + lmlo;
  1.2830 +      }
  1.2831 +#endif
  1.2832 +
  1.2833 +      for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
  1.2834 +           pp = prev_row + 1; i < bpp; i++)
  1.2835 +      {
  1.2836 +         v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
  1.2837 +
  1.2838 +         sum += (v < 128) ? v : 256 - v;
  1.2839 +      }
  1.2840 +
  1.2841 +      for (lp = row_buf + 1; i < row_bytes; i++)
  1.2842 +      {
  1.2843 +         v = *dp++ =
  1.2844 +             (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
  1.2845 +
  1.2846 +         sum += (v < 128) ? v : 256 - v;
  1.2847 +
  1.2848 +         if (sum > lmins)  /* We are already worse, don't continue. */
  1.2849 +            break;
  1.2850 +      }
  1.2851 +
  1.2852 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.2853 +      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1.2854 +      {
  1.2855 +         int j;
  1.2856 +         png_uint_32 sumhi, sumlo;
  1.2857 +         sumlo = sum & PNG_LOMASK;
  1.2858 +         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  1.2859 +
  1.2860 +         for (j = 0; j < num_p_filters; j++)
  1.2861 +         {
  1.2862 +            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
  1.2863 +            {
  1.2864 +               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
  1.2865 +                   PNG_WEIGHT_SHIFT;
  1.2866 +
  1.2867 +               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
  1.2868 +                   PNG_WEIGHT_SHIFT;
  1.2869 +            }
  1.2870 +         }
  1.2871 +
  1.2872 +         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
  1.2873 +             PNG_COST_SHIFT;
  1.2874 +
  1.2875 +         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
  1.2876 +             PNG_COST_SHIFT;
  1.2877 +
  1.2878 +         if (sumhi > PNG_HIMASK)
  1.2879 +            sum = PNG_MAXSUM;
  1.2880 +
  1.2881 +         else
  1.2882 +            sum = (sumhi << PNG_HISHIFT) + sumlo;
  1.2883 +      }
  1.2884 +#endif
  1.2885 +
  1.2886 +      if (sum < mins)
  1.2887 +      {
  1.2888 +         mins = sum;
  1.2889 +         best_row = png_ptr->avg_row;
  1.2890 +      }
  1.2891 +   }
  1.2892 +
  1.2893 +   /* Paeth filter */
  1.2894 +   if (filter_to_do == PNG_FILTER_PAETH)
  1.2895 +   {
  1.2896 +      png_bytep rp, dp, pp, cp, lp;
  1.2897 +      png_size_t i;
  1.2898 +
  1.2899 +      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
  1.2900 +          pp = prev_row + 1; i < bpp; i++)
  1.2901 +      {
  1.2902 +         *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
  1.2903 +      }
  1.2904 +
  1.2905 +      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
  1.2906 +      {
  1.2907 +         int a, b, c, pa, pb, pc, p;
  1.2908 +
  1.2909 +         b = *pp++;
  1.2910 +         c = *cp++;
  1.2911 +         a = *lp++;
  1.2912 +
  1.2913 +         p = b - c;
  1.2914 +         pc = a - c;
  1.2915 +
  1.2916 +#ifdef PNG_USE_ABS
  1.2917 +         pa = abs(p);
  1.2918 +         pb = abs(pc);
  1.2919 +         pc = abs(p + pc);
  1.2920 +#else
  1.2921 +         pa = p < 0 ? -p : p;
  1.2922 +         pb = pc < 0 ? -pc : pc;
  1.2923 +         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
  1.2924 +#endif
  1.2925 +
  1.2926 +         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
  1.2927 +
  1.2928 +         *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
  1.2929 +      }
  1.2930 +      best_row = png_ptr->paeth_row;
  1.2931 +   }
  1.2932 +
  1.2933 +   else if (filter_to_do & PNG_FILTER_PAETH)
  1.2934 +   {
  1.2935 +      png_bytep rp, dp, pp, cp, lp;
  1.2936 +      png_uint_32 sum = 0, lmins = mins;
  1.2937 +      png_size_t i;
  1.2938 +      int v;
  1.2939 +
  1.2940 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.2941 +      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1.2942 +      {
  1.2943 +         int j;
  1.2944 +         png_uint_32 lmhi, lmlo;
  1.2945 +         lmlo = lmins & PNG_LOMASK;
  1.2946 +         lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  1.2947 +
  1.2948 +         for (j = 0; j < num_p_filters; j++)
  1.2949 +         {
  1.2950 +            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
  1.2951 +            {
  1.2952 +               lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
  1.2953 +                   PNG_WEIGHT_SHIFT;
  1.2954 +
  1.2955 +               lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
  1.2956 +                   PNG_WEIGHT_SHIFT;
  1.2957 +            }
  1.2958 +         }
  1.2959 +
  1.2960 +         lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  1.2961 +             PNG_COST_SHIFT;
  1.2962 +
  1.2963 +         lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  1.2964 +             PNG_COST_SHIFT;
  1.2965 +
  1.2966 +         if (lmhi > PNG_HIMASK)
  1.2967 +            lmins = PNG_MAXSUM;
  1.2968 +
  1.2969 +         else
  1.2970 +            lmins = (lmhi << PNG_HISHIFT) + lmlo;
  1.2971 +      }
  1.2972 +#endif
  1.2973 +
  1.2974 +      for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
  1.2975 +          pp = prev_row + 1; i < bpp; i++)
  1.2976 +      {
  1.2977 +         v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
  1.2978 +
  1.2979 +         sum += (v < 128) ? v : 256 - v;
  1.2980 +      }
  1.2981 +
  1.2982 +      for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
  1.2983 +      {
  1.2984 +         int a, b, c, pa, pb, pc, p;
  1.2985 +
  1.2986 +         b = *pp++;
  1.2987 +         c = *cp++;
  1.2988 +         a = *lp++;
  1.2989 +
  1.2990 +#ifndef PNG_SLOW_PAETH
  1.2991 +         p = b - c;
  1.2992 +         pc = a - c;
  1.2993 +#ifdef PNG_USE_ABS
  1.2994 +         pa = abs(p);
  1.2995 +         pb = abs(pc);
  1.2996 +         pc = abs(p + pc);
  1.2997 +#else
  1.2998 +         pa = p < 0 ? -p : p;
  1.2999 +         pb = pc < 0 ? -pc : pc;
  1.3000 +         pc = (p + pc) < 0 ? -(p + pc) : p + pc;
  1.3001 +#endif
  1.3002 +         p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
  1.3003 +#else /* PNG_SLOW_PAETH */
  1.3004 +         p = a + b - c;
  1.3005 +         pa = abs(p - a);
  1.3006 +         pb = abs(p - b);
  1.3007 +         pc = abs(p - c);
  1.3008 +
  1.3009 +         if (pa <= pb && pa <= pc)
  1.3010 +            p = a;
  1.3011 +
  1.3012 +         else if (pb <= pc)
  1.3013 +            p = b;
  1.3014 +
  1.3015 +         else
  1.3016 +            p = c;
  1.3017 +#endif /* PNG_SLOW_PAETH */
  1.3018 +
  1.3019 +         v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
  1.3020 +
  1.3021 +         sum += (v < 128) ? v : 256 - v;
  1.3022 +
  1.3023 +         if (sum > lmins)  /* We are already worse, don't continue. */
  1.3024 +            break;
  1.3025 +      }
  1.3026 +
  1.3027 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.3028 +      if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  1.3029 +      {
  1.3030 +         int j;
  1.3031 +         png_uint_32 sumhi, sumlo;
  1.3032 +         sumlo = sum & PNG_LOMASK;
  1.3033 +         sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  1.3034 +
  1.3035 +         for (j = 0; j < num_p_filters; j++)
  1.3036 +         {
  1.3037 +            if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
  1.3038 +            {
  1.3039 +               sumlo = (sumlo * png_ptr->filter_weights[j]) >>
  1.3040 +                   PNG_WEIGHT_SHIFT;
  1.3041 +
  1.3042 +               sumhi = (sumhi * png_ptr->filter_weights[j]) >>
  1.3043 +                   PNG_WEIGHT_SHIFT;
  1.3044 +            }
  1.3045 +         }
  1.3046 +
  1.3047 +         sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  1.3048 +             PNG_COST_SHIFT;
  1.3049 +
  1.3050 +         sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  1.3051 +             PNG_COST_SHIFT;
  1.3052 +
  1.3053 +         if (sumhi > PNG_HIMASK)
  1.3054 +            sum = PNG_MAXSUM;
  1.3055 +
  1.3056 +         else
  1.3057 +            sum = (sumhi << PNG_HISHIFT) + sumlo;
  1.3058 +      }
  1.3059 +#endif
  1.3060 +
  1.3061 +      if (sum < mins)
  1.3062 +      {
  1.3063 +         best_row = png_ptr->paeth_row;
  1.3064 +      }
  1.3065 +   }
  1.3066 +#endif /* PNG_WRITE_FILTER_SUPPORTED */
  1.3067 +
  1.3068 +   /* Do the actual writing of the filtered row data from the chosen filter. */
  1.3069 +   png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
  1.3070 +
  1.3071 +#ifdef PNG_WRITE_FILTER_SUPPORTED
  1.3072 +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  1.3073 +   /* Save the type of filter we picked this time for future calculations */
  1.3074 +   if (png_ptr->num_prev_filters > 0)
  1.3075 +   {
  1.3076 +      int j;
  1.3077 +
  1.3078 +      for (j = 1; j < num_p_filters; j++)
  1.3079 +      {
  1.3080 +         png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
  1.3081 +      }
  1.3082 +
  1.3083 +      png_ptr->prev_filters[j] = best_row[0];
  1.3084 +   }
  1.3085 +#endif
  1.3086 +#endif /* PNG_WRITE_FILTER_SUPPORTED */
  1.3087 +}
  1.3088 +
  1.3089 +
  1.3090 +/* Do the actual writing of a previously filtered row. */
  1.3091 +static void
  1.3092 +png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
  1.3093 +   png_size_t full_row_length/*includes filter byte*/)
  1.3094 +{
  1.3095 +   png_debug(1, "in png_write_filtered_row");
  1.3096 +
  1.3097 +   png_debug1(2, "filter = %d", filtered_row[0]);
  1.3098 +
  1.3099 +   png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH);
  1.3100 +
  1.3101 +   /* Swap the current and previous rows */
  1.3102 +   if (png_ptr->prev_row != NULL)
  1.3103 +   {
  1.3104 +      png_bytep tptr;
  1.3105 +
  1.3106 +      tptr = png_ptr->prev_row;
  1.3107 +      png_ptr->prev_row = png_ptr->row_buf;
  1.3108 +      png_ptr->row_buf = tptr;
  1.3109 +   }
  1.3110 +
  1.3111 +   /* Finish row - updates counters and flushes zlib if last row */
  1.3112 +   png_write_finish_row(png_ptr);
  1.3113 +
  1.3114 +#ifdef PNG_WRITE_FLUSH_SUPPORTED
  1.3115 +   png_ptr->flush_rows++;
  1.3116 +
  1.3117 +   if (png_ptr->flush_dist > 0 &&
  1.3118 +       png_ptr->flush_rows >= png_ptr->flush_dist)
  1.3119 +   {
  1.3120 +      png_write_flush(png_ptr);
  1.3121 +   }
  1.3122 +#endif
  1.3123 +}
  1.3124 +
  1.3125 +#ifdef PNG_WRITE_APNG_SUPPORTED
  1.3126 +void /* PRIVATE */
  1.3127 +png_write_reset(png_structp png_ptr)
  1.3128 +{
  1.3129 +    png_ptr->row_number = 0;
  1.3130 +    png_ptr->pass = 0;
  1.3131 +    png_ptr->mode &= ~PNG_HAVE_IDAT;
  1.3132 +}
  1.3133 +
  1.3134 +void /* PRIVATE */
  1.3135 +png_write_reinit(png_structp png_ptr, png_infop info_ptr,
  1.3136 +                 png_uint_32 width, png_uint_32 height)
  1.3137 +{
  1.3138 +    if (png_ptr->num_frames_written == 0 &&
  1.3139 +        (width != png_ptr->first_frame_width ||
  1.3140 +         height != png_ptr->first_frame_height))
  1.3141 +        png_error(png_ptr, "width and/or height in the first frame's fcTL "
  1.3142 +                           "don't match the ones in IHDR");
  1.3143 +    if (width > png_ptr->first_frame_width ||
  1.3144 +        height > png_ptr->first_frame_height)
  1.3145 +        png_error(png_ptr, "width and/or height for a frame greater than"
  1.3146 +                           "the ones in IHDR");
  1.3147 +
  1.3148 +    png_set_IHDR(png_ptr, info_ptr, width, height,
  1.3149 +                 info_ptr->bit_depth, info_ptr->color_type,
  1.3150 +                 info_ptr->interlace_type, info_ptr->compression_type,
  1.3151 +                 info_ptr->filter_type);
  1.3152 +
  1.3153 +    png_ptr->width = width;
  1.3154 +    png_ptr->height = height;
  1.3155 +    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
  1.3156 +    png_ptr->usr_width = png_ptr->width;
  1.3157 +}
  1.3158 +#endif /* PNG_WRITE_APNG_SUPPORTED */
  1.3159 +#endif /* PNG_WRITE_SUPPORTED */

mercurial