src/3rdparty/libpng/pngwutil.c
branchGCC_SURGE
changeset 31 5daf16870df6
parent 30 5dc02b23752f
equal deleted inserted replaced
27:93b982ccede2 31:5daf16870df6
     1 
     1 
     2 /* pngwutil.c - utilities to write a PNG file
     2 /* pngwutil.c - utilities to write a PNG file
     3  *
     3  *
     4  * Last changed in libpng 1.2.40 [September 10, 2009]
     4  * Last changed in libpng 1.4.0 [January 3, 2010]
     5  * Copyright (c) 1998-2009 Glenn Randers-Pehrson
     5  * Copyright (c) 1998-2010 Glenn Randers-Pehrson
     6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
     6  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
     7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
     7  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
     8  *
     8  *
     9  * This code is released under the libpng license.
     9  * This code is released under the libpng license.
    10  * For conditions of distribution and use, see the disclaimer
    10  * For conditions of distribution and use, see the disclaimer
    11  * and license in png.h
    11  * and license in png.h
    12  */
    12  */
    13 
    13 
    14 #define PNG_INTERNAL
    14 #define PNG_NO_PEDANTIC_WARNINGS
    15 #include "png.h"
    15 #include "png.h"
    16 #ifdef PNG_WRITE_SUPPORTED
    16 #ifdef PNG_WRITE_SUPPORTED
       
    17 #include "pngpriv.h"
    17 
    18 
    18 /* Place a 32-bit number into a buffer in PNG byte order.  We work
    19 /* Place a 32-bit number into a buffer in PNG byte order.  We work
    19  * with unsigned numbers for convenience, although one supported
    20  * with unsigned numbers for convenience, although one supported
    20  * ancillary chunk uses signed (two's complement) numbers.
    21  * ancillary chunk uses signed (two's complement) numbers.
    21  */
    22  */
    26    buf[1] = (png_byte)((i >> 16) & 0xff);
    27    buf[1] = (png_byte)((i >> 16) & 0xff);
    27    buf[2] = (png_byte)((i >> 8) & 0xff);
    28    buf[2] = (png_byte)((i >> 8) & 0xff);
    28    buf[3] = (png_byte)(i & 0xff);
    29    buf[3] = (png_byte)(i & 0xff);
    29 }
    30 }
    30 
    31 
       
    32 #ifdef PNG_SAVE_INT_32_SUPPORTED
    31 /* The png_save_int_32 function assumes integers are stored in two's
    33 /* The png_save_int_32 function assumes integers are stored in two's
    32  * complement format.  If this isn't the case, then this routine needs to
    34  * complement format.  If this isn't the case, then this routine needs to
    33  * be modified to write data in two's complement format.
    35  * be modified to write data in two's complement format.
    34  */
    36  */
    35 void PNGAPI
    37 void PNGAPI
    38    buf[0] = (png_byte)((i >> 24) & 0xff);
    40    buf[0] = (png_byte)((i >> 24) & 0xff);
    39    buf[1] = (png_byte)((i >> 16) & 0xff);
    41    buf[1] = (png_byte)((i >> 16) & 0xff);
    40    buf[2] = (png_byte)((i >> 8) & 0xff);
    42    buf[2] = (png_byte)((i >> 8) & 0xff);
    41    buf[3] = (png_byte)(i & 0xff);
    43    buf[3] = (png_byte)(i & 0xff);
    42 }
    44 }
       
    45 #endif
    43 
    46 
    44 /* Place a 16-bit number into a buffer in PNG byte order.
    47 /* Place a 16-bit number into a buffer in PNG byte order.
    45  * The parameter is declared unsigned int, not png_uint_16,
    48  * The parameter is declared unsigned int, not png_uint_16,
    46  * just to avoid potential problems on pre-ANSI C compilers.
    49  * just to avoid potential problems on pre-ANSI C compilers.
    47  */
    50  */
    56  * the magic bytes of the signature, or more likely, the PNG stream is
    59  * the magic bytes of the signature, or more likely, the PNG stream is
    57  * being embedded into another stream and doesn't need its own signature,
    60  * being embedded into another stream and doesn't need its own signature,
    58  * we should call png_set_sig_bytes() to tell libpng how many of the
    61  * we should call png_set_sig_bytes() to tell libpng how many of the
    59  * bytes have already been written.
    62  * bytes have already been written.
    60  */
    63  */
    61 void /* PRIVATE */
    64 void PNGAPI
    62 png_write_sig(png_structp png_ptr)
    65 png_write_sig(png_structp png_ptr)
    63 {
    66 {
    64    png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
    67    png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
       
    68 
       
    69 #ifdef PNG_IO_STATE_SUPPORTED
       
    70    /* Inform the I/O callback that the signature is being written */
       
    71    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE;
       
    72 #endif
    65 
    73 
    66    /* Write the rest of the 8 byte signature */
    74    /* Write the rest of the 8 byte signature */
    67    png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
    75    png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
    68       (png_size_t)(8 - png_ptr->sig_bytes));
    76       (png_size_t)(8 - png_ptr->sig_bytes));
    69    if (png_ptr->sig_bytes < 3)
    77    if (png_ptr->sig_bytes < 3)
   104       (unsigned long)length);
   112       (unsigned long)length);
   105 
   113 
   106    if (png_ptr == NULL)
   114    if (png_ptr == NULL)
   107       return;
   115       return;
   108 
   116 
       
   117 #ifdef PNG_IO_STATE_SUPPORTED
       
   118    /* Inform the I/O callback that the chunk header is being written.
       
   119     * PNG_IO_CHUNK_HDR requires a single I/O call.
       
   120     */
       
   121    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR;
       
   122 #endif
       
   123 
   109    /* Write the length and the chunk name */
   124    /* Write the length and the chunk name */
   110    png_save_uint_32(buf, length);
   125    png_save_uint_32(buf, length);
   111    png_memcpy(buf + 4, chunk_name, 4);
   126    png_memcpy(buf + 4, chunk_name, 4);
   112    png_write_data(png_ptr, buf, (png_size_t)8);
   127    png_write_data(png_ptr, buf, (png_size_t)8);
   113    /* Put the chunk name into png_ptr->chunk_name */
   128    /* Put the chunk name into png_ptr->chunk_name */
   114    png_memcpy(png_ptr->chunk_name, chunk_name, 4);
   129    png_memcpy(png_ptr->chunk_name, chunk_name, 4);
   115    /* Reset the crc and run it over the chunk name */
   130    /* Reset the crc and run it over the chunk name */
   116    png_reset_crc(png_ptr);
   131    png_reset_crc(png_ptr);
   117    png_calculate_crc(png_ptr, chunk_name, (png_size_t)4);
   132    png_calculate_crc(png_ptr, chunk_name, 4);
       
   133 
       
   134 #ifdef PNG_IO_STATE_SUPPORTED
       
   135    /* Inform the I/O callback that chunk data will (possibly) be written.
       
   136     * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
       
   137     */
       
   138    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA;
       
   139 #endif
   118 }
   140 }
   119 
   141 
   120 /* Write the data of a PNG chunk started with png_write_chunk_start().
   142 /* Write the data of a PNG chunk started with png_write_chunk_start().
   121  * Note that multiple calls to this function are allowed, and that the
   143  * Note that multiple calls to this function are allowed, and that the
   122  * sum of the lengths from these calls *must* add up to the total_length
   144  * sum of the lengths from these calls *must* add up to the total_length
   144 {
   166 {
   145    png_byte buf[4];
   167    png_byte buf[4];
   146 
   168 
   147    if (png_ptr == NULL) return;
   169    if (png_ptr == NULL) return;
   148 
   170 
       
   171 #ifdef PNG_IO_STATE_SUPPORTED
       
   172    /* Inform the I/O callback that the chunk CRC is being written.
       
   173     * PNG_IO_CHUNK_CRC requires a single I/O function call.
       
   174     */
       
   175    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC;
       
   176 #endif
       
   177 
   149    /* Write the crc in a single operation */
   178    /* Write the crc in a single operation */
   150    png_save_uint_32(buf, png_ptr->crc);
   179    png_save_uint_32(buf, png_ptr->crc);
   151 
   180 
   152    png_write_data(png_ptr, buf, (png_size_t)4);
   181    png_write_data(png_ptr, buf, (png_size_t)4);
   153 }
   182 }
   190        return((int)text_len);
   219        return((int)text_len);
   191    }
   220    }
   192 
   221 
   193    if (compression >= PNG_TEXT_COMPRESSION_LAST)
   222    if (compression >= PNG_TEXT_COMPRESSION_LAST)
   194    {
   223    {
   195 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
   224 #ifdef PNG_STDIO_SUPPORTED
   196       char msg[50];
   225       char msg[50];
   197       png_snprintf(msg, 50, "Unknown compression type %d", compression);
   226       png_snprintf(msg, 50, "Unknown compression type %d", compression);
   198       png_warning(png_ptr, msg);
   227       png_warning(png_ptr, msg);
   199 #else
   228 #else
   200       png_warning(png_ptr, "Unknown compression type");
   229       png_warning(png_ptr, "Unknown compression type");
   249             {
   278             {
   250                png_charpp old_ptr;
   279                png_charpp old_ptr;
   251 
   280 
   252                old_ptr = comp->output_ptr;
   281                old_ptr = comp->output_ptr;
   253                comp->output_ptr = (png_charpp)png_malloc(png_ptr,
   282                comp->output_ptr = (png_charpp)png_malloc(png_ptr,
   254                   (png_uint_32)
   283                   (png_alloc_size_t)
   255                   (comp->max_output_ptr * png_sizeof(png_charpp)));
   284                   (comp->max_output_ptr * png_sizeof(png_charpp)));
   256                png_memcpy(comp->output_ptr, old_ptr, old_max
   285                png_memcpy(comp->output_ptr, old_ptr, old_max
   257                   * png_sizeof(png_charp));
   286                   * png_sizeof(png_charp));
   258                png_free(png_ptr, old_ptr);
   287                png_free(png_ptr, old_ptr);
   259             }
   288             }
   260             else
   289             else
   261                comp->output_ptr = (png_charpp)png_malloc(png_ptr,
   290                comp->output_ptr = (png_charpp)png_malloc(png_ptr,
   262                   (png_uint_32)
   291                   (png_alloc_size_t)
   263                   (comp->max_output_ptr * png_sizeof(png_charp)));
   292                   (comp->max_output_ptr * png_sizeof(png_charp)));
   264          }
   293          }
   265 
   294 
   266          /* Save the data */
   295          /* Save the data */
   267          comp->output_ptr[comp->num_output_ptr] =
   296          comp->output_ptr[comp->num_output_ptr] =
   268             (png_charp)png_malloc(png_ptr,
   297             (png_charp)png_malloc(png_ptr,
   269             (png_uint_32)png_ptr->zbuf_size);
   298             (png_alloc_size_t)png_ptr->zbuf_size);
   270          png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
   299          png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
   271             png_ptr->zbuf_size);
   300             png_ptr->zbuf_size);
   272          comp->num_output_ptr++;
   301          comp->num_output_ptr++;
   273 
   302 
   274          /* and reset the buffer */
   303          /* and reset the buffer */
   301                   png_charpp old_ptr;
   330                   png_charpp old_ptr;
   302 
   331 
   303                   old_ptr = comp->output_ptr;
   332                   old_ptr = comp->output_ptr;
   304                   /* This could be optimized to realloc() */
   333                   /* This could be optimized to realloc() */
   305                   comp->output_ptr = (png_charpp)png_malloc(png_ptr,
   334                   comp->output_ptr = (png_charpp)png_malloc(png_ptr,
   306                      (png_uint_32)(comp->max_output_ptr *
   335                      (png_alloc_size_t)(comp->max_output_ptr *
   307                      png_sizeof(png_charp)));
   336                      png_sizeof(png_charp)));
   308                   png_memcpy(comp->output_ptr, old_ptr,
   337                   png_memcpy(comp->output_ptr, old_ptr,
   309                      old_max * png_sizeof(png_charp));
   338                      old_max * png_sizeof(png_charp));
   310                   png_free(png_ptr, old_ptr);
   339                   png_free(png_ptr, old_ptr);
   311                }
   340                }
   312                else
   341                else
   313                   comp->output_ptr = (png_charpp)png_malloc(png_ptr,
   342                   comp->output_ptr = (png_charpp)png_malloc(png_ptr,
   314                      (png_uint_32)(comp->max_output_ptr *
   343                      (png_alloc_size_t)(comp->max_output_ptr *
   315                      png_sizeof(png_charp)));
   344                      png_sizeof(png_charp)));
   316             }
   345             }
   317 
   346 
   318             /* Save the data */
   347             /* Save the data */
   319             comp->output_ptr[comp->num_output_ptr] =
   348             comp->output_ptr[comp->num_output_ptr] =
   320                (png_charp)png_malloc(png_ptr,
   349                (png_charp)png_malloc(png_ptr,
   321                (png_uint_32)png_ptr->zbuf_size);
   350                (png_alloc_size_t)png_ptr->zbuf_size);
   322             png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
   351             png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
   323                png_ptr->zbuf_size);
   352                png_ptr->zbuf_size);
   324             comp->num_output_ptr++;
   353             comp->num_output_ptr++;
   325 
   354 
   326             /* and reset the buffer pointers */
   355             /* and reset the buffer pointers */
   364    for (i = 0; i < comp->num_output_ptr; i++)
   393    for (i = 0; i < comp->num_output_ptr; i++)
   365    {
   394    {
   366       png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i],
   395       png_write_chunk_data(png_ptr, (png_bytep)comp->output_ptr[i],
   367          (png_size_t)png_ptr->zbuf_size);
   396          (png_size_t)png_ptr->zbuf_size);
   368       png_free(png_ptr, comp->output_ptr[i]);
   397       png_free(png_ptr, comp->output_ptr[i]);
   369        comp->output_ptr[i]=NULL;
       
   370    }
   398    }
   371    if (comp->max_output_ptr != 0)
   399    if (comp->max_output_ptr != 0)
   372       png_free(png_ptr, comp->output_ptr);
   400       png_free(png_ptr, comp->output_ptr);
   373        comp->output_ptr=NULL;
       
   374    /* Write anything left in zbuf */
   401    /* Write anything left in zbuf */
   375    if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
   402    if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
   376       png_write_chunk_data(png_ptr, png_ptr->zbuf,
   403       png_write_chunk_data(png_ptr, png_ptr->zbuf,
   377          (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
   404          (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
   378 
   405 
   389 void /* PRIVATE */
   416 void /* PRIVATE */
   390 png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
   417 png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
   391    int bit_depth, int color_type, int compression_type, int filter_type,
   418    int bit_depth, int color_type, int compression_type, int filter_type,
   392    int interlace_type)
   419    int interlace_type)
   393 {
   420 {
   394 #ifdef PNG_USE_LOCAL_ARRAYS
       
   395    PNG_IHDR;
   421    PNG_IHDR;
   396 #endif
       
   397    int ret;
   422    int ret;
   398 
   423 
   399    png_byte buf[13]; /* Buffer to store the IHDR info */
   424    png_byte buf[13]; /* Buffer to store the IHDR info */
   400 
   425 
   401    png_debug(1, "in png_write_IHDR");
   426    png_debug(1, "in png_write_IHDR");
   457     *    included PNG_FLAG_MNG_FILTER_64 and
   482     *    included PNG_FLAG_MNG_FILTER_64 and
   458     * 4. The filter_method is 64 and
   483     * 4. The filter_method is 64 and
   459     * 5. The color_type is RGB or RGBA
   484     * 5. The color_type is RGB or RGBA
   460     */
   485     */
   461    if (
   486    if (
   462 #if defined(PNG_MNG_FEATURES_SUPPORTED)
   487 #ifdef PNG_MNG_FEATURES_SUPPORTED
   463       !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
   488       !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
   464       ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
   489       ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
   465       (color_type == PNG_COLOR_TYPE_RGB ||
   490       (color_type == PNG_COLOR_TYPE_RGB ||
   466        color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
   491        color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
   467       (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
   492       (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
   485 
   510 
   486    /* Save the relevent information */
   511    /* Save the relevent information */
   487    png_ptr->bit_depth = (png_byte)bit_depth;
   512    png_ptr->bit_depth = (png_byte)bit_depth;
   488    png_ptr->color_type = (png_byte)color_type;
   513    png_ptr->color_type = (png_byte)color_type;
   489    png_ptr->interlaced = (png_byte)interlace_type;
   514    png_ptr->interlaced = (png_byte)interlace_type;
   490 #if defined(PNG_MNG_FEATURES_SUPPORTED)
   515 #ifdef PNG_MNG_FEATURES_SUPPORTED
   491    png_ptr->filter_type = (png_byte)filter_type;
   516    png_ptr->filter_type = (png_byte)filter_type;
   492 #endif
   517 #endif
   493    png_ptr->compression_type = (png_byte)compression_type;
   518    png_ptr->compression_type = (png_byte)compression_type;
   494    png_ptr->width = width;
   519    png_ptr->width = width;
   495    png_ptr->height = height;
   520    png_ptr->height = height;
   567  * structure.
   592  * structure.
   568  */
   593  */
   569 void /* PRIVATE */
   594 void /* PRIVATE */
   570 png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
   595 png_write_PLTE(png_structp png_ptr, png_colorp palette, png_uint_32 num_pal)
   571 {
   596 {
   572 #ifdef PNG_USE_LOCAL_ARRAYS
       
   573    PNG_PLTE;
   597    PNG_PLTE;
   574 #endif
       
   575    png_uint_32 i;
   598    png_uint_32 i;
   576    png_colorp pal_ptr;
   599    png_colorp pal_ptr;
   577    png_byte buf[3];
   600    png_byte buf[3];
   578 
   601 
   579    png_debug(1, "in png_write_PLTE");
   602    png_debug(1, "in png_write_PLTE");
   580 
   603 
   581    if ((
   604    if ((
   582 #if defined(PNG_MNG_FEATURES_SUPPORTED)
   605 #ifdef PNG_MNG_FEATURES_SUPPORTED
   583         !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
   606         !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
   584 #endif
   607 #endif
   585         num_pal == 0) || num_pal > 256)
   608         num_pal == 0) || num_pal > 256)
   586    {
   609    {
   587      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   610      if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
   605    png_ptr->num_palette = (png_uint_16)num_pal;
   628    png_ptr->num_palette = (png_uint_16)num_pal;
   606    png_debug1(3, "num_palette = %d", png_ptr->num_palette);
   629    png_debug1(3, "num_palette = %d", png_ptr->num_palette);
   607 
   630 
   608    png_write_chunk_start(png_ptr, (png_bytep)png_PLTE,
   631    png_write_chunk_start(png_ptr, (png_bytep)png_PLTE,
   609      (png_uint_32)(num_pal * 3));
   632      (png_uint_32)(num_pal * 3));
   610 #ifndef PNG_NO_POINTER_INDEXING
   633 #ifdef PNG_POINTER_INDEXING_SUPPORTED
   611    for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
   634    for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
   612    {
   635    {
   613       buf[0] = pal_ptr->red;
   636       buf[0] = pal_ptr->red;
   614       buf[1] = pal_ptr->green;
   637       buf[1] = pal_ptr->green;
   615       buf[2] = pal_ptr->blue;
   638       buf[2] = pal_ptr->blue;
   632 
   655 
   633 /* Write an IDAT chunk */
   656 /* Write an IDAT chunk */
   634 void /* PRIVATE */
   657 void /* PRIVATE */
   635 png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
   658 png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
   636 {
   659 {
   637 #ifdef PNG_USE_LOCAL_ARRAYS
       
   638    PNG_IDAT;
   660    PNG_IDAT;
   639 #endif
       
   640 
   661 
   641    png_debug(1, "in png_write_IDAT");
   662    png_debug(1, "in png_write_IDAT");
   642 
   663 
   643    /* Optimize the CMF field in the zlib stream. */
   664    /* Optimize the CMF field in the zlib stream. */
   644    /* This hack of the zlib stream is compliant to the stream specification. */
   665    /* This hack of the zlib stream is compliant to the stream specification. */
   687 
   708 
   688 /* Write an IEND chunk */
   709 /* Write an IEND chunk */
   689 void /* PRIVATE */
   710 void /* PRIVATE */
   690 png_write_IEND(png_structp png_ptr)
   711 png_write_IEND(png_structp png_ptr)
   691 {
   712 {
   692 #ifdef PNG_USE_LOCAL_ARRAYS
       
   693    PNG_IEND;
   713    PNG_IEND;
   694 #endif
       
   695 
   714 
   696    png_debug(1, "in png_write_IEND");
   715    png_debug(1, "in png_write_IEND");
   697 
   716 
   698    png_write_chunk(png_ptr, (png_bytep)png_IEND, png_bytep_NULL,
   717    png_write_chunk(png_ptr, (png_bytep)png_IEND, NULL,
   699      (png_size_t)0);
   718      (png_size_t)0);
   700    png_ptr->mode |= PNG_HAVE_IEND;
   719    png_ptr->mode |= PNG_HAVE_IEND;
   701 }
   720 }
   702 
   721 
   703 #if defined(PNG_WRITE_gAMA_SUPPORTED)
   722 #ifdef PNG_WRITE_gAMA_SUPPORTED
   704 /* Write a gAMA chunk */
   723 /* Write a gAMA chunk */
   705 #ifdef PNG_FLOATING_POINT_SUPPORTED
   724 #ifdef PNG_FLOATING_POINT_SUPPORTED
   706 void /* PRIVATE */
   725 void /* PRIVATE */
   707 png_write_gAMA(png_structp png_ptr, double file_gamma)
   726 png_write_gAMA(png_structp png_ptr, double file_gamma)
   708 {
   727 {
   709 #ifdef PNG_USE_LOCAL_ARRAYS
       
   710    PNG_gAMA;
   728    PNG_gAMA;
   711 #endif
       
   712    png_uint_32 igamma;
   729    png_uint_32 igamma;
   713    png_byte buf[4];
   730    png_byte buf[4];
   714 
   731 
   715    png_debug(1, "in png_write_gAMA");
   732    png_debug(1, "in png_write_gAMA");
   716 
   733 
   722 #endif
   739 #endif
   723 #ifdef PNG_FIXED_POINT_SUPPORTED
   740 #ifdef PNG_FIXED_POINT_SUPPORTED
   724 void /* PRIVATE */
   741 void /* PRIVATE */
   725 png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
   742 png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
   726 {
   743 {
   727 #ifdef PNG_USE_LOCAL_ARRAYS
       
   728    PNG_gAMA;
   744    PNG_gAMA;
   729 #endif
       
   730    png_byte buf[4];
   745    png_byte buf[4];
   731 
   746 
   732    png_debug(1, "in png_write_gAMA");
   747    png_debug(1, "in png_write_gAMA");
   733 
   748 
   734    /* file_gamma is saved in 1/100,000ths */
   749    /* file_gamma is saved in 1/100,000ths */
   736    png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
   751    png_write_chunk(png_ptr, (png_bytep)png_gAMA, buf, (png_size_t)4);
   737 }
   752 }
   738 #endif
   753 #endif
   739 #endif
   754 #endif
   740 
   755 
   741 #if defined(PNG_WRITE_sRGB_SUPPORTED)
   756 #ifdef PNG_WRITE_sRGB_SUPPORTED
   742 /* Write a sRGB chunk */
   757 /* Write a sRGB chunk */
   743 void /* PRIVATE */
   758 void /* PRIVATE */
   744 png_write_sRGB(png_structp png_ptr, int srgb_intent)
   759 png_write_sRGB(png_structp png_ptr, int srgb_intent)
   745 {
   760 {
   746 #ifdef PNG_USE_LOCAL_ARRAYS
       
   747    PNG_sRGB;
   761    PNG_sRGB;
   748 #endif
       
   749    png_byte buf[1];
   762    png_byte buf[1];
   750 
   763 
   751    png_debug(1, "in png_write_sRGB");
   764    png_debug(1, "in png_write_sRGB");
   752 
   765 
   753    if (srgb_intent >= PNG_sRGB_INTENT_LAST)
   766    if (srgb_intent >= PNG_sRGB_INTENT_LAST)
   756    buf[0]=(png_byte)srgb_intent;
   769    buf[0]=(png_byte)srgb_intent;
   757    png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1);
   770    png_write_chunk(png_ptr, (png_bytep)png_sRGB, buf, (png_size_t)1);
   758 }
   771 }
   759 #endif
   772 #endif
   760 
   773 
   761 #if defined(PNG_WRITE_iCCP_SUPPORTED)
   774 #ifdef PNG_WRITE_iCCP_SUPPORTED
   762 /* Write an iCCP chunk */
   775 /* Write an iCCP chunk */
   763 void /* PRIVATE */
   776 void /* PRIVATE */
   764 png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
   777 png_write_iCCP(png_structp png_ptr, png_charp name, int compression_type,
   765    png_charp profile, int profile_len)
   778    png_charp profile, int profile_len)
   766 {
   779 {
   767 #ifdef PNG_USE_LOCAL_ARRAYS
       
   768    PNG_iCCP;
   780    PNG_iCCP;
   769 #endif
       
   770    png_size_t name_len;
   781    png_size_t name_len;
   771    png_charp new_name;
   782    png_charp new_name;
   772    compression_state comp;
   783    compression_state comp;
   773    int embedded_profile_len = 0;
   784    int embedded_profile_len = 0;
   774 
   785 
   837    png_write_chunk_end(png_ptr);
   848    png_write_chunk_end(png_ptr);
   838    png_free(png_ptr, new_name);
   849    png_free(png_ptr, new_name);
   839 }
   850 }
   840 #endif
   851 #endif
   841 
   852 
   842 #if defined(PNG_WRITE_sPLT_SUPPORTED)
   853 #ifdef PNG_WRITE_sPLT_SUPPORTED
   843 /* Write a sPLT chunk */
   854 /* Write a sPLT chunk */
   844 void /* PRIVATE */
   855 void /* PRIVATE */
   845 png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
   856 png_write_sPLT(png_structp png_ptr, png_sPLT_tp spalette)
   846 {
   857 {
   847 #ifdef PNG_USE_LOCAL_ARRAYS
       
   848    PNG_sPLT;
   858    PNG_sPLT;
   849 #endif
       
   850    png_size_t name_len;
   859    png_size_t name_len;
   851    png_charp new_name;
   860    png_charp new_name;
   852    png_byte entrybuf[10];
   861    png_byte entrybuf[10];
   853    int entry_size = (spalette->depth == 8 ? 6 : 10);
   862    png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
   854    int palette_size = entry_size * spalette->nentries;
   863    png_size_t palette_size = entry_size * spalette->nentries;
   855    png_sPLT_entryp ep;
   864    png_sPLT_entryp ep;
   856 #ifdef PNG_NO_POINTER_INDEXING
   865 #ifndef PNG_POINTER_INDEXING_SUPPORTED
   857    int i;
   866    int i;
   858 #endif
   867 #endif
   859 
   868 
   860    png_debug(1, "in png_write_sPLT");
   869    png_debug(1, "in png_write_sPLT");
   861 
   870 
   868    png_write_chunk_data(png_ptr, (png_bytep)new_name,
   877    png_write_chunk_data(png_ptr, (png_bytep)new_name,
   869      (png_size_t)(name_len + 1));
   878      (png_size_t)(name_len + 1));
   870    png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1);
   879    png_write_chunk_data(png_ptr, (png_bytep)&spalette->depth, (png_size_t)1);
   871 
   880 
   872    /* Loop through each palette entry, writing appropriately */
   881    /* Loop through each palette entry, writing appropriately */
   873 #ifndef PNG_NO_POINTER_INDEXING
   882 #ifdef PNG_POINTER_INDEXING_SUPPORTED
   874    for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
   883    for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
   875    {
   884    {
   876       if (spalette->depth == 8)
   885       if (spalette->depth == 8)
   877       {
   886       {
   878           entrybuf[0] = (png_byte)ep->red;
   887           entrybuf[0] = (png_byte)ep->red;
   918    png_write_chunk_end(png_ptr);
   927    png_write_chunk_end(png_ptr);
   919    png_free(png_ptr, new_name);
   928    png_free(png_ptr, new_name);
   920 }
   929 }
   921 #endif
   930 #endif
   922 
   931 
   923 #if defined(PNG_WRITE_sBIT_SUPPORTED)
   932 #ifdef PNG_WRITE_sBIT_SUPPORTED
   924 /* Write the sBIT chunk */
   933 /* Write the sBIT chunk */
   925 void /* PRIVATE */
   934 void /* PRIVATE */
   926 png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
   935 png_write_sBIT(png_structp png_ptr, png_color_8p sbit, int color_type)
   927 {
   936 {
   928 #ifdef PNG_USE_LOCAL_ARRAYS
       
   929    PNG_sBIT;
   937    PNG_sBIT;
   930 #endif
       
   931    png_byte buf[4];
   938    png_byte buf[4];
   932    png_size_t size;
   939    png_size_t size;
   933 
   940 
   934    png_debug(1, "in png_write_sBIT");
   941    png_debug(1, "in png_write_sBIT");
   935 
   942 
   975 
   982 
   976    png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size);
   983    png_write_chunk(png_ptr, (png_bytep)png_sBIT, buf, size);
   977 }
   984 }
   978 #endif
   985 #endif
   979 
   986 
   980 #if defined(PNG_WRITE_cHRM_SUPPORTED)
   987 #ifdef PNG_WRITE_cHRM_SUPPORTED
   981 /* Write the cHRM chunk */
   988 /* Write the cHRM chunk */
   982 #ifdef PNG_FLOATING_POINT_SUPPORTED
   989 #ifdef PNG_FLOATING_POINT_SUPPORTED
   983 void /* PRIVATE */
   990 void /* PRIVATE */
   984 png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
   991 png_write_cHRM(png_structp png_ptr, double white_x, double white_y,
   985    double red_x, double red_y, double green_x, double green_y,
   992    double red_x, double red_y, double green_x, double green_y,
   986    double blue_x, double blue_y)
   993    double blue_x, double blue_y)
   987 {
   994 {
   988 #ifdef PNG_USE_LOCAL_ARRAYS
       
   989    PNG_cHRM;
   995    PNG_cHRM;
   990 #endif
       
   991    png_byte buf[32];
   996    png_byte buf[32];
   992 
   997 
   993    png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y,
   998    png_fixed_point int_white_x, int_white_y, int_red_x, int_red_y,
   994       int_green_x, int_green_y, int_blue_x, int_blue_y;
   999       int_green_x, int_green_y, int_blue_x, int_blue_y;
   995 
  1000 
  1002    int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5);
  1007    int_green_x = (png_uint_32)(green_x * 100000.0 + 0.5);
  1003    int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5);
  1008    int_green_y = (png_uint_32)(green_y * 100000.0 + 0.5);
  1004    int_blue_x  = (png_uint_32)(blue_x  * 100000.0 + 0.5);
  1009    int_blue_x  = (png_uint_32)(blue_x  * 100000.0 + 0.5);
  1005    int_blue_y  = (png_uint_32)(blue_y  * 100000.0 + 0.5);
  1010    int_blue_y  = (png_uint_32)(blue_y  * 100000.0 + 0.5);
  1006 
  1011 
  1007 #if !defined(PNG_NO_CHECK_cHRM)
  1012 #ifdef PNG_CHECK_cHRM_SUPPORTED
  1008    if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y,
  1013    if (png_check_cHRM_fixed(png_ptr, int_white_x, int_white_y,
  1009       int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y))
  1014       int_red_x, int_red_y, int_green_x, int_green_y, int_blue_x, int_blue_y))
  1010 #endif
  1015 #endif
  1011    {
  1016    {
  1012       /* Each value is saved in 1/100,000ths */
  1017       /* Each value is saved in 1/100,000ths */
  1032 png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
  1037 png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
  1033    png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
  1038    png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
  1034    png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
  1039    png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
  1035    png_fixed_point blue_y)
  1040    png_fixed_point blue_y)
  1036 {
  1041 {
  1037 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1038    PNG_cHRM;
  1042    PNG_cHRM;
  1039 #endif
       
  1040    png_byte buf[32];
  1043    png_byte buf[32];
  1041 
  1044 
  1042    png_debug(1, "in png_write_cHRM");
  1045    png_debug(1, "in png_write_cHRM");
  1043 
  1046 
  1044    /* Each value is saved in 1/100,000ths */
  1047    /* Each value is saved in 1/100,000ths */
  1045 #if !defined(PNG_NO_CHECK_cHRM)
  1048 #ifdef PNG_CHECK_cHRM_SUPPORTED
  1046    if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
  1049    if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
  1047       green_x, green_y, blue_x, blue_y))
  1050       green_x, green_y, blue_x, blue_y))
  1048 #endif
  1051 #endif
  1049    {
  1052    {
  1050       png_save_uint_32(buf, (png_uint_32)white_x);
  1053       png_save_uint_32(buf, (png_uint_32)white_x);
  1063    }
  1066    }
  1064 }
  1067 }
  1065 #endif
  1068 #endif
  1066 #endif
  1069 #endif
  1067 
  1070 
  1068 #if defined(PNG_WRITE_tRNS_SUPPORTED)
  1071 #ifdef PNG_WRITE_tRNS_SUPPORTED
  1069 /* Write the tRNS chunk */
  1072 /* Write the tRNS chunk */
  1070 void /* PRIVATE */
  1073 void /* PRIVATE */
  1071 png_write_tRNS(png_structp png_ptr, png_bytep trans, png_color_16p tran,
  1074 png_write_tRNS(png_structp png_ptr, png_bytep trans_alpha, png_color_16p tran,
  1072    int num_trans, int color_type)
  1075    int num_trans, int color_type)
  1073 {
  1076 {
  1074 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1075    PNG_tRNS;
  1077    PNG_tRNS;
  1076 #endif
       
  1077    png_byte buf[6];
  1078    png_byte buf[6];
  1078 
  1079 
  1079    png_debug(1, "in png_write_tRNS");
  1080    png_debug(1, "in png_write_tRNS");
  1080 
  1081 
  1081    if (color_type == PNG_COLOR_TYPE_PALETTE)
  1082    if (color_type == PNG_COLOR_TYPE_PALETTE)
  1084       {
  1085       {
  1085          png_warning(png_ptr, "Invalid number of transparent colors specified");
  1086          png_warning(png_ptr, "Invalid number of transparent colors specified");
  1086          return;
  1087          return;
  1087       }
  1088       }
  1088       /* Write the chunk out as it is */
  1089       /* Write the chunk out as it is */
  1089       png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans,
  1090       png_write_chunk(png_ptr, (png_bytep)png_tRNS, trans_alpha,
  1090         (png_size_t)num_trans);
  1091         (png_size_t)num_trans);
  1091    }
  1092    }
  1092    else if (color_type == PNG_COLOR_TYPE_GRAY)
  1093    else if (color_type == PNG_COLOR_TYPE_GRAY)
  1093    {
  1094    {
  1094       /* One 16 bit value */
  1095       /* One 16 bit value */
  1120       png_warning(png_ptr, "Can't write tRNS with an alpha channel");
  1121       png_warning(png_ptr, "Can't write tRNS with an alpha channel");
  1121    }
  1122    }
  1122 }
  1123 }
  1123 #endif
  1124 #endif
  1124 
  1125 
  1125 #if defined(PNG_WRITE_bKGD_SUPPORTED)
  1126 #ifdef PNG_WRITE_bKGD_SUPPORTED
  1126 /* Write the background chunk */
  1127 /* Write the background chunk */
  1127 void /* PRIVATE */
  1128 void /* PRIVATE */
  1128 png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
  1129 png_write_bKGD(png_structp png_ptr, png_color_16p back, int color_type)
  1129 {
  1130 {
  1130 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1131    PNG_bKGD;
  1131    PNG_bKGD;
  1132 #endif
       
  1133    png_byte buf[6];
  1132    png_byte buf[6];
  1134 
  1133 
  1135    png_debug(1, "in png_write_bKGD");
  1134    png_debug(1, "in png_write_bKGD");
  1136 
  1135 
  1137    if (color_type == PNG_COLOR_TYPE_PALETTE)
  1136    if (color_type == PNG_COLOR_TYPE_PALETTE)
  1138    {
  1137    {
  1139       if (
  1138       if (
  1140 #if defined(PNG_MNG_FEATURES_SUPPORTED)
  1139 #ifdef PNG_MNG_FEATURES_SUPPORTED
  1141           (png_ptr->num_palette ||
  1140           (png_ptr->num_palette ||
  1142           (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
  1141           (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
  1143 #endif
  1142 #endif
  1144          back->index >= png_ptr->num_palette)
  1143          back->index >= png_ptr->num_palette)
  1145       {
  1144       {
  1174       png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2);
  1173       png_write_chunk(png_ptr, (png_bytep)png_bKGD, buf, (png_size_t)2);
  1175    }
  1174    }
  1176 }
  1175 }
  1177 #endif
  1176 #endif
  1178 
  1177 
  1179 #if defined(PNG_WRITE_hIST_SUPPORTED)
  1178 #ifdef PNG_WRITE_hIST_SUPPORTED
  1180 /* Write the histogram */
  1179 /* Write the histogram */
  1181 void /* PRIVATE */
  1180 void /* PRIVATE */
  1182 png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
  1181 png_write_hIST(png_structp png_ptr, png_uint_16p hist, int num_hist)
  1183 {
  1182 {
  1184 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1185    PNG_hIST;
  1183    PNG_hIST;
  1186 #endif
       
  1187    int i;
  1184    int i;
  1188    png_byte buf[3];
  1185    png_byte buf[3];
  1189 
  1186 
  1190    png_debug(1, "in png_write_hIST");
  1187    png_debug(1, "in png_write_hIST");
  1191 
  1188 
  1251    for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
  1248    for (kp = key, dp = *new_key; *kp != '\0'; kp++, dp++)
  1252    {
  1249    {
  1253       if ((png_byte)*kp < 0x20 ||
  1250       if ((png_byte)*kp < 0x20 ||
  1254          ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1))
  1251          ((png_byte)*kp > 0x7E && (png_byte)*kp < 0xA1))
  1255       {
  1252       {
  1256 #if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
  1253 #ifdef PNG_STDIO_SUPPORTED
  1257          char msg[40];
  1254          char msg[40];
  1258 
  1255 
  1259          png_snprintf(msg, 40,
  1256          png_snprintf(msg, 40,
  1260            "invalid keyword character 0x%02X", (png_byte)*kp);
  1257            "invalid keyword character 0x%02X", (png_byte)*kp);
  1261          png_warning(png_ptr, msg);
  1258          png_warning(png_ptr, msg);
  1323       png_warning(png_ptr, "extra interior spaces removed from keyword");
  1320       png_warning(png_ptr, "extra interior spaces removed from keyword");
  1324 
  1321 
  1325    if (key_len == 0)
  1322    if (key_len == 0)
  1326    {
  1323    {
  1327       png_free(png_ptr, *new_key);
  1324       png_free(png_ptr, *new_key);
  1328        *new_key=NULL;
       
  1329       png_warning(png_ptr, "Zero length keyword");
  1325       png_warning(png_ptr, "Zero length keyword");
  1330    }
  1326    }
  1331 
  1327 
  1332    if (key_len > 79)
  1328    if (key_len > 79)
  1333    {
  1329    {
  1338 
  1334 
  1339    return (key_len);
  1335    return (key_len);
  1340 }
  1336 }
  1341 #endif
  1337 #endif
  1342 
  1338 
  1343 #if defined(PNG_WRITE_tEXt_SUPPORTED)
  1339 #ifdef PNG_WRITE_tEXt_SUPPORTED
  1344 /* Write a tEXt chunk */
  1340 /* Write a tEXt chunk */
  1345 void /* PRIVATE */
  1341 void /* PRIVATE */
  1346 png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
  1342 png_write_tEXt(png_structp png_ptr, png_charp key, png_charp text,
  1347    png_size_t text_len)
  1343    png_size_t text_len)
  1348 {
  1344 {
  1349 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1350    PNG_tEXt;
  1345    PNG_tEXt;
  1351 #endif
       
  1352    png_size_t key_len;
  1346    png_size_t key_len;
  1353    png_charp new_key;
  1347    png_charp new_key;
  1354 
  1348 
  1355    png_debug(1, "in png_write_tEXt");
  1349    png_debug(1, "in png_write_tEXt");
  1356 
  1350 
  1379    png_write_chunk_end(png_ptr);
  1373    png_write_chunk_end(png_ptr);
  1380    png_free(png_ptr, new_key);
  1374    png_free(png_ptr, new_key);
  1381 }
  1375 }
  1382 #endif
  1376 #endif
  1383 
  1377 
  1384 #if defined(PNG_WRITE_zTXt_SUPPORTED)
  1378 #ifdef PNG_WRITE_zTXt_SUPPORTED
  1385 /* Write a compressed text chunk */
  1379 /* Write a compressed text chunk */
  1386 void /* PRIVATE */
  1380 void /* PRIVATE */
  1387 png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
  1381 png_write_zTXt(png_structp png_ptr, png_charp key, png_charp text,
  1388    png_size_t text_len, int compression)
  1382    png_size_t text_len, int compression)
  1389 {
  1383 {
  1390 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1391    PNG_zTXt;
  1384    PNG_zTXt;
  1392 #endif
       
  1393    png_size_t key_len;
  1385    png_size_t key_len;
  1394    char buf[1];
  1386    char buf[1];
  1395    png_charp new_key;
  1387    png_charp new_key;
  1396    compression_state comp;
  1388    compression_state comp;
  1397 
  1389 
  1439    /* Close the chunk */
  1431    /* Close the chunk */
  1440    png_write_chunk_end(png_ptr);
  1432    png_write_chunk_end(png_ptr);
  1441 }
  1433 }
  1442 #endif
  1434 #endif
  1443 
  1435 
  1444 #if defined(PNG_WRITE_iTXt_SUPPORTED)
  1436 #ifdef PNG_WRITE_iTXt_SUPPORTED
  1445 /* Write an iTXt chunk */
  1437 /* Write an iTXt chunk */
  1446 void /* PRIVATE */
  1438 void /* PRIVATE */
  1447 png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
  1439 png_write_iTXt(png_structp png_ptr, int compression, png_charp key,
  1448     png_charp lang, png_charp lang_key, png_charp text)
  1440     png_charp lang, png_charp lang_key, png_charp text)
  1449 {
  1441 {
  1450 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1451    PNG_iTXt;
  1442    PNG_iTXt;
  1452 #endif
       
  1453    png_size_t lang_len, key_len, lang_key_len, text_len;
  1443    png_size_t lang_len, key_len, lang_key_len, text_len;
  1454    png_charp new_lang;
  1444    png_charp new_lang;
  1455    png_charp new_key = NULL;
  1445    png_charp new_key = NULL;
  1456    png_byte cbuf[2];
  1446    png_byte cbuf[2];
  1457    compression_state comp;
  1447    compression_state comp;
  1528    png_free(png_ptr, new_key);
  1518    png_free(png_ptr, new_key);
  1529    png_free(png_ptr, new_lang);
  1519    png_free(png_ptr, new_lang);
  1530 }
  1520 }
  1531 #endif
  1521 #endif
  1532 
  1522 
  1533 #if defined(PNG_WRITE_oFFs_SUPPORTED)
  1523 #ifdef PNG_WRITE_oFFs_SUPPORTED
  1534 /* Write the oFFs chunk */
  1524 /* Write the oFFs chunk */
  1535 void /* PRIVATE */
  1525 void /* PRIVATE */
  1536 png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
  1526 png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
  1537    int unit_type)
  1527    int unit_type)
  1538 {
  1528 {
  1539 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1540    PNG_oFFs;
  1529    PNG_oFFs;
  1541 #endif
       
  1542    png_byte buf[9];
  1530    png_byte buf[9];
  1543 
  1531 
  1544    png_debug(1, "in png_write_oFFs");
  1532    png_debug(1, "in png_write_oFFs");
  1545 
  1533 
  1546    if (unit_type >= PNG_OFFSET_LAST)
  1534    if (unit_type >= PNG_OFFSET_LAST)
  1551    buf[8] = (png_byte)unit_type;
  1539    buf[8] = (png_byte)unit_type;
  1552 
  1540 
  1553    png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9);
  1541    png_write_chunk(png_ptr, (png_bytep)png_oFFs, buf, (png_size_t)9);
  1554 }
  1542 }
  1555 #endif
  1543 #endif
  1556 #if defined(PNG_WRITE_pCAL_SUPPORTED)
  1544 #ifdef PNG_WRITE_pCAL_SUPPORTED
  1557 /* Write the pCAL chunk (described in the PNG extensions document) */
  1545 /* Write the pCAL chunk (described in the PNG extensions document) */
  1558 void /* PRIVATE */
  1546 void /* PRIVATE */
  1559 png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
  1547 png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
  1560    png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
  1548    png_int_32 X1, int type, int nparams, png_charp units, png_charpp params)
  1561 {
  1549 {
  1562 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1563    PNG_pCAL;
  1550    PNG_pCAL;
  1564 #endif
       
  1565    png_size_t purpose_len, units_len, total_len;
  1551    png_size_t purpose_len, units_len, total_len;
  1566    png_uint_32p params_len;
  1552    png_uint_32p params_len;
  1567    png_byte buf[10];
  1553    png_byte buf[10];
  1568    png_charp new_purpose;
  1554    png_charp new_purpose;
  1569    int i;
  1555    int i;
  1578    units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
  1564    units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
  1579    png_debug1(3, "pCAL units length = %d", (int)units_len);
  1565    png_debug1(3, "pCAL units length = %d", (int)units_len);
  1580    total_len = purpose_len + units_len + 10;
  1566    total_len = purpose_len + units_len + 10;
  1581 
  1567 
  1582    params_len = (png_uint_32p)png_malloc(png_ptr,
  1568    params_len = (png_uint_32p)png_malloc(png_ptr,
  1583       (png_uint_32)(nparams * png_sizeof(png_uint_32)));
  1569       (png_alloc_size_t)(nparams * png_sizeof(png_uint_32)));
  1584 
  1570 
  1585    /* Find the length of each parameter, making sure we don't count the
  1571    /* Find the length of each parameter, making sure we don't count the
  1586       null terminator for the last parameter. */
  1572       null terminator for the last parameter. */
  1587    for (i = 0; i < nparams; i++)
  1573    for (i = 0; i < nparams; i++)
  1588    {
  1574    {
  1614    png_free(png_ptr, params_len);
  1600    png_free(png_ptr, params_len);
  1615    png_write_chunk_end(png_ptr);
  1601    png_write_chunk_end(png_ptr);
  1616 }
  1602 }
  1617 #endif
  1603 #endif
  1618 
  1604 
  1619 #if defined(PNG_WRITE_sCAL_SUPPORTED)
  1605 #ifdef PNG_WRITE_sCAL_SUPPORTED
  1620 /* Write the sCAL chunk */
  1606 /* Write the sCAL chunk */
  1621 #if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
  1607 #if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
  1622 void /* PRIVATE */
  1608 void /* PRIVATE */
  1623 png_write_sCAL(png_structp png_ptr, int unit, double width, double height)
  1609 png_write_sCAL(png_structp png_ptr, int unit, double width, double height)
  1624 {
  1610 {
  1625 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1626    PNG_sCAL;
  1611    PNG_sCAL;
  1627 #endif
       
  1628    char buf[64];
  1612    char buf[64];
  1629    png_size_t total_len;
  1613    png_size_t total_len;
  1630 
  1614 
  1631    png_debug(1, "in png_write_sCAL");
  1615    png_debug(1, "in png_write_sCAL");
  1632 
  1616 
  1633    buf[0] = (char)unit;
  1617    buf[0] = (char)unit;
  1634 #if defined(_WIN32_WCE)
       
  1635 /* sprintf() function is not supported on WindowsCE */
       
  1636    {
       
  1637       wchar_t wc_buf[32];
       
  1638       size_t wc_len;
       
  1639       swprintf(wc_buf, TEXT("%12.12e"), width);
       
  1640       wc_len = wcslen(wc_buf);
       
  1641       WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + 1, wc_len, NULL, NULL);
       
  1642       total_len = wc_len + 2;
       
  1643       swprintf(wc_buf, TEXT("%12.12e"), height);
       
  1644       wc_len = wcslen(wc_buf);
       
  1645       WideCharToMultiByte(CP_ACP, 0, wc_buf, -1, buf + total_len, wc_len,
       
  1646          NULL, NULL);
       
  1647       total_len += wc_len;
       
  1648    }
       
  1649 #else
       
  1650    png_snprintf(buf + 1, 63, "%12.12e", width);
  1618    png_snprintf(buf + 1, 63, "%12.12e", width);
  1651    total_len = 1 + png_strlen(buf + 1) + 1;
  1619    total_len = 1 + png_strlen(buf + 1) + 1;
  1652    png_snprintf(buf + total_len, 64-total_len, "%12.12e", height);
  1620    png_snprintf(buf + total_len, 64-total_len, "%12.12e", height);
  1653    total_len += png_strlen(buf + total_len);
  1621    total_len += png_strlen(buf + total_len);
  1654 #endif
       
  1655 
  1622 
  1656    png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
  1623    png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
  1657    png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len);
  1624    png_write_chunk(png_ptr, (png_bytep)png_sCAL, (png_bytep)buf, total_len);
  1658 }
  1625 }
  1659 #else
  1626 #else
  1660 #ifdef PNG_FIXED_POINT_SUPPORTED
  1627 #ifdef PNG_FIXED_POINT_SUPPORTED
  1661 void /* PRIVATE */
  1628 void /* PRIVATE */
  1662 png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
  1629 png_write_sCAL_s(png_structp png_ptr, int unit, png_charp width,
  1663    png_charp height)
  1630    png_charp height)
  1664 {
  1631 {
  1665 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1666    PNG_sCAL;
  1632    PNG_sCAL;
  1667 #endif
       
  1668    png_byte buf[64];
  1633    png_byte buf[64];
  1669    png_size_t wlen, hlen, total_len;
  1634    png_size_t wlen, hlen, total_len;
  1670 
  1635 
  1671    png_debug(1, "in png_write_sCAL_s");
  1636    png_debug(1, "in png_write_sCAL_s");
  1672 
  1637 
  1688 }
  1653 }
  1689 #endif
  1654 #endif
  1690 #endif
  1655 #endif
  1691 #endif
  1656 #endif
  1692 
  1657 
  1693 #if defined(PNG_WRITE_pHYs_SUPPORTED)
  1658 #ifdef PNG_WRITE_pHYs_SUPPORTED
  1694 /* Write the pHYs chunk */
  1659 /* Write the pHYs chunk */
  1695 void /* PRIVATE */
  1660 void /* PRIVATE */
  1696 png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
  1661 png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
  1697    png_uint_32 y_pixels_per_unit,
  1662    png_uint_32 y_pixels_per_unit,
  1698    int unit_type)
  1663    int unit_type)
  1699 {
  1664 {
  1700 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1701    PNG_pHYs;
  1665    PNG_pHYs;
  1702 #endif
       
  1703    png_byte buf[9];
  1666    png_byte buf[9];
  1704 
  1667 
  1705    png_debug(1, "in png_write_pHYs");
  1668    png_debug(1, "in png_write_pHYs");
  1706 
  1669 
  1707    if (unit_type >= PNG_RESOLUTION_LAST)
  1670    if (unit_type >= PNG_RESOLUTION_LAST)
  1713 
  1676 
  1714    png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9);
  1677    png_write_chunk(png_ptr, (png_bytep)png_pHYs, buf, (png_size_t)9);
  1715 }
  1678 }
  1716 #endif
  1679 #endif
  1717 
  1680 
  1718 #if defined(PNG_WRITE_tIME_SUPPORTED)
  1681 #ifdef PNG_WRITE_tIME_SUPPORTED
  1719 /* Write the tIME chunk.  Use either png_convert_from_struct_tm()
  1682 /* Write the tIME chunk.  Use either png_convert_from_struct_tm()
  1720  * or png_convert_from_time_t(), or fill in the structure yourself.
  1683  * or png_convert_from_time_t(), or fill in the structure yourself.
  1721  */
  1684  */
  1722 void /* PRIVATE */
  1685 void /* PRIVATE */
  1723 png_write_tIME(png_structp png_ptr, png_timep mod_time)
  1686 png_write_tIME(png_structp png_ptr, png_timep mod_time)
  1724 {
  1687 {
  1725 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1726    PNG_tIME;
  1688    PNG_tIME;
  1727 #endif
       
  1728    png_byte buf[7];
  1689    png_byte buf[7];
  1729 
  1690 
  1730    png_debug(1, "in png_write_tIME");
  1691    png_debug(1, "in png_write_tIME");
  1731 
  1692 
  1732    if (mod_time->month  > 12 || mod_time->month  < 1 ||
  1693    if (mod_time->month  > 12 || mod_time->month  < 1 ||
  1751 /* Initializes the row writing capability of libpng */
  1712 /* Initializes the row writing capability of libpng */
  1752 void /* PRIVATE */
  1713 void /* PRIVATE */
  1753 png_write_start_row(png_structp png_ptr)
  1714 png_write_start_row(png_structp png_ptr)
  1754 {
  1715 {
  1755 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1716 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1756 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1757    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  1717    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  1758 
  1718 
  1759    /* Start of interlace block */
  1719    /* Start of interlace block */
  1760    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  1720    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  1761 
  1721 
  1766    int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
  1726    int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
  1767 
  1727 
  1768    /* Offset to next interlace block in the y direction */
  1728    /* Offset to next interlace block in the y direction */
  1769    int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
  1729    int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
  1770 #endif
  1730 #endif
  1771 #endif
       
  1772 
  1731 
  1773    png_size_t buf_size;
  1732    png_size_t buf_size;
  1774 
  1733 
  1775    png_debug(1, "in png_write_start_row");
  1734    png_debug(1, "in png_write_start_row");
  1776 
  1735 
  1777    buf_size = (png_size_t)(PNG_ROWBYTES(
  1736    buf_size = (png_size_t)(PNG_ROWBYTES(
  1778       png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1);
  1737       png_ptr->usr_channels*png_ptr->usr_bit_depth, png_ptr->width) + 1);
  1779 
  1738 
  1780    /* Set up row buffer */
  1739    /* Set up row buffer */
  1781    png_ptr->row_buf = (png_bytep)png_malloc(png_ptr,
  1740    png_ptr->row_buf = (png_bytep)png_malloc(png_ptr,
  1782      (png_uint_32)buf_size);
  1741      (png_alloc_size_t)buf_size);
  1783    png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
  1742    png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
  1784 
  1743 
  1785 #ifndef PNG_NO_WRITE_FILTER
  1744 #ifdef PNG_WRITE_FILTER_SUPPORTED
  1786    /* Set up filtering buffer, if using this filter */
  1745    /* Set up filtering buffer, if using this filter */
  1787    if (png_ptr->do_filter & PNG_FILTER_SUB)
  1746    if (png_ptr->do_filter & PNG_FILTER_SUB)
  1788    {
  1747    {
  1789       png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
  1748       png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
  1790          (png_uint_32)(png_ptr->rowbytes + 1));
  1749          (png_alloc_size_t)(png_ptr->rowbytes + 1));
  1791       png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
  1750       png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
  1792    }
  1751    }
  1793 
  1752 
  1794    /* We only need to keep the previous row if we are using one of these. */
  1753    /* We only need to keep the previous row if we are using one of these. */
  1795    if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
  1754    if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
  1796    {
  1755    {
  1797      /* Set up previous row buffer */
  1756       /* Set up previous row buffer */
  1798      png_ptr->prev_row = (png_bytep)png_malloc(png_ptr,
  1757       png_ptr->prev_row = (png_bytep)png_calloc(png_ptr,
  1799         (png_uint_32)buf_size);
  1758          (png_alloc_size_t)buf_size);
  1800      png_memset(png_ptr->prev_row, 0, buf_size);
       
  1801 
  1759 
  1802       if (png_ptr->do_filter & PNG_FILTER_UP)
  1760       if (png_ptr->do_filter & PNG_FILTER_UP)
  1803       {
  1761       {
  1804          png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
  1762          png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
  1805            (png_uint_32)(png_ptr->rowbytes + 1));
  1763             (png_size_t)(png_ptr->rowbytes + 1));
  1806          png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
  1764          png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
  1807       }
  1765       }
  1808 
  1766 
  1809       if (png_ptr->do_filter & PNG_FILTER_AVG)
  1767       if (png_ptr->do_filter & PNG_FILTER_AVG)
  1810       {
  1768       {
  1811          png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
  1769          png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
  1812            (png_uint_32)(png_ptr->rowbytes + 1));
  1770             (png_alloc_size_t)(png_ptr->rowbytes + 1));
  1813          png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
  1771          png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
  1814       }
  1772       }
  1815 
  1773 
  1816       if (png_ptr->do_filter & PNG_FILTER_PAETH)
  1774       if (png_ptr->do_filter & PNG_FILTER_PAETH)
  1817       {
  1775       {
  1818          png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
  1776          png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
  1819            (png_uint_32)(png_ptr->rowbytes + 1));
  1777             (png_size_t)(png_ptr->rowbytes + 1));
  1820          png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
  1778          png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
  1821       }
  1779       }
  1822    }
  1780    }
  1823 #endif /* PNG_NO_WRITE_FILTER */
  1781 #endif /* PNG_WRITE_FILTER_SUPPORTED */
  1824 
  1782 
  1825 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1783 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1826    /* If interlaced, we need to set up width and height of pass */
  1784    /* If interlaced, we need to set up width and height of pass */
  1827    if (png_ptr->interlaced)
  1785    if (png_ptr->interlaced)
  1828    {
  1786    {
  1852 /* Internal use only.  Called when finished processing a row of data. */
  1810 /* Internal use only.  Called when finished processing a row of data. */
  1853 void /* PRIVATE */
  1811 void /* PRIVATE */
  1854 png_write_finish_row(png_structp png_ptr)
  1812 png_write_finish_row(png_structp png_ptr)
  1855 {
  1813 {
  1856 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1814 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1857 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1858    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  1815    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  1859 
  1816 
  1860    /* Start of interlace block */
  1817    /* Start of interlace block */
  1861    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  1818    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  1862 
  1819 
  1866    /* Start of interlace block in the y direction */
  1823    /* Start of interlace block in the y direction */
  1867    int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
  1824    int png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
  1868 
  1825 
  1869    /* Offset to next interlace block in the y direction */
  1826    /* Offset to next interlace block in the y direction */
  1870    int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
  1827    int png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
  1871 #endif
       
  1872 #endif
  1828 #endif
  1873 
  1829 
  1874    int ret;
  1830    int ret;
  1875 
  1831 
  1876    png_debug(1, "in png_write_finish_row");
  1832    png_debug(1, "in png_write_finish_row");
  1960 
  1916 
  1961    deflateReset(&png_ptr->zstream);
  1917    deflateReset(&png_ptr->zstream);
  1962    png_ptr->zstream.data_type = Z_BINARY;
  1918    png_ptr->zstream.data_type = Z_BINARY;
  1963 }
  1919 }
  1964 
  1920 
  1965 #if defined(PNG_WRITE_INTERLACING_SUPPORTED)
  1921 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
  1966 /* Pick out the correct pixels for the interlace pass.
  1922 /* Pick out the correct pixels for the interlace pass.
  1967  * The basic idea here is to go through the row with a source
  1923  * The basic idea here is to go through the row with a source
  1968  * pointer and a destination pointer (sp and dp), and copy the
  1924  * pointer and a destination pointer (sp and dp), and copy the
  1969  * correct pixels for the pass.  As the row gets compacted,
  1925  * correct pixels for the pass.  As the row gets compacted,
  1970  * sp will always be >= dp, so we should never overwrite anything.
  1926  * sp will always be >= dp, so we should never overwrite anything.
  1971  * See the default: case for the easiest code to understand.
  1927  * See the default: case for the easiest code to understand.
  1972  */
  1928  */
  1973 void /* PRIVATE */
  1929 void /* PRIVATE */
  1974 png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
  1930 png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
  1975 {
  1931 {
  1976 #ifdef PNG_USE_LOCAL_ARRAYS
       
  1977    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  1932    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
  1978 
  1933 
  1979    /* Start of interlace block */
  1934    /* Start of interlace block */
  1980    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  1935    int png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
  1981 
  1936 
  1982    /* Offset to next interlace block */
  1937    /* Offset to next interlace block */
  1983    int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
  1938    int png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
  1984 #endif
       
  1985 
  1939 
  1986    png_debug(1, "in png_do_write_interlace");
  1940    png_debug(1, "in png_do_write_interlace");
  1987 
  1941 
  1988    /* We don't have to do anything on the last pass (6) */
  1942    /* We don't have to do anything on the last pass (6) */
  1989 #if defined(PNG_USELESS_TESTS_SUPPORTED)
       
  1990    if (row != NULL && row_info != NULL && pass < 6)
       
  1991 #else
       
  1992    if (pass < 6)
  1943    if (pass < 6)
  1993 #endif
       
  1994    {
  1944    {
  1995       /* Each pixel depth is handled separately */
  1945       /* Each pixel depth is handled separately */
  1996       switch (row_info->pixel_depth)
  1946       switch (row_info->pixel_depth)
  1997       {
  1947       {
  1998          case 1:
  1948          case 1:
  2144 #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
  2094 #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
  2145 void /* PRIVATE */
  2095 void /* PRIVATE */
  2146 png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
  2096 png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
  2147 {
  2097 {
  2148    png_bytep best_row;
  2098    png_bytep best_row;
  2149 #ifndef PNG_NO_WRITE_FILTER
  2099 #ifdef PNG_WRITE_FILTER_SUPPORTED
  2150    png_bytep prev_row, row_buf;
  2100    png_bytep prev_row, row_buf;
  2151    png_uint_32 mins, bpp;
  2101    png_uint_32 mins, bpp;
  2152    png_byte filter_to_do = png_ptr->do_filter;
  2102    png_byte filter_to_do = png_ptr->do_filter;
  2153    png_uint_32 row_bytes = row_info->rowbytes;
  2103    png_uint_32 row_bytes = row_info->rowbytes;
  2154 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2104 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2155    int num_p_filters = (int)png_ptr->num_prev_filters;
  2105    int num_p_filters = (int)png_ptr->num_prev_filters;
  2156 #endif 
  2106 #endif 
  2157 
  2107 
  2158    png_debug(1, "in png_write_find_filter");
  2108    png_debug(1, "in png_write_find_filter");
  2159 
  2109 
       
  2110 #ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
       
  2111   if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
       
  2112   {
       
  2113       /* These will never be selected so we need not test them. */
       
  2114       filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
       
  2115   }
       
  2116 #endif 
       
  2117 
  2160    /* Find out how many bytes offset each pixel is */
  2118    /* Find out how many bytes offset each pixel is */
  2161    bpp = (row_info->pixel_depth + 7) >> 3;
  2119    bpp = (row_info->pixel_depth + 7) >> 3;
  2162 
  2120 
  2163    prev_row = png_ptr->prev_row;
  2121    prev_row = png_ptr->prev_row;
  2164 #endif
  2122 #endif
  2165    best_row = png_ptr->row_buf;
  2123    best_row = png_ptr->row_buf;
  2166 #ifndef PNG_NO_WRITE_FILTER
  2124 #ifdef PNG_WRITE_FILTER_SUPPORTED
  2167    row_buf = best_row;
  2125    row_buf = best_row;
  2168    mins = PNG_MAXSUM;
  2126    mins = PNG_MAXSUM;
  2169 
  2127 
  2170    /* The prediction method we use is to find which method provides the
  2128    /* The prediction method we use is to find which method provides the
  2171     * smallest value when summing the absolute values of the distances
  2129     * smallest value when summing the absolute values of the distances
  2204       {
  2162       {
  2205          v = *rp;
  2163          v = *rp;
  2206          sum += (v < 128) ? v : 256 - v;
  2164          sum += (v < 128) ? v : 256 - v;
  2207       }
  2165       }
  2208 
  2166 
  2209 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  2167 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2210       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2168       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2211       {
  2169       {
  2212          png_uint_32 sumhi, sumlo;
  2170          png_uint_32 sumhi, sumlo;
  2213          int j;
  2171          int j;
  2214          sumlo = sum & PNG_LOMASK;
  2172          sumlo = sum & PNG_LOMASK;
  2268       png_bytep rp, dp, lp;
  2226       png_bytep rp, dp, lp;
  2269       png_uint_32 sum = 0, lmins = mins;
  2227       png_uint_32 sum = 0, lmins = mins;
  2270       png_uint_32 i;
  2228       png_uint_32 i;
  2271       int v;
  2229       int v;
  2272 
  2230 
  2273 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  2231 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2274       /* We temporarily increase the "minimum sum" by the factor we
  2232       /* We temporarily increase the "minimum sum" by the factor we
  2275        * would reduce the sum of this filter, so that we can do the
  2233        * would reduce the sum of this filter, so that we can do the
  2276        * early exit comparison without scaling the sum each time.
  2234        * early exit comparison without scaling the sum each time.
  2277        */
  2235        */
  2278       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2236       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2321 
  2279 
  2322          if (sum > lmins)  /* We are already worse, don't continue. */
  2280          if (sum > lmins)  /* We are already worse, don't continue. */
  2323             break;
  2281             break;
  2324       }
  2282       }
  2325 
  2283 
  2326 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  2284 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2327       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2285       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2328       {
  2286       {
  2329          int j;
  2287          int j;
  2330          png_uint_32 sumhi, sumlo;
  2288          png_uint_32 sumhi, sumlo;
  2331          sumlo = sum & PNG_LOMASK;
  2289          sumlo = sum & PNG_LOMASK;
  2382       png_uint_32 sum = 0, lmins = mins;
  2340       png_uint_32 sum = 0, lmins = mins;
  2383       png_uint_32 i;
  2341       png_uint_32 i;
  2384       int v;
  2342       int v;
  2385 
  2343 
  2386 
  2344 
  2387 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  2345 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2388       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2346       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2389       {
  2347       {
  2390          int j;
  2348          int j;
  2391          png_uint_32 lmhi, lmlo;
  2349          png_uint_32 lmhi, lmlo;
  2392          lmlo = lmins & PNG_LOMASK;
  2350          lmlo = lmins & PNG_LOMASK;
  2424 
  2382 
  2425          if (sum > lmins)  /* We are already worse, don't continue. */
  2383          if (sum > lmins)  /* We are already worse, don't continue. */
  2426             break;
  2384             break;
  2427       }
  2385       }
  2428 
  2386 
  2429 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  2387 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2430       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2388       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2431       {
  2389       {
  2432          int j;
  2390          int j;
  2433          png_uint_32 sumhi, sumlo;
  2391          png_uint_32 sumhi, sumlo;
  2434          sumlo = sum & PNG_LOMASK;
  2392          sumlo = sum & PNG_LOMASK;
  2487       png_bytep rp, dp, pp, lp;
  2445       png_bytep rp, dp, pp, lp;
  2488       png_uint_32 sum = 0, lmins = mins;
  2446       png_uint_32 sum = 0, lmins = mins;
  2489       png_uint_32 i;
  2447       png_uint_32 i;
  2490       int v;
  2448       int v;
  2491 
  2449 
  2492 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  2450 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2493       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2451       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2494       {
  2452       {
  2495          int j;
  2453          int j;
  2496          png_uint_32 lmhi, lmlo;
  2454          png_uint_32 lmhi, lmlo;
  2497          lmlo = lmins & PNG_LOMASK;
  2455          lmlo = lmins & PNG_LOMASK;
  2536 
  2494 
  2537          if (sum > lmins)  /* We are already worse, don't continue. */
  2495          if (sum > lmins)  /* We are already worse, don't continue. */
  2538             break;
  2496             break;
  2539       }
  2497       }
  2540 
  2498 
  2541 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  2499 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2542       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2500       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2543       {
  2501       {
  2544          int j;
  2502          int j;
  2545          png_uint_32 sumhi, sumlo;
  2503          png_uint_32 sumhi, sumlo;
  2546          sumlo = sum & PNG_LOMASK;
  2504          sumlo = sum & PNG_LOMASK;
  2620       png_bytep rp, dp, pp, cp, lp;
  2578       png_bytep rp, dp, pp, cp, lp;
  2621       png_uint_32 sum = 0, lmins = mins;
  2579       png_uint_32 sum = 0, lmins = mins;
  2622       png_uint_32 i;
  2580       png_uint_32 i;
  2623       int v;
  2581       int v;
  2624 
  2582 
  2625 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  2583 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2626       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2584       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2627       {
  2585       {
  2628          int j;
  2586          int j;
  2629          png_uint_32 lmhi, lmlo;
  2587          png_uint_32 lmhi, lmlo;
  2630          lmlo = lmins & PNG_LOMASK;
  2588          lmlo = lmins & PNG_LOMASK;
  2701 
  2659 
  2702          if (sum > lmins)  /* We are already worse, don't continue. */
  2660          if (sum > lmins)  /* We are already worse, don't continue. */
  2703             break;
  2661             break;
  2704       }
  2662       }
  2705 
  2663 
  2706 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  2664 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2707       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2665       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
  2708       {
  2666       {
  2709          int j;
  2667          int j;
  2710          png_uint_32 sumhi, sumlo;
  2668          png_uint_32 sumhi, sumlo;
  2711          sumlo = sum & PNG_LOMASK;
  2669          sumlo = sum & PNG_LOMASK;
  2737       if (sum < mins)
  2695       if (sum < mins)
  2738       {
  2696       {
  2739          best_row = png_ptr->paeth_row;
  2697          best_row = png_ptr->paeth_row;
  2740       }
  2698       }
  2741    }
  2699    }
  2742 #endif /* PNG_NO_WRITE_FILTER */
  2700 #endif /* PNG_WRITE_FILTER_SUPPORTED */
  2743    /* Do the actual writing of the filtered row data from the chosen filter. */
  2701    /* Do the actual writing of the filtered row data from the chosen filter. */
  2744 
  2702 
  2745    png_write_filtered_row(png_ptr, best_row);
  2703    png_write_filtered_row(png_ptr, best_row);
  2746 
  2704 
  2747 #ifndef PNG_NO_WRITE_FILTER
  2705 #ifdef PNG_WRITE_FILTER_SUPPORTED
  2748 #if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
  2706 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
  2749    /* Save the type of filter we picked this time for future calculations */
  2707    /* Save the type of filter we picked this time for future calculations */
  2750    if (png_ptr->num_prev_filters > 0)
  2708    if (png_ptr->num_prev_filters > 0)
  2751    {
  2709    {
  2752       int j;
  2710       int j;
  2753       for (j = 1; j < num_p_filters; j++)
  2711       for (j = 1; j < num_p_filters; j++)
  2755          png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
  2713          png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
  2756       }
  2714       }
  2757       png_ptr->prev_filters[j] = best_row[0];
  2715       png_ptr->prev_filters[j] = best_row[0];
  2758    }
  2716    }
  2759 #endif
  2717 #endif
  2760 #endif /* PNG_NO_WRITE_FILTER */
  2718 #endif /* PNG_WRITE_FILTER_SUPPORTED */
  2761 }
  2719 }
  2762 
  2720 
  2763 
  2721 
  2764 /* Do the actual writing of a previously filtered row. */
  2722 /* Do the actual writing of a previously filtered row. */
  2765 void /* PRIVATE */
  2723 void /* PRIVATE */
  2810    }
  2768    }
  2811 
  2769 
  2812    /* Finish row - updates counters and flushes zlib if last row */
  2770    /* Finish row - updates counters and flushes zlib if last row */
  2813    png_write_finish_row(png_ptr);
  2771    png_write_finish_row(png_ptr);
  2814 
  2772 
  2815 #if defined(PNG_WRITE_FLUSH_SUPPORTED)
  2773 #ifdef PNG_WRITE_FLUSH_SUPPORTED
  2816    png_ptr->flush_rows++;
  2774    png_ptr->flush_rows++;
  2817 
  2775 
  2818    if (png_ptr->flush_dist > 0 &&
  2776    if (png_ptr->flush_dist > 0 &&
  2819        png_ptr->flush_rows >= png_ptr->flush_dist)
  2777        png_ptr->flush_rows >= png_ptr->flush_dist)
  2820    {
  2778    {