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