media/libpng/pngwutil.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     2 /* pngwutil.c - utilities to write a PNG file
     3  *
     4  * Last changed in libpng 1.6.2 [April 25, 2013]
     5  * Copyright (c) 1998-2013 Glenn Randers-Pehrson
     6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
     7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
     8  *
     9  * This code is released under the libpng license.
    10  * For conditions of distribution and use, see the disclaimer
    11  * and license in png.h
    12  */
    14 #include "pngpriv.h"
    16 #ifdef PNG_WRITE_SUPPORTED
    18 #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
    19 /* Place a 32-bit number into a buffer in PNG byte order.  We work
    20  * with unsigned numbers for convenience, although one supported
    21  * ancillary chunk uses signed (two's complement) numbers.
    22  */
    23 void PNGAPI
    24 png_save_uint_32(png_bytep buf, png_uint_32 i)
    25 {
    26    buf[0] = (png_byte)((i >> 24) & 0xff);
    27    buf[1] = (png_byte)((i >> 16) & 0xff);
    28    buf[2] = (png_byte)((i >> 8) & 0xff);
    29    buf[3] = (png_byte)(i & 0xff);
    30 }
    32 /* Place a 16-bit number into a buffer in PNG byte order.
    33  * The parameter is declared unsigned int, not png_uint_16,
    34  * just to avoid potential problems on pre-ANSI C compilers.
    35  */
    36 void PNGAPI
    37 png_save_uint_16(png_bytep buf, unsigned int i)
    38 {
    39    buf[0] = (png_byte)((i >> 8) & 0xff);
    40    buf[1] = (png_byte)(i & 0xff);
    41 }
    42 #endif
    44 /* Simple function to write the signature.  If we have already written
    45  * the magic bytes of the signature, or more likely, the PNG stream is
    46  * being embedded into another stream and doesn't need its own signature,
    47  * we should call png_set_sig_bytes() to tell libpng how many of the
    48  * bytes have already been written.
    49  */
    50 void PNGAPI
    51 png_write_sig(png_structrp png_ptr)
    52 {
    53    png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
    55 #ifdef PNG_IO_STATE_SUPPORTED
    56    /* Inform the I/O callback that the signature is being written */
    57    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE;
    58 #endif
    60    /* Write the rest of the 8 byte signature */
    61    png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
    62       (png_size_t)(8 - png_ptr->sig_bytes));
    64    if (png_ptr->sig_bytes < 3)
    65       png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
    66 }
    68 /* Write the start of a PNG chunk.  The type is the chunk type.
    69  * The total_length is the sum of the lengths of all the data you will be
    70  * passing in png_write_chunk_data().
    71  */
    72 static void
    73 png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name,
    74     png_uint_32 length)
    75 {
    76    png_byte buf[8];
    78 #if defined(PNG_DEBUG) && (PNG_DEBUG > 0)
    79    PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
    80    png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
    81 #endif
    83    if (png_ptr == NULL)
    84       return;
    86 #ifdef PNG_IO_STATE_SUPPORTED
    87    /* Inform the I/O callback that the chunk header is being written.
    88     * PNG_IO_CHUNK_HDR requires a single I/O call.
    89     */
    90    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR;
    91 #endif
    93    /* Write the length and the chunk name */
    94    png_save_uint_32(buf, length);
    95    png_save_uint_32(buf + 4, chunk_name);
    96    png_write_data(png_ptr, buf, 8);
    98    /* Put the chunk name into png_ptr->chunk_name */
    99    png_ptr->chunk_name = chunk_name;
   101    /* Reset the crc and run it over the chunk name */
   102    png_reset_crc(png_ptr);
   104    png_calculate_crc(png_ptr, buf + 4, 4);
   106 #ifdef PNG_IO_STATE_SUPPORTED
   107    /* Inform the I/O callback that chunk data will (possibly) be written.
   108     * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
   109     */
   110    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA;
   111 #endif
   112 }
   114 void PNGAPI
   115 png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
   116     png_uint_32 length)
   117 {
   118    png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
   119 }
   121 /* Write the data of a PNG chunk started with png_write_chunk_header().
   122  * Note that multiple calls to this function are allowed, and that the
   123  * sum of the lengths from these calls *must* add up to the total_length
   124  * given to png_write_chunk_header().
   125  */
   126 void PNGAPI
   127 png_write_chunk_data(png_structrp png_ptr, png_const_bytep data,
   128     png_size_t length)
   129 {
   130    /* Write the data, and run the CRC over it */
   131    if (png_ptr == NULL)
   132       return;
   134    if (data != NULL && length > 0)
   135    {
   136       png_write_data(png_ptr, data, length);
   138       /* Update the CRC after writing the data,
   139        * in case that the user I/O routine alters it.
   140        */
   141       png_calculate_crc(png_ptr, data, length);
   142    }
   143 }
   145 /* Finish a chunk started with png_write_chunk_header(). */
   146 void PNGAPI
   147 png_write_chunk_end(png_structrp png_ptr)
   148 {
   149    png_byte buf[4];
   151    if (png_ptr == NULL) return;
   153 #ifdef PNG_IO_STATE_SUPPORTED
   154    /* Inform the I/O callback that the chunk CRC is being written.
   155     * PNG_IO_CHUNK_CRC requires a single I/O function call.
   156     */
   157    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC;
   158 #endif
   160    /* Write the crc in a single operation */
   161    png_save_uint_32(buf, png_ptr->crc);
   163    png_write_data(png_ptr, buf, (png_size_t)4);
   164 }
   166 /* Write a PNG chunk all at once.  The type is an array of ASCII characters
   167  * representing the chunk name.  The array must be at least 4 bytes in
   168  * length, and does not need to be null terminated.  To be safe, pass the
   169  * pre-defined chunk names here, and if you need a new one, define it
   170  * where the others are defined.  The length is the length of the data.
   171  * All the data must be present.  If that is not possible, use the
   172  * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
   173  * functions instead.
   174  */
   175 static void
   176 png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
   177    png_const_bytep data, png_size_t length)
   178 {
   179    if (png_ptr == NULL)
   180       return;
   182    /* On 64 bit architectures 'length' may not fit in a png_uint_32. */
   183    if (length > PNG_UINT_31_MAX)
   184       png_error(png_ptr, "length exceeds PNG maxima");
   186    png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
   187    png_write_chunk_data(png_ptr, data, length);
   188    png_write_chunk_end(png_ptr);
   189 }
   191 /* This is the API that calls the internal function above. */
   192 void PNGAPI
   193 png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
   194    png_const_bytep data, png_size_t length)
   195 {
   196    png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
   197       length);
   198 }
   200 /* This is used below to find the size of an image to pass to png_deflate_claim,
   201  * so it only needs to be accurate if the size is less than 16384 bytes (the
   202  * point at which a lower LZ window size can be used.)
   203  */
   204 static png_alloc_size_t
   205 png_image_size(png_structrp png_ptr)
   206 {
   207    /* Only return sizes up to the maximum of a png_uint_32, do this by limiting
   208     * the width and height used to 15 bits.
   209     */
   210    png_uint_32 h = png_ptr->height;
   212    if (png_ptr->rowbytes < 32768 && h < 32768)
   213    {
   214       if (png_ptr->interlaced)
   215       {
   216          /* Interlacing makes the image larger because of the replication of
   217           * both the filter byte and the padding to a byte boundary.
   218           */
   219          png_uint_32 w = png_ptr->width;
   220          unsigned int pd = png_ptr->pixel_depth;
   221          png_alloc_size_t cb_base;
   222          int pass;
   224          for (cb_base=0, pass=0; pass<=6; ++pass)
   225          {
   226             png_uint_32 pw = PNG_PASS_COLS(w, pass);
   228             if (pw > 0)
   229                cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass);
   230          }
   232          return cb_base;
   233       }
   235       else
   236          return (png_ptr->rowbytes+1) * h;
   237    }
   239    else
   240       return 0xffffffffU;
   241 }
   243 #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
   244    /* This is the code to hack the first two bytes of the deflate stream (the
   245     * deflate header) to correct the windowBits value to match the actual data
   246     * size.  Note that the second argument is the *uncompressed* size but the
   247     * first argument is the *compressed* data (and it must be deflate
   248     * compressed.)
   249     */
   250 static void
   251 optimize_cmf(png_bytep data, png_alloc_size_t data_size)
   252 {
   253    /* Optimize the CMF field in the zlib stream.  The resultant zlib stream is
   254     * still compliant to the stream specification.
   255     */
   256    if (data_size <= 16384) /* else windowBits must be 15 */
   257    {
   258       unsigned int z_cmf = data[0];  /* zlib compression method and flags */
   260       if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
   261       {
   262          unsigned int z_cinfo;
   263          unsigned int half_z_window_size;
   265          z_cinfo = z_cmf >> 4;
   266          half_z_window_size = 1U << (z_cinfo + 7);
   268          if (data_size <= half_z_window_size) /* else no change */
   269          {
   270             unsigned int tmp;
   272             do
   273             {
   274                half_z_window_size >>= 1;
   275                --z_cinfo;
   276             }
   277             while (z_cinfo > 0 && data_size <= half_z_window_size);
   279             z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
   281             data[0] = (png_byte)z_cmf;
   282             tmp = data[1] & 0xe0;
   283             tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
   284             data[1] = (png_byte)tmp;
   285          }
   286       }
   287    }
   288 }
   289 #else
   290 #  define optimize_cmf(dp,dl) ((void)0)
   291 #endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
   293 /* Initialize the compressor for the appropriate type of compression. */
   294 static int
   295 png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
   296    png_alloc_size_t data_size)
   297 {
   298    if (png_ptr->zowner != 0)
   299    {
   300       char msg[64];
   302       PNG_STRING_FROM_CHUNK(msg, owner);
   303       msg[4] = ':';
   304       msg[5] = ' ';
   305       PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner);
   306       /* So the message that results is "<chunk> using zstream"; this is an
   307        * internal error, but is very useful for debugging.  i18n requirements
   308        * are minimal.
   309        */
   310       (void)png_safecat(msg, (sizeof msg), 10, " using zstream");
   311 #     if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
   312          png_warning(png_ptr, msg);
   314          /* Attempt sane error recovery */
   315          if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */
   316          {
   317             png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT");
   318             return Z_STREAM_ERROR;
   319          }
   321          png_ptr->zowner = 0;
   322 #     else
   323          png_error(png_ptr, msg);
   324 #     endif
   325    }
   327    {
   328       int level = png_ptr->zlib_level;
   329       int method = png_ptr->zlib_method;
   330       int windowBits = png_ptr->zlib_window_bits;
   331       int memLevel = png_ptr->zlib_mem_level;
   332       int strategy; /* set below */
   333       int ret; /* zlib return code */
   335       if (owner == png_IDAT)
   336       {
   337          if (png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY)
   338             strategy = png_ptr->zlib_strategy;
   340          else if (png_ptr->do_filter != PNG_FILTER_NONE)
   341             strategy = PNG_Z_DEFAULT_STRATEGY;
   343          else
   344             strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY;
   345       }
   347       else
   348       {
   349 #        ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
   350             level = png_ptr->zlib_text_level;
   351             method = png_ptr->zlib_text_method;
   352             windowBits = png_ptr->zlib_text_window_bits;
   353             memLevel = png_ptr->zlib_text_mem_level;
   354             strategy = png_ptr->zlib_text_strategy;
   355 #        else
   356             /* If customization is not supported the values all come from the
   357              * IDAT values except for the strategy, which is fixed to the
   358              * default.  (This is the pre-1.6.0 behavior too, although it was
   359              * implemented in a very different way.)
   360              */
   361             strategy = Z_DEFAULT_STRATEGY;
   362 #        endif
   363       }
   365       /* Adjust 'windowBits' down if larger than 'data_size'; to stop this
   366        * happening just pass 32768 as the data_size parameter.  Notice that zlib
   367        * requires an extra 262 bytes in the window in addition to the data to be
   368        * able to see the whole of the data, so if data_size+262 takes us to the
   369        * next windowBits size we need to fix up the value later.  (Because even
   370        * though deflate needs the extra window, inflate does not!)
   371        */
   372       if (data_size <= 16384)
   373       {
   374          /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to
   375           * work round a Microsoft Visual C misbehavior which, contrary to C-90,
   376           * widens the result of the following shift to 64-bits if (and,
   377           * apparently, only if) it is used in a test.
   378           */
   379          unsigned int half_window_size = 1U << (windowBits-1);
   381          while (data_size + 262 <= half_window_size)
   382          {
   383             half_window_size >>= 1;
   384             --windowBits;
   385          }
   386       }
   388       /* Check against the previous initialized values, if any. */
   389       if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) &&
   390          (png_ptr->zlib_set_level != level ||
   391          png_ptr->zlib_set_method != method ||
   392          png_ptr->zlib_set_window_bits != windowBits ||
   393          png_ptr->zlib_set_mem_level != memLevel ||
   394          png_ptr->zlib_set_strategy != strategy))
   395       {
   396          if (deflateEnd(&png_ptr->zstream) != Z_OK)
   397             png_warning(png_ptr, "deflateEnd failed (ignored)");
   399          png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED;
   400       }
   402       /* For safety clear out the input and output pointers (currently zlib
   403        * doesn't use them on Init, but it might in the future).
   404        */
   405       png_ptr->zstream.next_in = NULL;
   406       png_ptr->zstream.avail_in = 0;
   407       png_ptr->zstream.next_out = NULL;
   408       png_ptr->zstream.avail_out = 0;
   410       /* Now initialize if required, setting the new parameters, otherwise just
   411        * to a simple reset to the previous parameters.
   412        */
   413       if (png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED)
   414          ret = deflateReset(&png_ptr->zstream);
   416       else
   417       {
   418          ret = deflateInit2(&png_ptr->zstream, level, method, windowBits,
   419             memLevel, strategy);
   421          if (ret == Z_OK)
   422             png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
   423       }
   425       /* The return code is from either deflateReset or deflateInit2; they have
   426        * pretty much the same set of error codes.
   427        */
   428       if (ret == Z_OK)
   429          png_ptr->zowner = owner;
   431       else
   432          png_zstream_error(png_ptr, ret);
   434       return ret;
   435    }
   436 }
   438 /* Clean up (or trim) a linked list of compression buffers. */
   439 void /* PRIVATE */
   440 png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp)
   441 {
   442    png_compression_bufferp list = *listp;
   444    if (list != NULL)
   445    {
   446       *listp = NULL;
   448       do
   449       {
   450          png_compression_bufferp next = list->next;
   452          png_free(png_ptr, list);
   453          list = next;
   454       }
   455       while (list != NULL);
   456    }
   457 }
   459 #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
   460 /* This pair of functions encapsulates the operation of (a) compressing a
   461  * text string, and (b) issuing it later as a series of chunk data writes.
   462  * The compression_state structure is shared context for these functions
   463  * set up by the caller to allow access to the relevant local variables.
   464  *
   465  * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size
   466  * temporary buffers.  From 1.6.0 it is retained in png_struct so that it will
   467  * be correctly freed in the event of a write error (previous implementations
   468  * just leaked memory.)
   469  */
   470 typedef struct
   471 {
   472    png_const_bytep      input;        /* The uncompressed input data */
   473    png_alloc_size_t     input_len;    /* Its length */
   474    png_uint_32          output_len;   /* Final compressed length */
   475    png_byte             output[1024]; /* First block of output */
   476 } compression_state;
   478 static void
   479 png_text_compress_init(compression_state *comp, png_const_bytep input,
   480    png_alloc_size_t input_len)
   481 {
   482    comp->input = input;
   483    comp->input_len = input_len;
   484    comp->output_len = 0;
   485 }
   487 /* Compress the data in the compression state input */
   488 static int
   489 png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
   490    compression_state *comp, png_uint_32 prefix_len)
   491 {
   492    int ret;
   494    /* To find the length of the output it is necessary to first compress the
   495     * input, the result is buffered rather than using the two-pass algorithm
   496     * that is used on the inflate side; deflate is assumed to be slower and a
   497     * PNG writer is assumed to have more memory available than a PNG reader.
   498     *
   499     * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an
   500     * upper limit on the output size, but it is always bigger than the input
   501     * size so it is likely to be more efficient to use this linked-list
   502     * approach.
   503     */
   504    ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len);
   506    if (ret != Z_OK)
   507       return ret;
   509    /* Set up the compression buffers, we need a loop here to avoid overflowing a
   510     * uInt.  Use ZLIB_IO_MAX to limit the input.  The output is always limited
   511     * by the output buffer size, so there is no need to check that.  Since this
   512     * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits
   513     * in size.
   514     */
   515    {
   516       png_compression_bufferp *end = &png_ptr->zbuffer_list;
   517       png_alloc_size_t input_len = comp->input_len; /* may be zero! */
   518       png_uint_32 output_len;
   520       /* zlib updates these for us: */
   521       png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input);
   522       png_ptr->zstream.avail_in = 0; /* Set below */
   523       png_ptr->zstream.next_out = comp->output;
   524       png_ptr->zstream.avail_out = (sizeof comp->output);
   526       output_len = png_ptr->zstream.avail_out;
   528       do
   529       {
   530          uInt avail_in = ZLIB_IO_MAX;
   532          if (avail_in > input_len)
   533             avail_in = (uInt)input_len;
   535          input_len -= avail_in;
   537          png_ptr->zstream.avail_in = avail_in;
   539          if (png_ptr->zstream.avail_out == 0)
   540          {
   541             png_compression_buffer *next;
   543             /* Chunk data is limited to 2^31 bytes in length, so the prefix
   544              * length must be counted here.
   545              */
   546             if (output_len + prefix_len > PNG_UINT_31_MAX)
   547             {
   548                ret = Z_MEM_ERROR;
   549                break;
   550             }
   552             /* Need a new (malloc'ed) buffer, but there may be one present
   553              * already.
   554              */
   555             next = *end;
   556             if (next == NULL)
   557             {
   558                next = png_voidcast(png_compression_bufferp, png_malloc_base
   559                   (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
   561                if (next == NULL)
   562                {
   563                   ret = Z_MEM_ERROR;
   564                   break;
   565                }
   567                /* Link in this buffer (so that it will be freed later) */
   568                next->next = NULL;
   569                *end = next;
   570             }
   572             png_ptr->zstream.next_out = next->output;
   573             png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
   574             output_len += png_ptr->zstream.avail_out;
   576             /* Move 'end' to the next buffer pointer. */
   577             end = &next->next;
   578          }
   580          /* Compress the data */
   581          ret = deflate(&png_ptr->zstream,
   582             input_len > 0 ? Z_NO_FLUSH : Z_FINISH);
   584          /* Claw back input data that was not consumed (because avail_in is
   585           * reset above every time round the loop).
   586           */
   587          input_len += png_ptr->zstream.avail_in;
   588          png_ptr->zstream.avail_in = 0; /* safety */
   589       }
   590       while (ret == Z_OK);
   592       /* There may be some space left in the last output buffer, this needs to
   593        * be subtracted from output_len.
   594        */
   595       output_len -= png_ptr->zstream.avail_out;
   596       png_ptr->zstream.avail_out = 0; /* safety */
   597       comp->output_len = output_len;
   599       /* Now double check the output length, put in a custom message if it is
   600        * too long.  Otherwise ensure the z_stream::msg pointer is set to
   601        * something.
   602        */
   603       if (output_len + prefix_len >= PNG_UINT_31_MAX)
   604       {
   605          png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long");
   606          ret = Z_MEM_ERROR;
   607       }
   609       else
   610          png_zstream_error(png_ptr, ret);
   612       /* Reset zlib for another zTXt/iTXt or image data */
   613       png_ptr->zowner = 0;
   615       /* The only success case is Z_STREAM_END, input_len must be 0, if not this
   616        * is an internal error.
   617        */
   618       if (ret == Z_STREAM_END && input_len == 0)
   619       {
   620          /* Fix up the deflate header, if required */
   621          optimize_cmf(comp->output, comp->input_len);
   623          /* But Z_OK is returned, not Z_STREAM_END; this allows the claim
   624           * function above to return Z_STREAM_END on an error (though it never
   625           * does in the current versions of zlib.)
   626           */
   627          return Z_OK;
   628       }
   630       else
   631          return ret;
   632    }
   633 }
   635 /* Ship the compressed text out via chunk writes */
   636 static void
   637 png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
   638 {
   639    png_uint_32 output_len = comp->output_len;
   640    png_const_bytep output = comp->output;
   641    png_uint_32 avail = (sizeof comp->output);
   642    png_compression_buffer *next = png_ptr->zbuffer_list;
   644    for (;;)
   645    {
   646       if (avail > output_len)
   647          avail = output_len;
   649       png_write_chunk_data(png_ptr, output, avail);
   651       output_len -= avail;
   653       if (output_len == 0 || next == NULL)
   654          break;
   656       avail = png_ptr->zbuffer_size;
   657       output = next->output;
   658       next = next->next;
   659    }
   661    /* This is an internal error; 'next' must have been NULL! */
   662    if (output_len > 0)
   663       png_error(png_ptr, "error writing ancillary chunked compressed data");
   664 }
   665 #endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
   667 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
   668     defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
   669 /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
   670  * and if invalid, correct the keyword rather than discarding the entire
   671  * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
   672  * length, forbids leading or trailing whitespace, multiple internal spaces,
   673  * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
   674  *
   675  * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
   676  * trailing '\0').  If this routine returns 0 then there was no keyword, or a
   677  * valid one could not be generated, and the caller must png_error.
   678  */
   679 static png_uint_32
   680 png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
   681 {
   682    png_const_charp orig_key = key;
   683    png_uint_32 key_len = 0;
   684    int bad_character = 0;
   685    int space = 1;
   687    png_debug(1, "in png_check_keyword");
   689    if (key == NULL)
   690    {
   691       *new_key = 0;
   692       return 0;
   693    }
   695    while (*key && key_len < 79)
   696    {
   697       png_byte ch = (png_byte)(0xff & *key++);
   699       if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
   700          *new_key++ = ch, ++key_len, space = 0;
   702       else if (!space)
   703       {
   704          /* A space or an invalid character when one wasn't seen immediately
   705           * before; output just a space.
   706           */
   707          *new_key++ = 32, ++key_len, space = 1;
   709          /* If the character was not a space then it is invalid. */
   710          if (ch != 32)
   711             bad_character = ch;
   712       }
   714       else if (!bad_character)
   715          bad_character = ch; /* just skip it, record the first error */
   716    }
   718    if (key_len > 0 && space) /* trailing space */
   719    {
   720       --key_len, --new_key;
   721       if (!bad_character)
   722          bad_character = 32;
   723    }
   725    /* Terminate the keyword */
   726    *new_key = 0;
   728    if (key_len == 0)
   729       return 0;
   731    /* Try to only output one warning per keyword: */
   732    if (*key) /* keyword too long */
   733       png_warning(png_ptr, "keyword truncated");
   735    else if (bad_character)
   736    {
   737       PNG_WARNING_PARAMETERS(p)
   739       png_warning_parameter(p, 1, orig_key);
   740       png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
   742       png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
   743    }
   745    return key_len;
   746 }
   747 #endif
   749 /* Write the IHDR chunk, and update the png_struct with the necessary
   750  * information.  Note that the rest of this code depends upon this
   751  * information being correct.
   752  */
   753 void /* PRIVATE */
   754 png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
   755     int bit_depth, int color_type, int compression_type, int filter_type,
   756     int interlace_type)
   757 {
   758    png_byte buf[13]; /* Buffer to store the IHDR info */
   760    png_debug(1, "in png_write_IHDR");
   762    /* Check that we have valid input data from the application info */
   763    switch (color_type)
   764    {
   765       case PNG_COLOR_TYPE_GRAY:
   766          switch (bit_depth)
   767          {
   768             case 1:
   769             case 2:
   770             case 4:
   771             case 8:
   772 #ifdef PNG_WRITE_16BIT_SUPPORTED
   773             case 16:
   774 #endif
   775                png_ptr->channels = 1; break;
   777             default:
   778                png_error(png_ptr,
   779                    "Invalid bit depth for grayscale image");
   780          }
   781          break;
   783       case PNG_COLOR_TYPE_RGB:
   784 #ifdef PNG_WRITE_16BIT_SUPPORTED
   785          if (bit_depth != 8 && bit_depth != 16)
   786 #else
   787          if (bit_depth != 8)
   788 #endif
   789             png_error(png_ptr, "Invalid bit depth for RGB image");
   791          png_ptr->channels = 3;
   792          break;
   794       case PNG_COLOR_TYPE_PALETTE:
   795          switch (bit_depth)
   796          {
   797             case 1:
   798             case 2:
   799             case 4:
   800             case 8:
   801                png_ptr->channels = 1;
   802                break;
   804             default:
   805                png_error(png_ptr, "Invalid bit depth for paletted image");
   806          }
   807          break;
   809       case PNG_COLOR_TYPE_GRAY_ALPHA:
   810          if (bit_depth != 8 && bit_depth != 16)
   811             png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
   813          png_ptr->channels = 2;
   814          break;
   816       case PNG_COLOR_TYPE_RGB_ALPHA:
   817 #ifdef PNG_WRITE_16BIT_SUPPORTED
   818          if (bit_depth != 8 && bit_depth != 16)
   819 #else
   820          if (bit_depth != 8)
   821 #endif
   822             png_error(png_ptr, "Invalid bit depth for RGBA image");
   824          png_ptr->channels = 4;
   825          break;
   827       default:
   828          png_error(png_ptr, "Invalid image color type specified");
   829    }
   831    if (compression_type != PNG_COMPRESSION_TYPE_BASE)
   832    {
   833       png_warning(png_ptr, "Invalid compression type specified");
   834       compression_type = PNG_COMPRESSION_TYPE_BASE;
   835    }
   837    /* Write filter_method 64 (intrapixel differencing) only if
   838     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
   839     * 2. Libpng did not write a PNG signature (this filter_method is only
   840     *    used in PNG datastreams that are embedded in MNG datastreams) and
   841     * 3. The application called png_permit_mng_features with a mask that
   842     *    included PNG_FLAG_MNG_FILTER_64 and
   843     * 4. The filter_method is 64 and
   844     * 5. The color_type is RGB or RGBA
   845     */
   846    if (
   847 #ifdef PNG_MNG_FEATURES_SUPPORTED
   848        !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
   849        ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
   850        (color_type == PNG_COLOR_TYPE_RGB ||
   851         color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
   852        (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
   853 #endif
   854        filter_type != PNG_FILTER_TYPE_BASE)
   855    {
   856       png_warning(png_ptr, "Invalid filter type specified");
   857       filter_type = PNG_FILTER_TYPE_BASE;
   858    }
   860 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
   861    if (interlace_type != PNG_INTERLACE_NONE &&
   862        interlace_type != PNG_INTERLACE_ADAM7)
   863    {
   864       png_warning(png_ptr, "Invalid interlace type specified");
   865       interlace_type = PNG_INTERLACE_ADAM7;
   866    }
   867 #else
   868    interlace_type=PNG_INTERLACE_NONE;
   869 #endif
   871    /* Save the relevent information */
   872    png_ptr->bit_depth = (png_byte)bit_depth;
   873    png_ptr->color_type = (png_byte)color_type;
   874    png_ptr->interlaced = (png_byte)interlace_type;
   875 #ifdef PNG_MNG_FEATURES_SUPPORTED
   876    png_ptr->filter_type = (png_byte)filter_type;
   877 #endif
   878    png_ptr->compression_type = (png_byte)compression_type;
   879    png_ptr->width = width;
   880    png_ptr->height = height;
   882    png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
   883    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
   884    /* Set the usr info, so any transformations can modify it */
   885    png_ptr->usr_width = png_ptr->width;
   886    png_ptr->usr_bit_depth = png_ptr->bit_depth;
   887    png_ptr->usr_channels = png_ptr->channels;
   889    /* Pack the header information into the buffer */
   890    png_save_uint_32(buf, width);
   891    png_save_uint_32(buf + 4, height);
   892    buf[8] = (png_byte)bit_depth;
   893    buf[9] = (png_byte)color_type;
   894    buf[10] = (png_byte)compression_type;
   895    buf[11] = (png_byte)filter_type;
   896    buf[12] = (png_byte)interlace_type;
   898    /* Write the chunk */
   899    png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
   901 #ifdef PNG_WRITE_APNG_SUPPORTED
   902    png_ptr->first_frame_width = width;
   903    png_ptr->first_frame_height = height;
   904 #endif
   906    if (!(png_ptr->do_filter))
   907    {
   908       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
   909           png_ptr->bit_depth < 8)
   910          png_ptr->do_filter = PNG_FILTER_NONE;
   912       else
   913          png_ptr->do_filter = PNG_ALL_FILTERS;
   914    }
   916    png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
   917 }
   919 /* Write the palette.  We are careful not to trust png_color to be in the
   920  * correct order for PNG, so people can redefine it to any convenient
   921  * structure.
   922  */
   923 void /* PRIVATE */
   924 png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
   925     png_uint_32 num_pal)
   926 {
   927    png_uint_32 i;
   928    png_const_colorp pal_ptr;
   929    png_byte buf[3];
   931    png_debug(1, "in png_write_PLTE");
   933    if ((
   934 #ifdef PNG_MNG_FEATURES_SUPPORTED
   935        !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
   936 #endif
   937        num_pal == 0) || num_pal > 256)
   938    {
   939       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   940       {
   941          png_error(png_ptr, "Invalid number of colors in palette");
   942       }
   944       else
   945       {
   946          png_warning(png_ptr, "Invalid number of colors in palette");
   947          return;
   948       }
   949    }
   951    if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
   952    {
   953       png_warning(png_ptr,
   954           "Ignoring request to write a PLTE chunk in grayscale PNG");
   956       return;
   957    }
   959    png_ptr->num_palette = (png_uint_16)num_pal;
   960    png_debug1(3, "num_palette = %d", png_ptr->num_palette);
   962    png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
   963 #ifdef PNG_POINTER_INDEXING_SUPPORTED
   965    for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
   966    {
   967       buf[0] = pal_ptr->red;
   968       buf[1] = pal_ptr->green;
   969       buf[2] = pal_ptr->blue;
   970       png_write_chunk_data(png_ptr, buf, (png_size_t)3);
   971    }
   973 #else
   974    /* This is a little slower but some buggy compilers need to do this
   975     * instead
   976     */
   977    pal_ptr=palette;
   979    for (i = 0; i < num_pal; i++)
   980    {
   981       buf[0] = pal_ptr[i].red;
   982       buf[1] = pal_ptr[i].green;
   983       buf[2] = pal_ptr[i].blue;
   984       png_write_chunk_data(png_ptr, buf, (png_size_t)3);
   985    }
   987 #endif
   988    png_write_chunk_end(png_ptr);
   989    png_ptr->mode |= PNG_HAVE_PLTE;
   990 }
   992 /* This is similar to png_text_compress, above, except that it does not require
   993  * all of the data at once and, instead of buffering the compressed result,
   994  * writes it as IDAT chunks.  Unlike png_text_compress it *can* png_error out
   995  * because it calls the write interface.  As a result it does its own error
   996  * reporting and does not return an error code.  In the event of error it will
   997  * just call png_error.  The input data length may exceed 32-bits.  The 'flush'
   998  * parameter is exactly the same as that to deflate, with the following
   999  * meanings:
  1001  * Z_NO_FLUSH: normal incremental output of compressed data
  1002  * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush
  1003  * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
  1005  * The routine manages the acquire and release of the png_ptr->zstream by
  1006  * checking and (at the end) clearing png_ptr->zowner, it does some sanity
  1007  * checks on the 'mode' flags while doing this.
  1008  */
  1009 void /* PRIVATE */
  1010 png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
  1011    png_alloc_size_t input_len, int flush)
  1013    if (png_ptr->zowner != png_IDAT)
  1015       /* First time.   Ensure we have a temporary buffer for compression and
  1016        * trim the buffer list if it has more than one entry to free memory.
  1017        * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been
  1018        * created at this point, but the check here is quick and safe.
  1019        */
  1020       if (png_ptr->zbuffer_list == NULL)
  1022          png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp,
  1023             png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
  1024          png_ptr->zbuffer_list->next = NULL;
  1027       else
  1028          png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next);
  1030       /* It is a terminal error if we can't claim the zstream. */
  1031       if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK)
  1032          png_error(png_ptr, png_ptr->zstream.msg);
  1034       /* The output state is maintained in png_ptr->zstream, so it must be
  1035        * initialized here after the claim.
  1036        */
  1037       png_ptr->zstream.next_out = png_ptr->zbuffer_list->output;
  1038       png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
  1041    /* Now loop reading and writing until all the input is consumed or an error
  1042     * terminates the operation.  The _out values are maintained across calls to
  1043     * this function, but the input must be reset each time.
  1044     */
  1045    png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
  1046    png_ptr->zstream.avail_in = 0; /* set below */
  1047    for (;;)
  1049       int ret;
  1051       /* INPUT: from the row data */
  1052       uInt avail = ZLIB_IO_MAX;
  1054       if (avail > input_len)
  1055          avail = (uInt)input_len; /* safe because of the check */
  1057       png_ptr->zstream.avail_in = avail;
  1058       input_len -= avail;
  1060       ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush);
  1062       /* Include as-yet unconsumed input */
  1063       input_len += png_ptr->zstream.avail_in;
  1064       png_ptr->zstream.avail_in = 0;
  1066       /* OUTPUT: write complete IDAT chunks when avail_out drops to zero, note
  1067        * that these two zstream fields are preserved across the calls, therefore
  1068        * there is no need to set these up on entry to the loop.
  1069        */
  1070       if (png_ptr->zstream.avail_out == 0)
  1072          png_bytep data = png_ptr->zbuffer_list->output;
  1073          uInt size = png_ptr->zbuffer_size;
  1075          /* Write an IDAT containing the data then reset the buffer.  The
  1076           * first IDAT may need deflate header optimization.
  1077           */
  1078 #        ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
  1079             if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
  1080                png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
  1081                optimize_cmf(data, png_image_size(png_ptr));
  1082 #        endif
  1084 #        ifdef PNG_WRITE_APNG_SUPPORTED
  1085          if (png_ptr->num_frames_written == 0)
  1086 #        endif
  1087          png_write_complete_chunk(png_ptr, png_IDAT, data, size);
  1088 #        ifdef PNG_WRITE_APNG_SUPPORTED
  1089          else
  1090             png_write_fdAT(png_ptr, data, size);
  1091 #        endif /* PNG_WRITE_APNG_SUPPORTED */
  1093          png_ptr->mode |= PNG_HAVE_IDAT;
  1095          png_ptr->zstream.next_out = data;
  1096          png_ptr->zstream.avail_out = size;
  1098          /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with
  1099           * the same flush parameter until it has finished output, for NO_FLUSH
  1100           * it doesn't matter.
  1101           */
  1102          if (ret == Z_OK && flush != Z_NO_FLUSH)
  1103             continue;
  1106       /* The order of these checks doesn't matter much; it just effect which
  1107        * possible error might be detected if multiple things go wrong at once.
  1108        */
  1109       if (ret == Z_OK) /* most likely return code! */
  1111          /* If all the input has been consumed then just return.  If Z_FINISH
  1112           * was used as the flush parameter something has gone wrong if we get
  1113           * here.
  1114           */
  1115          if (input_len == 0)
  1117             if (flush == Z_FINISH)
  1118                png_error(png_ptr, "Z_OK on Z_FINISH with output space");
  1120             return;
  1124       else if (ret == Z_STREAM_END && flush == Z_FINISH)
  1126          /* This is the end of the IDAT data; any pending output must be
  1127           * flushed.  For small PNG files we may still be at the beginning.
  1128           */
  1129          png_bytep data = png_ptr->zbuffer_list->output;
  1130          uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out;
  1132 #        ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
  1133             if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
  1134                png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
  1135                optimize_cmf(data, png_image_size(png_ptr));
  1136 #        endif
  1138 #        ifdef PNG_WRITE_APNG_SUPPORTED
  1139          if (png_ptr->num_frames_written == 0)
  1140 #        endif
  1141          png_write_complete_chunk(png_ptr, png_IDAT, data, size);
  1142 #        ifdef PNG_WRITE_APNG_SUPPORTED
  1143          else
  1144             png_write_fdAT(png_ptr, data, size);
  1145 #        endif /* PNG_WRITE_APNG_SUPPORTED */
  1147          png_ptr->zstream.avail_out = 0;
  1148          png_ptr->zstream.next_out = NULL;
  1149          png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
  1151          png_ptr->zowner = 0; /* Release the stream */
  1152          return;
  1155       else
  1157          /* This is an error condition. */
  1158          png_zstream_error(png_ptr, ret);
  1159          png_error(png_ptr, png_ptr->zstream.msg);
  1164 /* Write an IEND chunk */
  1165 void /* PRIVATE */
  1166 png_write_IEND(png_structrp png_ptr)
  1168    png_debug(1, "in png_write_IEND");
  1170    png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0);
  1171    png_ptr->mode |= PNG_HAVE_IEND;
  1174 #ifdef PNG_WRITE_gAMA_SUPPORTED
  1175 /* Write a gAMA chunk */
  1176 void /* PRIVATE */
  1177 png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
  1179    png_byte buf[4];
  1181    png_debug(1, "in png_write_gAMA");
  1183    /* file_gamma is saved in 1/100,000ths */
  1184    png_save_uint_32(buf, (png_uint_32)file_gamma);
  1185    png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
  1187 #endif
  1189 #ifdef PNG_WRITE_sRGB_SUPPORTED
  1190 /* Write a sRGB chunk */
  1191 void /* PRIVATE */
  1192 png_write_sRGB(png_structrp png_ptr, int srgb_intent)
  1194    png_byte buf[1];
  1196    png_debug(1, "in png_write_sRGB");
  1198    if (srgb_intent >= PNG_sRGB_INTENT_LAST)
  1199       png_warning(png_ptr,
  1200           "Invalid sRGB rendering intent specified");
  1202    buf[0]=(png_byte)srgb_intent;
  1203    png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1);
  1205 #endif
  1207 #ifdef PNG_WRITE_iCCP_SUPPORTED
  1208 /* Write an iCCP chunk */
  1209 void /* PRIVATE */
  1210 png_write_iCCP(png_structrp png_ptr, png_const_charp name,
  1211     png_const_bytep profile)
  1213    png_uint_32 name_len;
  1214    png_uint_32 profile_len;
  1215    png_byte new_name[81]; /* 1 byte for the compression byte */
  1216    compression_state comp;
  1218    png_debug(1, "in png_write_iCCP");
  1220    /* These are all internal problems: the profile should have been checked
  1221     * before when it was stored.
  1222     */
  1223    if (profile == NULL)
  1224       png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */
  1226    profile_len = png_get_uint_32(profile);
  1228    if (profile_len < 132)
  1229       png_error(png_ptr, "ICC profile too short");
  1231    if (profile_len & 0x03)
  1232       png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
  1235       png_uint_32 embedded_profile_len = png_get_uint_32(profile);
  1237       if (profile_len != embedded_profile_len)
  1238          png_error(png_ptr, "Profile length does not match profile");
  1241    name_len = png_check_keyword(png_ptr, name, new_name);
  1243    if (name_len == 0)
  1244       png_error(png_ptr, "iCCP: invalid keyword");
  1246    new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE;
  1248    /* Make sure we include the NULL after the name and the compression type */
  1249    ++name_len;
  1251    png_text_compress_init(&comp, profile, profile_len);
  1253    /* Allow for keyword terminator and compression byte */
  1254    if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK)
  1255       png_error(png_ptr, png_ptr->zstream.msg);
  1257    png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);
  1259    png_write_chunk_data(png_ptr, new_name, name_len);
  1261    png_write_compressed_data_out(png_ptr, &comp);
  1263    png_write_chunk_end(png_ptr);
  1265 #endif
  1267 #ifdef PNG_WRITE_sPLT_SUPPORTED
  1268 /* Write a sPLT chunk */
  1269 void /* PRIVATE */
  1270 png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
  1272    png_uint_32 name_len;
  1273    png_byte new_name[80];
  1274    png_byte entrybuf[10];
  1275    png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
  1276    png_size_t palette_size = entry_size * spalette->nentries;
  1277    png_sPLT_entryp ep;
  1278 #ifndef PNG_POINTER_INDEXING_SUPPORTED
  1279    int i;
  1280 #endif
  1282    png_debug(1, "in png_write_sPLT");
  1284    name_len = png_check_keyword(png_ptr, spalette->name, new_name);
  1286    if (name_len == 0)
  1287       png_error(png_ptr, "sPLT: invalid keyword");
  1289    /* Make sure we include the NULL after the name */
  1290    png_write_chunk_header(png_ptr, png_sPLT,
  1291        (png_uint_32)(name_len + 2 + palette_size));
  1293    png_write_chunk_data(png_ptr, (png_bytep)new_name,
  1294        (png_size_t)(name_len + 1));
  1296    png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1);
  1298    /* Loop through each palette entry, writing appropriately */
  1299 #ifdef PNG_POINTER_INDEXING_SUPPORTED
  1300    for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
  1302       if (spalette->depth == 8)
  1304          entrybuf[0] = (png_byte)ep->red;
  1305          entrybuf[1] = (png_byte)ep->green;
  1306          entrybuf[2] = (png_byte)ep->blue;
  1307          entrybuf[3] = (png_byte)ep->alpha;
  1308          png_save_uint_16(entrybuf + 4, ep->frequency);
  1311       else
  1313          png_save_uint_16(entrybuf + 0, ep->red);
  1314          png_save_uint_16(entrybuf + 2, ep->green);
  1315          png_save_uint_16(entrybuf + 4, ep->blue);
  1316          png_save_uint_16(entrybuf + 6, ep->alpha);
  1317          png_save_uint_16(entrybuf + 8, ep->frequency);
  1320       png_write_chunk_data(png_ptr, entrybuf, entry_size);
  1322 #else
  1323    ep=spalette->entries;
  1324    for (i = 0; i>spalette->nentries; i++)
  1326       if (spalette->depth == 8)
  1328          entrybuf[0] = (png_byte)ep[i].red;
  1329          entrybuf[1] = (png_byte)ep[i].green;
  1330          entrybuf[2] = (png_byte)ep[i].blue;
  1331          entrybuf[3] = (png_byte)ep[i].alpha;
  1332          png_save_uint_16(entrybuf + 4, ep[i].frequency);
  1335       else
  1337          png_save_uint_16(entrybuf + 0, ep[i].red);
  1338          png_save_uint_16(entrybuf + 2, ep[i].green);
  1339          png_save_uint_16(entrybuf + 4, ep[i].blue);
  1340          png_save_uint_16(entrybuf + 6, ep[i].alpha);
  1341          png_save_uint_16(entrybuf + 8, ep[i].frequency);
  1344       png_write_chunk_data(png_ptr, entrybuf, entry_size);
  1346 #endif
  1348    png_write_chunk_end(png_ptr);
  1350 #endif
  1352 #ifdef PNG_WRITE_sBIT_SUPPORTED
  1353 /* Write the sBIT chunk */
  1354 void /* PRIVATE */
  1355 png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
  1357    png_byte buf[4];
  1358    png_size_t size;
  1360    png_debug(1, "in png_write_sBIT");
  1362    /* Make sure we don't depend upon the order of PNG_COLOR_8 */
  1363    if (color_type & PNG_COLOR_MASK_COLOR)
  1365       png_byte maxbits;
  1367       maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
  1368           png_ptr->usr_bit_depth);
  1370       if (sbit->red == 0 || sbit->red > maxbits ||
  1371           sbit->green == 0 || sbit->green > maxbits ||
  1372           sbit->blue == 0 || sbit->blue > maxbits)
  1374          png_warning(png_ptr, "Invalid sBIT depth specified");
  1375          return;
  1378       buf[0] = sbit->red;
  1379       buf[1] = sbit->green;
  1380       buf[2] = sbit->blue;
  1381       size = 3;
  1384    else
  1386       if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
  1388          png_warning(png_ptr, "Invalid sBIT depth specified");
  1389          return;
  1392       buf[0] = sbit->gray;
  1393       size = 1;
  1396    if (color_type & PNG_COLOR_MASK_ALPHA)
  1398       if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
  1400          png_warning(png_ptr, "Invalid sBIT depth specified");
  1401          return;
  1404       buf[size++] = sbit->alpha;
  1407    png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
  1409 #endif
  1411 #ifdef PNG_WRITE_cHRM_SUPPORTED
  1412 /* Write the cHRM chunk */
  1413 void /* PRIVATE */
  1414 png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy)
  1416    png_byte buf[32];
  1418    png_debug(1, "in png_write_cHRM");
  1420    /* Each value is saved in 1/100,000ths */
  1421    png_save_int_32(buf,      xy->whitex);
  1422    png_save_int_32(buf +  4, xy->whitey);
  1424    png_save_int_32(buf +  8, xy->redx);
  1425    png_save_int_32(buf + 12, xy->redy);
  1427    png_save_int_32(buf + 16, xy->greenx);
  1428    png_save_int_32(buf + 20, xy->greeny);
  1430    png_save_int_32(buf + 24, xy->bluex);
  1431    png_save_int_32(buf + 28, xy->bluey);
  1433    png_write_complete_chunk(png_ptr, png_cHRM, buf, 32);
  1435 #endif
  1437 #ifdef PNG_WRITE_tRNS_SUPPORTED
  1438 /* Write the tRNS chunk */
  1439 void /* PRIVATE */
  1440 png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
  1441     png_const_color_16p tran, int num_trans, int color_type)
  1443    png_byte buf[6];
  1445    png_debug(1, "in png_write_tRNS");
  1447    if (color_type == PNG_COLOR_TYPE_PALETTE)
  1449       if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
  1451          png_app_warning(png_ptr,
  1452              "Invalid number of transparent colors specified");
  1453          return;
  1456       /* Write the chunk out as it is */
  1457       png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
  1458          (png_size_t)num_trans);
  1461    else if (color_type == PNG_COLOR_TYPE_GRAY)
  1463       /* One 16 bit value */
  1464       if (tran->gray >= (1 << png_ptr->bit_depth))
  1466          png_app_warning(png_ptr,
  1467              "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
  1469          return;
  1472       png_save_uint_16(buf, tran->gray);
  1473       png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
  1476    else if (color_type == PNG_COLOR_TYPE_RGB)
  1478       /* Three 16 bit values */
  1479       png_save_uint_16(buf, tran->red);
  1480       png_save_uint_16(buf + 2, tran->green);
  1481       png_save_uint_16(buf + 4, tran->blue);
  1482 #ifdef PNG_WRITE_16BIT_SUPPORTED
  1483       if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
  1484 #else
  1485       if (buf[0] | buf[2] | buf[4])
  1486 #endif
  1488          png_app_warning(png_ptr,
  1489            "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
  1490          return;
  1493       png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
  1496    else
  1498       png_app_warning(png_ptr, "Can't write tRNS with an alpha channel");
  1501 #endif
  1503 #ifdef PNG_WRITE_bKGD_SUPPORTED
  1504 /* Write the background chunk */
  1505 void /* PRIVATE */
  1506 png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
  1508    png_byte buf[6];
  1510    png_debug(1, "in png_write_bKGD");
  1512    if (color_type == PNG_COLOR_TYPE_PALETTE)
  1514       if (
  1515 #ifdef PNG_MNG_FEATURES_SUPPORTED
  1516           (png_ptr->num_palette ||
  1517           (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
  1518 #endif
  1519          back->index >= png_ptr->num_palette)
  1521          png_warning(png_ptr, "Invalid background palette index");
  1522          return;
  1525       buf[0] = back->index;
  1526       png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
  1529    else if (color_type & PNG_COLOR_MASK_COLOR)
  1531       png_save_uint_16(buf, back->red);
  1532       png_save_uint_16(buf + 2, back->green);
  1533       png_save_uint_16(buf + 4, back->blue);
  1534 #ifdef PNG_WRITE_16BIT_SUPPORTED
  1535       if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
  1536 #else
  1537       if (buf[0] | buf[2] | buf[4])
  1538 #endif
  1540          png_warning(png_ptr,
  1541              "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
  1543          return;
  1546       png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
  1549    else
  1551       if (back->gray >= (1 << png_ptr->bit_depth))
  1553          png_warning(png_ptr,
  1554              "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
  1556          return;
  1559       png_save_uint_16(buf, back->gray);
  1560       png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
  1563 #endif
  1565 #ifdef PNG_WRITE_hIST_SUPPORTED
  1566 /* Write the histogram */
  1567 void /* PRIVATE */
  1568 png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
  1570    int i;
  1571    png_byte buf[3];
  1573    png_debug(1, "in png_write_hIST");
  1575    if (num_hist > (int)png_ptr->num_palette)
  1577       png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
  1578           png_ptr->num_palette);
  1580       png_warning(png_ptr, "Invalid number of histogram entries specified");
  1581       return;
  1584    png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
  1586    for (i = 0; i < num_hist; i++)
  1588       png_save_uint_16(buf, hist[i]);
  1589       png_write_chunk_data(png_ptr, buf, (png_size_t)2);
  1592    png_write_chunk_end(png_ptr);
  1594 #endif
  1596 #ifdef PNG_WRITE_tEXt_SUPPORTED
  1597 /* Write a tEXt chunk */
  1598 void /* PRIVATE */
  1599 png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
  1600     png_size_t text_len)
  1602    png_uint_32 key_len;
  1603    png_byte new_key[80];
  1605    png_debug(1, "in png_write_tEXt");
  1607    key_len = png_check_keyword(png_ptr, key, new_key);
  1609    if (key_len == 0)
  1610       png_error(png_ptr, "tEXt: invalid keyword");
  1612    if (text == NULL || *text == '\0')
  1613       text_len = 0;
  1615    else
  1616       text_len = strlen(text);
  1618    if (text_len > PNG_UINT_31_MAX - (key_len+1))
  1619       png_error(png_ptr, "tEXt: text too long");
  1621    /* Make sure we include the 0 after the key */
  1622    png_write_chunk_header(png_ptr, png_tEXt,
  1623        (png_uint_32)/*checked above*/(key_len + text_len + 1));
  1624    /*
  1625     * We leave it to the application to meet PNG-1.0 requirements on the
  1626     * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
  1627     * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
  1628     * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
  1629     */
  1630    png_write_chunk_data(png_ptr, new_key, key_len + 1);
  1632    if (text_len)
  1633       png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len);
  1635    png_write_chunk_end(png_ptr);
  1637 #endif
  1639 #ifdef PNG_WRITE_zTXt_SUPPORTED
  1640 /* Write a compressed text chunk */
  1641 void /* PRIVATE */
  1642 png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
  1643     png_size_t text_len, int compression)
  1645    png_uint_32 key_len;
  1646    png_byte new_key[81];
  1647    compression_state comp;
  1649    png_debug(1, "in png_write_zTXt");
  1650    PNG_UNUSED(text_len) /* Always use strlen */
  1652    if (compression == PNG_TEXT_COMPRESSION_NONE)
  1654       png_write_tEXt(png_ptr, key, text, 0);
  1655       return;
  1658    if (compression != PNG_TEXT_COMPRESSION_zTXt)
  1659       png_error(png_ptr, "zTXt: invalid compression type");
  1661    key_len = png_check_keyword(png_ptr, key, new_key);
  1663    if (key_len == 0)
  1664       png_error(png_ptr, "zTXt: invalid keyword");
  1666    /* Add the compression method and 1 for the keyword separator. */
  1667    new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
  1668    ++key_len;
  1670    /* Compute the compressed data; do it now for the length */
  1671    png_text_compress_init(&comp, (png_const_bytep)text,
  1672       text == NULL ? 0 : strlen(text));
  1674    if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
  1675       png_error(png_ptr, png_ptr->zstream.msg);
  1677    /* Write start of chunk */
  1678    png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
  1680    /* Write key */
  1681    png_write_chunk_data(png_ptr, new_key, key_len);
  1683    /* Write the compressed data */
  1684    png_write_compressed_data_out(png_ptr, &comp);
  1686    /* Close the chunk */
  1687    png_write_chunk_end(png_ptr);
  1689 #endif
  1691 #ifdef PNG_WRITE_iTXt_SUPPORTED
  1692 /* Write an iTXt chunk */
  1693 void /* PRIVATE */
  1694 png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
  1695     png_const_charp lang, png_const_charp lang_key, png_const_charp text)
  1697    png_uint_32 key_len, prefix_len;
  1698    png_size_t lang_len, lang_key_len;
  1699    png_byte new_key[82];
  1700    compression_state comp;
  1702    png_debug(1, "in png_write_iTXt");
  1704    key_len = png_check_keyword(png_ptr, key, new_key);
  1706    if (key_len == 0)
  1707       png_error(png_ptr, "iTXt: invalid keyword");
  1709    /* Set the compression flag */
  1710    switch (compression)
  1712       case PNG_ITXT_COMPRESSION_NONE:
  1713       case PNG_TEXT_COMPRESSION_NONE:
  1714          compression = new_key[++key_len] = 0; /* no compression */
  1715          break;
  1717       case PNG_TEXT_COMPRESSION_zTXt:
  1718       case PNG_ITXT_COMPRESSION_zTXt:
  1719          compression = new_key[++key_len] = 1; /* compressed */
  1720          break;
  1722       default:
  1723          png_error(png_ptr, "iTXt: invalid compression");
  1726    new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
  1727    ++key_len; /* for the keywod separator */
  1729    /* We leave it to the application to meet PNG-1.0 requirements on the
  1730     * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
  1731     * any non-Latin-1 characters except for NEWLINE.  ISO PNG, however,
  1732     * specifies that the text is UTF-8 and this really doesn't require any
  1733     * checking.
  1735     * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
  1737     * TODO: validate the language tag correctly (see the spec.)
  1738     */
  1739    if (lang == NULL) lang = ""; /* empty language is valid */
  1740    lang_len = strlen(lang)+1;
  1741    if (lang_key == NULL) lang_key = ""; /* may be empty */
  1742    lang_key_len = strlen(lang_key)+1;
  1743    if (text == NULL) text = ""; /* may be empty */
  1745    prefix_len = key_len;
  1746    if (lang_len > PNG_UINT_31_MAX-prefix_len)
  1747       prefix_len = PNG_UINT_31_MAX;
  1748    else
  1749       prefix_len = (png_uint_32)(prefix_len + lang_len);
  1751    if (lang_key_len > PNG_UINT_31_MAX-prefix_len)
  1752       prefix_len = PNG_UINT_31_MAX;
  1753    else
  1754       prefix_len = (png_uint_32)(prefix_len + lang_key_len);
  1756    png_text_compress_init(&comp, (png_const_bytep)text, strlen(text));
  1758    if (compression)
  1760       if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
  1761          png_error(png_ptr, png_ptr->zstream.msg);
  1764    else
  1766       if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
  1767          png_error(png_ptr, "iTXt: uncompressed text too long");
  1769       /* So the string will fit in a chunk: */
  1770       comp.output_len = (png_uint_32)/*SAFE*/comp.input_len;
  1773    png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);
  1775    png_write_chunk_data(png_ptr, new_key, key_len);
  1777    png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len);
  1779    png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len);
  1781    if (compression)
  1782       png_write_compressed_data_out(png_ptr, &comp);
  1784    else
  1785       png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.input_len);
  1787    png_write_chunk_end(png_ptr);
  1789 #endif
  1791 #ifdef PNG_WRITE_oFFs_SUPPORTED
  1792 /* Write the oFFs chunk */
  1793 void /* PRIVATE */
  1794 png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
  1795     int unit_type)
  1797    png_byte buf[9];
  1799    png_debug(1, "in png_write_oFFs");
  1801    if (unit_type >= PNG_OFFSET_LAST)
  1802       png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
  1804    png_save_int_32(buf, x_offset);
  1805    png_save_int_32(buf + 4, y_offset);
  1806    buf[8] = (png_byte)unit_type;
  1808    png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9);
  1810 #endif
  1811 #ifdef PNG_WRITE_pCAL_SUPPORTED
  1812 /* Write the pCAL chunk (described in the PNG extensions document) */
  1813 void /* PRIVATE */
  1814 png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
  1815     png_int_32 X1, int type, int nparams, png_const_charp units,
  1816     png_charpp params)
  1818    png_uint_32 purpose_len;
  1819    png_size_t units_len, total_len;
  1820    png_size_tp params_len;
  1821    png_byte buf[10];
  1822    png_byte new_purpose[80];
  1823    int i;
  1825    png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
  1827    if (type >= PNG_EQUATION_LAST)
  1828       png_error(png_ptr, "Unrecognized equation type for pCAL chunk");
  1830    purpose_len = png_check_keyword(png_ptr, purpose, new_purpose);
  1832    if (purpose_len == 0)
  1833       png_error(png_ptr, "pCAL: invalid keyword");
  1835    ++purpose_len; /* terminator */
  1837    png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
  1838    units_len = strlen(units) + (nparams == 0 ? 0 : 1);
  1839    png_debug1(3, "pCAL units length = %d", (int)units_len);
  1840    total_len = purpose_len + units_len + 10;
  1842    params_len = (png_size_tp)png_malloc(png_ptr,
  1843        (png_alloc_size_t)(nparams * (sizeof (png_size_t))));
  1845    /* Find the length of each parameter, making sure we don't count the
  1846     * null terminator for the last parameter.
  1847     */
  1848    for (i = 0; i < nparams; i++)
  1850       params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
  1851       png_debug2(3, "pCAL parameter %d length = %lu", i,
  1852           (unsigned long)params_len[i]);
  1853       total_len += params_len[i];
  1856    png_debug1(3, "pCAL total length = %d", (int)total_len);
  1857    png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
  1858    png_write_chunk_data(png_ptr, new_purpose, purpose_len);
  1859    png_save_int_32(buf, X0);
  1860    png_save_int_32(buf + 4, X1);
  1861    buf[8] = (png_byte)type;
  1862    buf[9] = (png_byte)nparams;
  1863    png_write_chunk_data(png_ptr, buf, (png_size_t)10);
  1864    png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len);
  1866    for (i = 0; i < nparams; i++)
  1868       png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
  1871    png_free(png_ptr, params_len);
  1872    png_write_chunk_end(png_ptr);
  1874 #endif
  1876 #ifdef PNG_WRITE_sCAL_SUPPORTED
  1877 /* Write the sCAL chunk */
  1878 void /* PRIVATE */
  1879 png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
  1880     png_const_charp height)
  1882    png_byte buf[64];
  1883    png_size_t wlen, hlen, total_len;
  1885    png_debug(1, "in png_write_sCAL_s");
  1887    wlen = strlen(width);
  1888    hlen = strlen(height);
  1889    total_len = wlen + hlen + 2;
  1891    if (total_len > 64)
  1893       png_warning(png_ptr, "Can't write sCAL (buffer too small)");
  1894       return;
  1897    buf[0] = (png_byte)unit;
  1898    memcpy(buf + 1, width, wlen + 1);      /* Append the '\0' here */
  1899    memcpy(buf + wlen + 2, height, hlen);  /* Do NOT append the '\0' here */
  1901    png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
  1902    png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
  1904 #endif
  1906 #ifdef PNG_WRITE_pHYs_SUPPORTED
  1907 /* Write the pHYs chunk */
  1908 void /* PRIVATE */
  1909 png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
  1910     png_uint_32 y_pixels_per_unit,
  1911     int unit_type)
  1913    png_byte buf[9];
  1915    png_debug(1, "in png_write_pHYs");
  1917    if (unit_type >= PNG_RESOLUTION_LAST)
  1918       png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
  1920    png_save_uint_32(buf, x_pixels_per_unit);
  1921    png_save_uint_32(buf + 4, y_pixels_per_unit);
  1922    buf[8] = (png_byte)unit_type;
  1924    png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
  1926 #endif
  1928 #ifdef PNG_WRITE_tIME_SUPPORTED
  1929 /* Write the tIME chunk.  Use either png_convert_from_struct_tm()
  1930  * or png_convert_from_time_t(), or fill in the structure yourself.
  1931  */
  1932 void /* PRIVATE */
  1933 png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
  1935    png_byte buf[7];
  1937    png_debug(1, "in png_write_tIME");
  1939    if (mod_time->month  > 12 || mod_time->month  < 1 ||
  1940        mod_time->day    > 31 || mod_time->day    < 1 ||
  1941        mod_time->hour   > 23 || mod_time->second > 60)
  1943       png_warning(png_ptr, "Invalid time specified for tIME chunk");
  1944       return;
  1947    png_save_uint_16(buf, mod_time->year);
  1948    buf[2] = mod_time->month;
  1949    buf[3] = mod_time->day;
  1950    buf[4] = mod_time->hour;
  1951    buf[5] = mod_time->minute;
  1952    buf[6] = mod_time->second;
  1954    png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
  1956 #endif
  1958 #ifdef PNG_WRITE_APNG_SUPPORTED
  1959 void /* PRIVATE */
  1960 png_write_acTL(png_structp png_ptr,
  1961     png_uint_32 num_frames, png_uint_32 num_plays)
  1963     png_byte buf[8];
  1965     png_debug(1, "in png_write_acTL");
  1967     png_ptr->num_frames_to_write = num_frames;
  1969     if (png_ptr->apng_flags & PNG_FIRST_FRAME_HIDDEN)
  1970         num_frames--;
  1972     png_save_uint_32(buf, num_frames);
  1973     png_save_uint_32(buf + 4, num_plays);
  1975     png_write_complete_chunk(png_ptr, png_acTL, buf, (png_size_t)8);
  1978 void /* PRIVATE */
  1979 png_write_fcTL(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
  1980     png_uint_32 x_offset, png_uint_32 y_offset,
  1981     png_uint_16 delay_num, png_uint_16 delay_den, png_byte dispose_op,
  1982     png_byte blend_op)
  1984     png_byte buf[26];
  1986     png_debug(1, "in png_write_fcTL");
  1988     if (png_ptr->num_frames_written == 0 && (x_offset != 0 || y_offset != 0))
  1989         png_error(png_ptr, "x and/or y offset for the first frame aren't 0");
  1990     if (png_ptr->num_frames_written == 0 &&
  1991         (width != png_ptr->first_frame_width ||
  1992          height != png_ptr->first_frame_height))
  1993         png_error(png_ptr, "width and/or height in the first frame's fcTL "
  1994                            "don't match the ones in IHDR");
  1996     /* more error checking */
  1997     png_ensure_fcTL_is_valid(png_ptr, width, height, x_offset, y_offset,
  1998                              delay_num, delay_den, dispose_op, blend_op);
  2000     png_save_uint_32(buf, png_ptr->next_seq_num);
  2001     png_save_uint_32(buf + 4, width);
  2002     png_save_uint_32(buf + 8, height);
  2003     png_save_uint_32(buf + 12, x_offset);
  2004     png_save_uint_32(buf + 16, y_offset);
  2005     png_save_uint_16(buf + 20, delay_num);
  2006     png_save_uint_16(buf + 22, delay_den);
  2007     buf[24] = dispose_op;
  2008     buf[25] = blend_op;
  2010     png_write_complete_chunk(png_ptr, png_fcTL, buf, (png_size_t)26);
  2012     png_ptr->next_seq_num++;
  2015 void /* PRIVATE */
  2016 png_write_fdAT(png_structp png_ptr,
  2017     png_const_bytep data, png_size_t length)
  2019     png_byte buf[4];
  2021     png_write_chunk_header(png_ptr, png_fdAT, (png_uint_32)(4 + length));
  2023     png_save_uint_32(buf, png_ptr->next_seq_num);
  2024     png_write_chunk_data(png_ptr, buf, 4);
  2026     png_write_chunk_data(png_ptr, data, length);
  2028     png_write_chunk_end(png_ptr);
  2030     png_ptr->next_seq_num++;
  2032 #endif /* PNG_WRITE_APNG_SUPPORTED */
  2034 /* Initializes the row writing capability of libpng */
  2035 void /* PRIVATE */
  2036 png_write_start_row(png_structrp png_ptr)
  2038 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  2039    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  2041    /* Start of interlace block */
  2042    static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  2044    /* Offset to next interlace block */
  2045    static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
  2047    /* Start of interlace block in the y direction */
  2048    static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
  2050    /* Offset to next interlace block in the y direction */
  2051    static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
  2052 #endif
  2054    png_alloc_size_t buf_size;
  2055    int usr_pixel_depth;
  2057    png_debug(1, "in png_write_start_row");
  2059    usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth;
  2060    buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1;
  2062    /* 1.5.6: added to allow checking in the row write code. */
  2063    png_ptr->transformed_pixel_depth = png_ptr->pixel_depth;
  2064    png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
  2066    /* Set up row buffer */
  2067    png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size);
  2069    png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
  2071 #ifdef PNG_WRITE_FILTER_SUPPORTED
  2072    /* Set up filtering buffer, if using this filter */
  2073    if (png_ptr->do_filter & PNG_FILTER_SUB)
  2075       png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1);
  2077       png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
  2080    /* We only need to keep the previous row if we are using one of these. */
  2081    if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
  2083       /* Set up previous row buffer */
  2084       png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size);
  2086       if (png_ptr->do_filter & PNG_FILTER_UP)
  2088          png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
  2089             png_ptr->rowbytes + 1);
  2091          png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
  2094       if (png_ptr->do_filter & PNG_FILTER_AVG)
  2096          png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
  2097              png_ptr->rowbytes + 1);
  2099          png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
  2102       if (png_ptr->do_filter & PNG_FILTER_PAETH)
  2104          png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
  2105              png_ptr->rowbytes + 1);
  2107          png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
  2110 #endif /* PNG_WRITE_FILTER_SUPPORTED */
  2112 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  2113    /* If interlaced, we need to set up width and height of pass */
  2114    if (png_ptr->interlaced)
  2116       if (!(png_ptr->transformations & PNG_INTERLACE))
  2118          png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
  2119              png_pass_ystart[0]) / png_pass_yinc[0];
  2121          png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
  2122              png_pass_start[0]) / png_pass_inc[0];
  2125       else
  2127          png_ptr->num_rows = png_ptr->height;
  2128          png_ptr->usr_width = png_ptr->width;
  2132    else
  2133 #endif
  2135       png_ptr->num_rows = png_ptr->height;
  2136       png_ptr->usr_width = png_ptr->width;
  2140 /* Internal use only.  Called when finished processing a row of data. */
  2141 void /* PRIVATE */
  2142 png_write_finish_row(png_structrp png_ptr)
  2144 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  2145    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  2147    /* Start of interlace block */
  2148    static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  2150    /* Offset to next interlace block */
  2151    static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
  2153    /* Start of interlace block in the y direction */
  2154    static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
  2156    /* Offset to next interlace block in the y direction */
  2157    static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
  2158 #endif
  2160    png_debug(1, "in png_write_finish_row");
  2162    /* Next row */
  2163    png_ptr->row_number++;
  2165    /* See if we are done */
  2166    if (png_ptr->row_number < png_ptr->num_rows)
  2167       return;
  2169 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  2170    /* If interlaced, go to next pass */
  2171    if (png_ptr->interlaced)
  2173       png_ptr->row_number = 0;
  2174       if (png_ptr->transformations & PNG_INTERLACE)
  2176          png_ptr->pass++;
  2179       else
  2181          /* Loop until we find a non-zero width or height pass */
  2182          do
  2184             png_ptr->pass++;
  2186             if (png_ptr->pass >= 7)
  2187                break;
  2189             png_ptr->usr_width = (png_ptr->width +
  2190                 png_pass_inc[png_ptr->pass] - 1 -
  2191                 png_pass_start[png_ptr->pass]) /
  2192                 png_pass_inc[png_ptr->pass];
  2194             png_ptr->num_rows = (png_ptr->height +
  2195                 png_pass_yinc[png_ptr->pass] - 1 -
  2196                 png_pass_ystart[png_ptr->pass]) /
  2197                 png_pass_yinc[png_ptr->pass];
  2199             if (png_ptr->transformations & PNG_INTERLACE)
  2200                break;
  2202          } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
  2206       /* Reset the row above the image for the next pass */
  2207       if (png_ptr->pass < 7)
  2209          if (png_ptr->prev_row != NULL)
  2210             memset(png_ptr->prev_row, 0,
  2211                 (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
  2212                 png_ptr->usr_bit_depth, png_ptr->width)) + 1);
  2214          return;
  2217 #endif
  2219    /* If we get here, we've just written the last row, so we need
  2220       to flush the compressor */
  2221    png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH);
  2224 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  2225 /* Pick out the correct pixels for the interlace pass.
  2226  * The basic idea here is to go through the row with a source
  2227  * pointer and a destination pointer (sp and dp), and copy the
  2228  * correct pixels for the pass.  As the row gets compacted,
  2229  * sp will always be >= dp, so we should never overwrite anything.
  2230  * See the default: case for the easiest code to understand.
  2231  */
  2232 void /* PRIVATE */
  2233 png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
  2235    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  2237    /* Start of interlace block */
  2238    static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  2240    /* Offset to next interlace block */
  2241    static PNG_CONST png_byte  png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
  2243    png_debug(1, "in png_do_write_interlace");
  2245    /* We don't have to do anything on the last pass (6) */
  2246    if (pass < 6)
  2248       /* Each pixel depth is handled separately */
  2249       switch (row_info->pixel_depth)
  2251          case 1:
  2253             png_bytep sp;
  2254             png_bytep dp;
  2255             int shift;
  2256             int d;
  2257             int value;
  2258             png_uint_32 i;
  2259             png_uint_32 row_width = row_info->width;
  2261             dp = row;
  2262             d = 0;
  2263             shift = 7;
  2265             for (i = png_pass_start[pass]; i < row_width;
  2266                i += png_pass_inc[pass])
  2268                sp = row + (png_size_t)(i >> 3);
  2269                value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
  2270                d |= (value << shift);
  2272                if (shift == 0)
  2274                   shift = 7;
  2275                   *dp++ = (png_byte)d;
  2276                   d = 0;
  2279                else
  2280                   shift--;
  2283             if (shift != 7)
  2284                *dp = (png_byte)d;
  2286             break;
  2289          case 2:
  2291             png_bytep sp;
  2292             png_bytep dp;
  2293             int shift;
  2294             int d;
  2295             int value;
  2296             png_uint_32 i;
  2297             png_uint_32 row_width = row_info->width;
  2299             dp = row;
  2300             shift = 6;
  2301             d = 0;
  2303             for (i = png_pass_start[pass]; i < row_width;
  2304                i += png_pass_inc[pass])
  2306                sp = row + (png_size_t)(i >> 2);
  2307                value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
  2308                d |= (value << shift);
  2310                if (shift == 0)
  2312                   shift = 6;
  2313                   *dp++ = (png_byte)d;
  2314                   d = 0;
  2317                else
  2318                   shift -= 2;
  2320             if (shift != 6)
  2321                *dp = (png_byte)d;
  2323             break;
  2326          case 4:
  2328             png_bytep sp;
  2329             png_bytep dp;
  2330             int shift;
  2331             int d;
  2332             int value;
  2333             png_uint_32 i;
  2334             png_uint_32 row_width = row_info->width;
  2336             dp = row;
  2337             shift = 4;
  2338             d = 0;
  2339             for (i = png_pass_start[pass]; i < row_width;
  2340                 i += png_pass_inc[pass])
  2342                sp = row + (png_size_t)(i >> 1);
  2343                value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
  2344                d |= (value << shift);
  2346                if (shift == 0)
  2348                   shift = 4;
  2349                   *dp++ = (png_byte)d;
  2350                   d = 0;
  2353                else
  2354                   shift -= 4;
  2356             if (shift != 4)
  2357                *dp = (png_byte)d;
  2359             break;
  2362          default:
  2364             png_bytep sp;
  2365             png_bytep dp;
  2366             png_uint_32 i;
  2367             png_uint_32 row_width = row_info->width;
  2368             png_size_t pixel_bytes;
  2370             /* Start at the beginning */
  2371             dp = row;
  2373             /* Find out how many bytes each pixel takes up */
  2374             pixel_bytes = (row_info->pixel_depth >> 3);
  2376             /* Loop through the row, only looking at the pixels that matter */
  2377             for (i = png_pass_start[pass]; i < row_width;
  2378                i += png_pass_inc[pass])
  2380                /* Find out where the original pixel is */
  2381                sp = row + (png_size_t)i * pixel_bytes;
  2383                /* Move the pixel */
  2384                if (dp != sp)
  2385                   memcpy(dp, sp, pixel_bytes);
  2387                /* Next pixel */
  2388                dp += pixel_bytes;
  2390             break;
  2393       /* Set new row width */
  2394       row_info->width = (row_info->width +
  2395           png_pass_inc[pass] - 1 -
  2396           png_pass_start[pass]) /
  2397           png_pass_inc[pass];
  2399       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
  2400           row_info->width);
  2403 #endif
  2405 /* This filters the row, chooses which filter to use, if it has not already
  2406  * been specified by the application, and then writes the row out with the
  2407  * chosen filter.
  2408  */
  2409 static void
  2410 png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
  2411    png_size_t row_bytes);
  2413 #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
  2414 #define PNG_HISHIFT 10
  2415 #define PNG_LOMASK ((png_uint_32)0xffffL)
  2416 #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
  2417 void /* PRIVATE */
  2418 png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
  2420    png_bytep best_row;
  2421 #ifdef PNG_WRITE_FILTER_SUPPORTED
  2422    png_bytep prev_row, row_buf;
  2423    png_uint_32 mins, bpp;
  2424    png_byte filter_to_do = png_ptr->do_filter;
  2425    png_size_t row_bytes = row_info->rowbytes;
  2426 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2427    int num_p_filters = png_ptr->num_prev_filters;
  2428 #endif
  2430    png_debug(1, "in png_write_find_filter");
  2432 #ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2433   if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
  2435      /* These will never be selected so we need not test them. */
  2436      filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
  2438 #endif
  2440    /* Find out how many bytes offset each pixel is */
  2441    bpp = (row_info->pixel_depth + 7) >> 3;
  2443    prev_row = png_ptr->prev_row;
  2444 #endif
  2445    best_row = png_ptr->row_buf;
  2446 #ifdef PNG_WRITE_FILTER_SUPPORTED
  2447    row_buf = best_row;
  2448    mins = PNG_MAXSUM;
  2450    /* The prediction method we use is to find which method provides the
  2451     * smallest value when summing the absolute values of the distances
  2452     * from zero, using anything >= 128 as negative numbers.  This is known
  2453     * as the "minimum sum of absolute differences" heuristic.  Other
  2454     * heuristics are the "weighted minimum sum of absolute differences"
  2455     * (experimental and can in theory improve compression), and the "zlib
  2456     * predictive" method (not implemented yet), which does test compressions
  2457     * of lines using different filter methods, and then chooses the
  2458     * (series of) filter(s) that give minimum compressed data size (VERY
  2459     * computationally expensive).
  2461     * GRR 980525:  consider also
  2463     *   (1) minimum sum of absolute differences from running average (i.e.,
  2464     *       keep running sum of non-absolute differences & count of bytes)
  2465     *       [track dispersion, too?  restart average if dispersion too large?]
  2467     *  (1b) minimum sum of absolute differences from sliding average, probably
  2468     *       with window size <= deflate window (usually 32K)
  2470     *   (2) minimum sum of squared differences from zero or running average
  2471     *       (i.e., ~ root-mean-square approach)
  2472     */
  2475    /* We don't need to test the 'no filter' case if this is the only filter
  2476     * that has been chosen, as it doesn't actually do anything to the data.
  2477     */
  2478    if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE)
  2480       png_bytep rp;
  2481       png_uint_32 sum = 0;
  2482       png_size_t i;
  2483       int v;
  2485       for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
  2487          v = *rp;
  2488          sum += (v < 128) ? v : 256 - v;
  2491 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2492       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2494          png_uint_32 sumhi, sumlo;
  2495          int j;
  2496          sumlo = sum & PNG_LOMASK;
  2497          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
  2499          /* Reduce the sum if we match any of the previous rows */
  2500          for (j = 0; j < num_p_filters; j++)
  2502             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
  2504                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
  2505                    PNG_WEIGHT_SHIFT;
  2507                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
  2508                    PNG_WEIGHT_SHIFT;
  2512          /* Factor in the cost of this filter (this is here for completeness,
  2513           * but it makes no sense to have a "cost" for the NONE filter, as
  2514           * it has the minimum possible computational cost - none).
  2515           */
  2516          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
  2517              PNG_COST_SHIFT;
  2519          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
  2520              PNG_COST_SHIFT;
  2522          if (sumhi > PNG_HIMASK)
  2523             sum = PNG_MAXSUM;
  2525          else
  2526             sum = (sumhi << PNG_HISHIFT) + sumlo;
  2528 #endif
  2529       mins = sum;
  2532    /* Sub filter */
  2533    if (filter_to_do == PNG_FILTER_SUB)
  2534    /* It's the only filter so no testing is needed */
  2536       png_bytep rp, lp, dp;
  2537       png_size_t i;
  2539       for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
  2540            i++, rp++, dp++)
  2542          *dp = *rp;
  2545       for (lp = row_buf + 1; i < row_bytes;
  2546          i++, rp++, lp++, dp++)
  2548          *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
  2551       best_row = png_ptr->sub_row;
  2554    else if (filter_to_do & PNG_FILTER_SUB)
  2556       png_bytep rp, dp, lp;
  2557       png_uint_32 sum = 0, lmins = mins;
  2558       png_size_t i;
  2559       int v;
  2561 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2562       /* We temporarily increase the "minimum sum" by the factor we
  2563        * would reduce the sum of this filter, so that we can do the
  2564        * early exit comparison without scaling the sum each time.
  2565        */
  2566       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2568          int j;
  2569          png_uint_32 lmhi, lmlo;
  2570          lmlo = lmins & PNG_LOMASK;
  2571          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  2573          for (j = 0; j < num_p_filters; j++)
  2575             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
  2577                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
  2578                    PNG_WEIGHT_SHIFT;
  2580                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
  2581                    PNG_WEIGHT_SHIFT;
  2585          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  2586              PNG_COST_SHIFT;
  2588          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  2589              PNG_COST_SHIFT;
  2591          if (lmhi > PNG_HIMASK)
  2592             lmins = PNG_MAXSUM;
  2594          else
  2595             lmins = (lmhi << PNG_HISHIFT) + lmlo;
  2597 #endif
  2599       for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
  2600            i++, rp++, dp++)
  2602          v = *dp = *rp;
  2604          sum += (v < 128) ? v : 256 - v;
  2607       for (lp = row_buf + 1; i < row_bytes;
  2608          i++, rp++, lp++, dp++)
  2610          v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
  2612          sum += (v < 128) ? v : 256 - v;
  2614          if (sum > lmins)  /* We are already worse, don't continue. */
  2615             break;
  2618 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2619       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2621          int j;
  2622          png_uint_32 sumhi, sumlo;
  2623          sumlo = sum & PNG_LOMASK;
  2624          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  2626          for (j = 0; j < num_p_filters; j++)
  2628             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
  2630                sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
  2631                    PNG_WEIGHT_SHIFT;
  2633                sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
  2634                    PNG_WEIGHT_SHIFT;
  2638          sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  2639              PNG_COST_SHIFT;
  2641          sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
  2642              PNG_COST_SHIFT;
  2644          if (sumhi > PNG_HIMASK)
  2645             sum = PNG_MAXSUM;
  2647          else
  2648             sum = (sumhi << PNG_HISHIFT) + sumlo;
  2650 #endif
  2652       if (sum < mins)
  2654          mins = sum;
  2655          best_row = png_ptr->sub_row;
  2659    /* Up filter */
  2660    if (filter_to_do == PNG_FILTER_UP)
  2662       png_bytep rp, dp, pp;
  2663       png_size_t i;
  2665       for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
  2666           pp = prev_row + 1; i < row_bytes;
  2667           i++, rp++, pp++, dp++)
  2669          *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
  2672       best_row = png_ptr->up_row;
  2675    else if (filter_to_do & PNG_FILTER_UP)
  2677       png_bytep rp, dp, pp;
  2678       png_uint_32 sum = 0, lmins = mins;
  2679       png_size_t i;
  2680       int v;
  2683 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2684       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2686          int j;
  2687          png_uint_32 lmhi, lmlo;
  2688          lmlo = lmins & PNG_LOMASK;
  2689          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  2691          for (j = 0; j < num_p_filters; j++)
  2693             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
  2695                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
  2696                    PNG_WEIGHT_SHIFT;
  2698                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
  2699                    PNG_WEIGHT_SHIFT;
  2703          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
  2704              PNG_COST_SHIFT;
  2706          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
  2707              PNG_COST_SHIFT;
  2709          if (lmhi > PNG_HIMASK)
  2710             lmins = PNG_MAXSUM;
  2712          else
  2713             lmins = (lmhi << PNG_HISHIFT) + lmlo;
  2715 #endif
  2717       for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
  2718           pp = prev_row + 1; i < row_bytes; i++)
  2720          v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
  2722          sum += (v < 128) ? v : 256 - v;
  2724          if (sum > lmins)  /* We are already worse, don't continue. */
  2725             break;
  2728 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2729       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2731          int j;
  2732          png_uint_32 sumhi, sumlo;
  2733          sumlo = sum & PNG_LOMASK;
  2734          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  2736          for (j = 0; j < num_p_filters; j++)
  2738             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
  2740                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
  2741                    PNG_WEIGHT_SHIFT;
  2743                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
  2744                    PNG_WEIGHT_SHIFT;
  2748          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
  2749              PNG_COST_SHIFT;
  2751          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
  2752              PNG_COST_SHIFT;
  2754          if (sumhi > PNG_HIMASK)
  2755             sum = PNG_MAXSUM;
  2757          else
  2758             sum = (sumhi << PNG_HISHIFT) + sumlo;
  2760 #endif
  2762       if (sum < mins)
  2764          mins = sum;
  2765          best_row = png_ptr->up_row;
  2769    /* Avg filter */
  2770    if (filter_to_do == PNG_FILTER_AVG)
  2772       png_bytep rp, dp, pp, lp;
  2773       png_uint_32 i;
  2775       for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
  2776            pp = prev_row + 1; i < bpp; i++)
  2778          *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
  2781       for (lp = row_buf + 1; i < row_bytes; i++)
  2783          *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
  2784                  & 0xff);
  2786       best_row = png_ptr->avg_row;
  2789    else if (filter_to_do & PNG_FILTER_AVG)
  2791       png_bytep rp, dp, pp, lp;
  2792       png_uint_32 sum = 0, lmins = mins;
  2793       png_size_t i;
  2794       int v;
  2796 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2797       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2799          int j;
  2800          png_uint_32 lmhi, lmlo;
  2801          lmlo = lmins & PNG_LOMASK;
  2802          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  2804          for (j = 0; j < num_p_filters; j++)
  2806             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
  2808                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
  2809                    PNG_WEIGHT_SHIFT;
  2811                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
  2812                    PNG_WEIGHT_SHIFT;
  2816          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
  2817              PNG_COST_SHIFT;
  2819          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
  2820              PNG_COST_SHIFT;
  2822          if (lmhi > PNG_HIMASK)
  2823             lmins = PNG_MAXSUM;
  2825          else
  2826             lmins = (lmhi << PNG_HISHIFT) + lmlo;
  2828 #endif
  2830       for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
  2831            pp = prev_row + 1; i < bpp; i++)
  2833          v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
  2835          sum += (v < 128) ? v : 256 - v;
  2838       for (lp = row_buf + 1; i < row_bytes; i++)
  2840          v = *dp++ =
  2841              (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
  2843          sum += (v < 128) ? v : 256 - v;
  2845          if (sum > lmins)  /* We are already worse, don't continue. */
  2846             break;
  2849 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2850       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2852          int j;
  2853          png_uint_32 sumhi, sumlo;
  2854          sumlo = sum & PNG_LOMASK;
  2855          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  2857          for (j = 0; j < num_p_filters; j++)
  2859             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
  2861                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
  2862                    PNG_WEIGHT_SHIFT;
  2864                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
  2865                    PNG_WEIGHT_SHIFT;
  2869          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
  2870              PNG_COST_SHIFT;
  2872          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
  2873              PNG_COST_SHIFT;
  2875          if (sumhi > PNG_HIMASK)
  2876             sum = PNG_MAXSUM;
  2878          else
  2879             sum = (sumhi << PNG_HISHIFT) + sumlo;
  2881 #endif
  2883       if (sum < mins)
  2885          mins = sum;
  2886          best_row = png_ptr->avg_row;
  2890    /* Paeth filter */
  2891    if (filter_to_do == PNG_FILTER_PAETH)
  2893       png_bytep rp, dp, pp, cp, lp;
  2894       png_size_t i;
  2896       for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
  2897           pp = prev_row + 1; i < bpp; i++)
  2899          *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
  2902       for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
  2904          int a, b, c, pa, pb, pc, p;
  2906          b = *pp++;
  2907          c = *cp++;
  2908          a = *lp++;
  2910          p = b - c;
  2911          pc = a - c;
  2913 #ifdef PNG_USE_ABS
  2914          pa = abs(p);
  2915          pb = abs(pc);
  2916          pc = abs(p + pc);
  2917 #else
  2918          pa = p < 0 ? -p : p;
  2919          pb = pc < 0 ? -pc : pc;
  2920          pc = (p + pc) < 0 ? -(p + pc) : p + pc;
  2921 #endif
  2923          p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
  2925          *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
  2927       best_row = png_ptr->paeth_row;
  2930    else if (filter_to_do & PNG_FILTER_PAETH)
  2932       png_bytep rp, dp, pp, cp, lp;
  2933       png_uint_32 sum = 0, lmins = mins;
  2934       png_size_t i;
  2935       int v;
  2937 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2938       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2940          int j;
  2941          png_uint_32 lmhi, lmlo;
  2942          lmlo = lmins & PNG_LOMASK;
  2943          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
  2945          for (j = 0; j < num_p_filters; j++)
  2947             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
  2949                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
  2950                    PNG_WEIGHT_SHIFT;
  2952                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
  2953                    PNG_WEIGHT_SHIFT;
  2957          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  2958              PNG_COST_SHIFT;
  2960          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  2961              PNG_COST_SHIFT;
  2963          if (lmhi > PNG_HIMASK)
  2964             lmins = PNG_MAXSUM;
  2966          else
  2967             lmins = (lmhi << PNG_HISHIFT) + lmlo;
  2969 #endif
  2971       for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
  2972           pp = prev_row + 1; i < bpp; i++)
  2974          v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
  2976          sum += (v < 128) ? v : 256 - v;
  2979       for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
  2981          int a, b, c, pa, pb, pc, p;
  2983          b = *pp++;
  2984          c = *cp++;
  2985          a = *lp++;
  2987 #ifndef PNG_SLOW_PAETH
  2988          p = b - c;
  2989          pc = a - c;
  2990 #ifdef PNG_USE_ABS
  2991          pa = abs(p);
  2992          pb = abs(pc);
  2993          pc = abs(p + pc);
  2994 #else
  2995          pa = p < 0 ? -p : p;
  2996          pb = pc < 0 ? -pc : pc;
  2997          pc = (p + pc) < 0 ? -(p + pc) : p + pc;
  2998 #endif
  2999          p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
  3000 #else /* PNG_SLOW_PAETH */
  3001          p = a + b - c;
  3002          pa = abs(p - a);
  3003          pb = abs(p - b);
  3004          pc = abs(p - c);
  3006          if (pa <= pb && pa <= pc)
  3007             p = a;
  3009          else if (pb <= pc)
  3010             p = b;
  3012          else
  3013             p = c;
  3014 #endif /* PNG_SLOW_PAETH */
  3016          v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
  3018          sum += (v < 128) ? v : 256 - v;
  3020          if (sum > lmins)  /* We are already worse, don't continue. */
  3021             break;
  3024 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  3025       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  3027          int j;
  3028          png_uint_32 sumhi, sumlo;
  3029          sumlo = sum & PNG_LOMASK;
  3030          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
  3032          for (j = 0; j < num_p_filters; j++)
  3034             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
  3036                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
  3037                    PNG_WEIGHT_SHIFT;
  3039                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
  3040                    PNG_WEIGHT_SHIFT;
  3044          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  3045              PNG_COST_SHIFT;
  3047          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
  3048              PNG_COST_SHIFT;
  3050          if (sumhi > PNG_HIMASK)
  3051             sum = PNG_MAXSUM;
  3053          else
  3054             sum = (sumhi << PNG_HISHIFT) + sumlo;
  3056 #endif
  3058       if (sum < mins)
  3060          best_row = png_ptr->paeth_row;
  3063 #endif /* PNG_WRITE_FILTER_SUPPORTED */
  3065    /* Do the actual writing of the filtered row data from the chosen filter. */
  3066    png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
  3068 #ifdef PNG_WRITE_FILTER_SUPPORTED
  3069 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  3070    /* Save the type of filter we picked this time for future calculations */
  3071    if (png_ptr->num_prev_filters > 0)
  3073       int j;
  3075       for (j = 1; j < num_p_filters; j++)
  3077          png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
  3080       png_ptr->prev_filters[j] = best_row[0];
  3082 #endif
  3083 #endif /* PNG_WRITE_FILTER_SUPPORTED */
  3087 /* Do the actual writing of a previously filtered row. */
  3088 static void
  3089 png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
  3090    png_size_t full_row_length/*includes filter byte*/)
  3092    png_debug(1, "in png_write_filtered_row");
  3094    png_debug1(2, "filter = %d", filtered_row[0]);
  3096    png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH);
  3098    /* Swap the current and previous rows */
  3099    if (png_ptr->prev_row != NULL)
  3101       png_bytep tptr;
  3103       tptr = png_ptr->prev_row;
  3104       png_ptr->prev_row = png_ptr->row_buf;
  3105       png_ptr->row_buf = tptr;
  3108    /* Finish row - updates counters and flushes zlib if last row */
  3109    png_write_finish_row(png_ptr);
  3111 #ifdef PNG_WRITE_FLUSH_SUPPORTED
  3112    png_ptr->flush_rows++;
  3114    if (png_ptr->flush_dist > 0 &&
  3115        png_ptr->flush_rows >= png_ptr->flush_dist)
  3117       png_write_flush(png_ptr);
  3119 #endif
  3122 #ifdef PNG_WRITE_APNG_SUPPORTED
  3123 void /* PRIVATE */
  3124 png_write_reset(png_structp png_ptr)
  3126     png_ptr->row_number = 0;
  3127     png_ptr->pass = 0;
  3128     png_ptr->mode &= ~PNG_HAVE_IDAT;
  3131 void /* PRIVATE */
  3132 png_write_reinit(png_structp png_ptr, png_infop info_ptr,
  3133                  png_uint_32 width, png_uint_32 height)
  3135     if (png_ptr->num_frames_written == 0 &&
  3136         (width != png_ptr->first_frame_width ||
  3137          height != png_ptr->first_frame_height))
  3138         png_error(png_ptr, "width and/or height in the first frame's fcTL "
  3139                            "don't match the ones in IHDR");
  3140     if (width > png_ptr->first_frame_width ||
  3141         height > png_ptr->first_frame_height)
  3142         png_error(png_ptr, "width and/or height for a frame greater than"
  3143                            "the ones in IHDR");
  3145     png_set_IHDR(png_ptr, info_ptr, width, height,
  3146                  info_ptr->bit_depth, info_ptr->color_type,
  3147                  info_ptr->interlace_type, info_ptr->compression_type,
  3148                  info_ptr->filter_type);
  3150     png_ptr->width = width;
  3151     png_ptr->height = height;
  3152     png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
  3153     png_ptr->usr_width = png_ptr->width;
  3155 #endif /* PNG_WRITE_APNG_SUPPORTED */
  3156 #endif /* PNG_WRITE_SUPPORTED */

mercurial