ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

pngwutil.c
Go to the documentation of this file.
00001 
00002 /* pngwutil.c - utilities to write a PNG file
00003  *
00004  * Last changed in libpng 1.5.6 [November 3, 2011]
00005  * Copyright (c) 1998-2011 Glenn Randers-Pehrson
00006  * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
00007  * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
00008  *
00009  * This code is released under the libpng license.
00010  * For conditions of distribution and use, see the disclaimer
00011  * and license in png.h
00012  */
00013 
00014 #include "pngpriv.h"
00015 
00016 #ifdef PNG_WRITE_SUPPORTED
00017 
00018 #ifdef PNG_WRITE_INT_FUNCTIONS_SUPPORTED
00019 /* Place a 32-bit number into a buffer in PNG byte order.  We work
00020  * with unsigned numbers for convenience, although one supported
00021  * ancillary chunk uses signed (two's complement) numbers.
00022  */
00023 void PNGAPI
00024 png_save_uint_32(png_bytep buf, png_uint_32 i)
00025 {
00026    buf[0] = (png_byte)((i >> 24) & 0xff);
00027    buf[1] = (png_byte)((i >> 16) & 0xff);
00028    buf[2] = (png_byte)((i >> 8) & 0xff);
00029    buf[3] = (png_byte)(i & 0xff);
00030 }
00031 
00032 #ifdef PNG_SAVE_INT_32_SUPPORTED
00033 /* The png_save_int_32 function assumes integers are stored in two's
00034  * complement format.  If this isn't the case, then this routine needs to
00035  * be modified to write data in two's complement format.  Note that,
00036  * the following works correctly even if png_int_32 has more than 32 bits
00037  * (compare the more complex code required on read for sign extention.)
00038  */
00039 void PNGAPI
00040 png_save_int_32(png_bytep buf, png_int_32 i)
00041 {
00042    buf[0] = (png_byte)((i >> 24) & 0xff);
00043    buf[1] = (png_byte)((i >> 16) & 0xff);
00044    buf[2] = (png_byte)((i >> 8) & 0xff);
00045    buf[3] = (png_byte)(i & 0xff);
00046 }
00047 #endif
00048 
00049 /* Place a 16-bit number into a buffer in PNG byte order.
00050  * The parameter is declared unsigned int, not png_uint_16,
00051  * just to avoid potential problems on pre-ANSI C compilers.
00052  */
00053 void PNGAPI
00054 png_save_uint_16(png_bytep buf, unsigned int i)
00055 {
00056    buf[0] = (png_byte)((i >> 8) & 0xff);
00057    buf[1] = (png_byte)(i & 0xff);
00058 }
00059 #endif
00060 
00061 /* Simple function to write the signature.  If we have already written
00062  * the magic bytes of the signature, or more likely, the PNG stream is
00063  * being embedded into another stream and doesn't need its own signature,
00064  * we should call png_set_sig_bytes() to tell libpng how many of the
00065  * bytes have already been written.
00066  */
00067 void PNGAPI
00068 png_write_sig(png_structp png_ptr)
00069 {
00070    png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
00071 
00072 #ifdef PNG_IO_STATE_SUPPORTED
00073    /* Inform the I/O callback that the signature is being written */
00074    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_SIGNATURE;
00075 #endif
00076 
00077    /* Write the rest of the 8 byte signature */
00078    png_write_data(png_ptr, &png_signature[png_ptr->sig_bytes],
00079       (png_size_t)(8 - png_ptr->sig_bytes));
00080 
00081    if (png_ptr->sig_bytes < 3)
00082       png_ptr->mode |= PNG_HAVE_PNG_SIGNATURE;
00083 }
00084 
00085 /* Write the start of a PNG chunk.  The type is the chunk type.
00086  * The total_length is the sum of the lengths of all the data you will be
00087  * passing in png_write_chunk_data().
00088  */
00089 static void
00090 png_write_chunk_header(png_structp png_ptr, png_uint_32 chunk_name,
00091     png_uint_32 length)
00092 {
00093    png_byte buf[8];
00094 
00095 #if defined(PNG_DEBUG) && (PNG_DEBUG > 0)
00096    PNG_CSTRING_FROM_CHUNK(buf, chunk_name);
00097    png_debug2(0, "Writing %s chunk, length = %lu", buf, (unsigned long)length);
00098 #endif
00099 
00100    if (png_ptr == NULL)
00101       return;
00102 
00103 #ifdef PNG_IO_STATE_SUPPORTED
00104    /* Inform the I/O callback that the chunk header is being written.
00105     * PNG_IO_CHUNK_HDR requires a single I/O call.
00106     */
00107    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_HDR;
00108 #endif
00109 
00110    /* Write the length and the chunk name */
00111    png_save_uint_32(buf, length);
00112    png_save_uint_32(buf + 4, chunk_name);
00113    png_write_data(png_ptr, buf, 8);
00114 
00115    /* Put the chunk name into png_ptr->chunk_name */
00116    png_ptr->chunk_name = chunk_name;
00117 
00118    /* Reset the crc and run it over the chunk name */
00119    png_reset_crc(png_ptr);
00120 
00121    png_calculate_crc(png_ptr, buf + 4, 4);
00122 
00123 #ifdef PNG_IO_STATE_SUPPORTED
00124    /* Inform the I/O callback that chunk data will (possibly) be written.
00125     * PNG_IO_CHUNK_DATA does NOT require a specific number of I/O calls.
00126     */
00127    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_DATA;
00128 #endif
00129 }
00130 
00131 void PNGAPI
00132 png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_string,
00133     png_uint_32 length)
00134 {
00135    png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
00136 }
00137 
00138 /* Write the data of a PNG chunk started with png_write_chunk_header().
00139  * Note that multiple calls to this function are allowed, and that the
00140  * sum of the lengths from these calls *must* add up to the total_length
00141  * given to png_write_chunk_header().
00142  */
00143 void PNGAPI
00144 png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
00145     png_size_t length)
00146 {
00147    /* Write the data, and run the CRC over it */
00148    if (png_ptr == NULL)
00149       return;
00150 
00151    if (data != NULL && length > 0)
00152    {
00153       png_write_data(png_ptr, data, length);
00154 
00155       /* Update the CRC after writing the data,
00156        * in case that the user I/O routine alters it.
00157        */
00158       png_calculate_crc(png_ptr, data, length);
00159    }
00160 }
00161 
00162 /* Finish a chunk started with png_write_chunk_header(). */
00163 void PNGAPI
00164 png_write_chunk_end(png_structp png_ptr)
00165 {
00166    png_byte buf[4];
00167 
00168    if (png_ptr == NULL) return;
00169 
00170 #ifdef PNG_IO_STATE_SUPPORTED
00171    /* Inform the I/O callback that the chunk CRC is being written.
00172     * PNG_IO_CHUNK_CRC requires a single I/O function call.
00173     */
00174    png_ptr->io_state = PNG_IO_WRITING | PNG_IO_CHUNK_CRC;
00175 #endif
00176 
00177    /* Write the crc in a single operation */
00178    png_save_uint_32(buf, png_ptr->crc);
00179 
00180    png_write_data(png_ptr, buf, (png_size_t)4);
00181 }
00182 
00183 /* Write a PNG chunk all at once.  The type is an array of ASCII characters
00184  * representing the chunk name.  The array must be at least 4 bytes in
00185  * length, and does not need to be null terminated.  To be safe, pass the
00186  * pre-defined chunk names here, and if you need a new one, define it
00187  * where the others are defined.  The length is the length of the data.
00188  * All the data must be present.  If that is not possible, use the
00189  * png_write_chunk_start(), png_write_chunk_data(), and png_write_chunk_end()
00190  * functions instead.
00191  */
00192 static void
00193 png_write_complete_chunk(png_structp png_ptr, png_uint_32 chunk_name,
00194    png_const_bytep data, png_size_t length)
00195 {
00196    if (png_ptr == NULL)
00197       return;
00198 
00199    /* On 64 bit architectures 'length' may not fit in a png_uint_32. */
00200    if (length > PNG_UINT_32_MAX)
00201       png_error(png_ptr, "length exceeds PNG maxima");
00202 
00203    png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
00204    png_write_chunk_data(png_ptr, data, length);
00205    png_write_chunk_end(png_ptr);
00206 }
00207 
00208 /* This is the API that calls the internal function above. */
00209 void PNGAPI
00210 png_write_chunk(png_structp png_ptr, png_const_bytep chunk_string,
00211    png_const_bytep data, png_size_t length)
00212 {
00213    png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
00214       length);
00215 }
00216 
00217 /* Initialize the compressor for the appropriate type of compression. */
00218 static void
00219 png_zlib_claim(png_structp png_ptr, png_uint_32 state)
00220 {
00221    if (!(png_ptr->zlib_state & PNG_ZLIB_IN_USE))
00222    {
00223       /* If already initialized for 'state' do not re-init. */
00224       if (png_ptr->zlib_state != state)
00225       {
00226          int ret = Z_OK;
00227          png_const_charp who = "-";
00228 
00229          /* If actually initialized for another state do a deflateEnd. */
00230          if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED)
00231          {
00232             ret = deflateEnd(&png_ptr->zstream);
00233             who = "end";
00234             png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
00235          }
00236 
00237          /* zlib itself detects an incomplete state on deflateEnd */
00238          if (ret == Z_OK) switch (state)
00239          {
00240 #           ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
00241                case PNG_ZLIB_FOR_TEXT:
00242                   ret = deflateInit2(&png_ptr->zstream,
00243                      png_ptr->zlib_text_level, png_ptr->zlib_text_method,
00244                      png_ptr->zlib_text_window_bits,
00245                      png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy);
00246                   who = "text";
00247                   break;
00248 #           endif
00249 
00250             case PNG_ZLIB_FOR_IDAT:
00251                ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
00252                    png_ptr->zlib_method, png_ptr->zlib_window_bits,
00253                    png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
00254                who = "IDAT";
00255                break;
00256 
00257             default:
00258                png_error(png_ptr, "invalid zlib state");
00259          }
00260 
00261          if (ret == Z_OK)
00262             png_ptr->zlib_state = state;
00263 
00264          else /* an error in deflateEnd or deflateInit2 */
00265          {
00266             size_t pos = 0;
00267             char msg[64];
00268 
00269             pos = png_safecat(msg, sizeof msg, pos,
00270                "zlib failed to initialize compressor (");
00271             pos = png_safecat(msg, sizeof msg, pos, who);
00272 
00273             switch (ret)
00274             {
00275                case Z_VERSION_ERROR:
00276                   pos = png_safecat(msg, sizeof msg, pos, ") version error");
00277                   break;
00278 
00279                case Z_STREAM_ERROR:
00280                   pos = png_safecat(msg, sizeof msg, pos, ") stream error");
00281                   break;
00282 
00283                case Z_MEM_ERROR:
00284                   pos = png_safecat(msg, sizeof msg, pos, ") memory error");
00285                   break;
00286 
00287                default:
00288                   pos = png_safecat(msg, sizeof msg, pos, ") unknown error");
00289                   break;
00290             }
00291 
00292             png_error(png_ptr, msg);
00293          }
00294       }
00295 
00296       /* Here on success, claim the zstream: */
00297       png_ptr->zlib_state |= PNG_ZLIB_IN_USE;
00298    }
00299 
00300    else
00301       png_error(png_ptr, "zstream already in use (internal error)");
00302 }
00303 
00304 /* The opposite: release the stream.  It is also reset, this API will warn on
00305  * error but will not fail.
00306  */
00307 static void
00308 png_zlib_release(png_structp png_ptr)
00309 {
00310    if (png_ptr->zlib_state & PNG_ZLIB_IN_USE)
00311    {
00312       int ret = deflateReset(&png_ptr->zstream);
00313 
00314       png_ptr->zlib_state &= ~PNG_ZLIB_IN_USE;
00315 
00316       if (ret != Z_OK)
00317       {
00318          png_const_charp err;
00319          PNG_WARNING_PARAMETERS(p)
00320 
00321          switch (ret)
00322          {
00323             case Z_VERSION_ERROR:
00324                err = "version";
00325                break;
00326 
00327             case Z_STREAM_ERROR:
00328                err = "stream";
00329                break;
00330 
00331             case Z_MEM_ERROR:
00332                err = "memory";
00333                break;
00334 
00335             default:
00336                err = "unknown";
00337                break;
00338          }
00339 
00340          png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, ret);
00341          png_warning_parameter(p, 2, err);
00342 
00343          if (png_ptr->zstream.msg)
00344             err = png_ptr->zstream.msg;
00345          else
00346             err = "[no zlib message]";
00347 
00348          png_warning_parameter(p, 3, err);
00349 
00350          png_formatted_warning(png_ptr, p,
00351             "zlib failed to reset compressor: @1(@2): @3");
00352       }
00353    }
00354 
00355    else
00356       png_warning(png_ptr, "zstream not in use (internal error)");
00357 }
00358 
00359 #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
00360 /* This pair of functions encapsulates the operation of (a) compressing a
00361  * text string, and (b) issuing it later as a series of chunk data writes.
00362  * The compression_state structure is shared context for these functions
00363  * set up by the caller in order to make the whole mess thread-safe.
00364  */
00365 
00366 typedef struct
00367 {
00368    png_const_bytep input;   /* The uncompressed input data */
00369    png_size_t input_len;    /* Its length */
00370    int num_output_ptr;      /* Number of output pointers used */
00371    int max_output_ptr;      /* Size of output_ptr */
00372    png_bytep *output_ptr;   /* Array of pointers to output */
00373 } compression_state;
00374 
00375 /* Compress given text into storage in the png_ptr structure */
00376 static int /* PRIVATE */
00377 png_text_compress(png_structp png_ptr,
00378     png_const_charp text, png_size_t text_len, int compression,
00379     compression_state *comp)
00380 {
00381    int ret;
00382 
00383    comp->num_output_ptr = 0;
00384    comp->max_output_ptr = 0;
00385    comp->output_ptr = NULL;
00386    comp->input = NULL;
00387    comp->input_len = text_len;
00388 
00389    /* We may just want to pass the text right through */
00390    if (compression == PNG_TEXT_COMPRESSION_NONE)
00391    {
00392       comp->input = (png_const_bytep)text;
00393       return((int)text_len);
00394    }
00395 
00396    if (compression >= PNG_TEXT_COMPRESSION_LAST)
00397    {
00398       PNG_WARNING_PARAMETERS(p)
00399 
00400       png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d,
00401          compression);
00402       png_formatted_warning(png_ptr, p, "Unknown compression type @1");
00403    }
00404 
00405    /* We can't write the chunk until we find out how much data we have,
00406     * which means we need to run the compressor first and save the
00407     * output.  This shouldn't be a problem, as the vast majority of
00408     * comments should be reasonable, but we will set up an array of
00409     * malloc'd pointers to be sure.
00410     *
00411     * If we knew the application was well behaved, we could simplify this
00412     * greatly by assuming we can always malloc an output buffer large
00413     * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
00414     * and malloc this directly.  The only time this would be a bad idea is
00415     * if we can't malloc more than 64K and we have 64K of random input
00416     * data, or if the input string is incredibly large (although this
00417     * wouldn't cause a failure, just a slowdown due to swapping).
00418     */
00419    png_zlib_claim(png_ptr, PNG_ZLIB_FOR_TEXT);
00420 
00421    /* Set up the compression buffers */
00422    /* TODO: the following cast hides a potential overflow problem. */
00423    png_ptr->zstream.avail_in = (uInt)text_len;
00424 
00425    /* NOTE: assume zlib doesn't overwrite the input */
00426    png_ptr->zstream.next_in = (Bytef *)text;
00427    png_ptr->zstream.avail_out = png_ptr->zbuf_size;
00428    png_ptr->zstream.next_out = png_ptr->zbuf;
00429 
00430    /* This is the same compression loop as in png_write_row() */
00431    do
00432    {
00433       /* Compress the data */
00434       ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
00435 
00436       if (ret != Z_OK)
00437       {
00438          /* Error */
00439          if (png_ptr->zstream.msg != NULL)
00440             png_error(png_ptr, png_ptr->zstream.msg);
00441 
00442          else
00443             png_error(png_ptr, "zlib error");
00444       }
00445 
00446       /* Check to see if we need more room */
00447       if (!(png_ptr->zstream.avail_out))
00448       {
00449          /* Make sure the output array has room */
00450          if (comp->num_output_ptr >= comp->max_output_ptr)
00451          {
00452             int old_max;
00453 
00454             old_max = comp->max_output_ptr;
00455             comp->max_output_ptr = comp->num_output_ptr + 4;
00456             if (comp->output_ptr != NULL)
00457             {
00458                png_bytepp old_ptr;
00459 
00460                old_ptr = comp->output_ptr;
00461 
00462                comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
00463                    (png_alloc_size_t)
00464                    (comp->max_output_ptr * png_sizeof(png_charpp)));
00465 
00466                png_memcpy(comp->output_ptr, old_ptr, old_max
00467                    * png_sizeof(png_charp));
00468 
00469                png_free(png_ptr, old_ptr);
00470             }
00471             else
00472                comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
00473                    (png_alloc_size_t)
00474                    (comp->max_output_ptr * png_sizeof(png_charp)));
00475          }
00476 
00477          /* Save the data */
00478          comp->output_ptr[comp->num_output_ptr] =
00479              (png_bytep)png_malloc(png_ptr,
00480              (png_alloc_size_t)png_ptr->zbuf_size);
00481 
00482          png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
00483              png_ptr->zbuf_size);
00484 
00485          comp->num_output_ptr++;
00486 
00487          /* and reset the buffer */
00488          png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
00489          png_ptr->zstream.next_out = png_ptr->zbuf;
00490       }
00491    /* Continue until we don't have any more to compress */
00492    } while (png_ptr->zstream.avail_in);
00493 
00494    /* Finish the compression */
00495    do
00496    {
00497       /* Tell zlib we are finished */
00498       ret = deflate(&png_ptr->zstream, Z_FINISH);
00499 
00500       if (ret == Z_OK)
00501       {
00502          /* Check to see if we need more room */
00503          if (!(png_ptr->zstream.avail_out))
00504          {
00505             /* Check to make sure our output array has room */
00506             if (comp->num_output_ptr >= comp->max_output_ptr)
00507             {
00508                int old_max;
00509 
00510                old_max = comp->max_output_ptr;
00511                comp->max_output_ptr = comp->num_output_ptr + 4;
00512                if (comp->output_ptr != NULL)
00513                {
00514                   png_bytepp old_ptr;
00515 
00516                   old_ptr = comp->output_ptr;
00517 
00518                   /* This could be optimized to realloc() */
00519                   comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
00520                       (png_alloc_size_t)(comp->max_output_ptr *
00521                       png_sizeof(png_charp)));
00522 
00523                   png_memcpy(comp->output_ptr, old_ptr,
00524                       old_max * png_sizeof(png_charp));
00525 
00526                   png_free(png_ptr, old_ptr);
00527                }
00528 
00529                else
00530                   comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
00531                       (png_alloc_size_t)(comp->max_output_ptr *
00532                       png_sizeof(png_charp)));
00533             }
00534 
00535             /* Save the data */
00536             comp->output_ptr[comp->num_output_ptr] =
00537                 (png_bytep)png_malloc(png_ptr,
00538                 (png_alloc_size_t)png_ptr->zbuf_size);
00539 
00540             png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
00541                 png_ptr->zbuf_size);
00542 
00543             comp->num_output_ptr++;
00544 
00545             /* and reset the buffer pointers */
00546             png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
00547             png_ptr->zstream.next_out = png_ptr->zbuf;
00548          }
00549       }
00550       else if (ret != Z_STREAM_END)
00551       {
00552          /* We got an error */
00553          if (png_ptr->zstream.msg != NULL)
00554             png_error(png_ptr, png_ptr->zstream.msg);
00555 
00556          else
00557             png_error(png_ptr, "zlib error");
00558       }
00559    } while (ret != Z_STREAM_END);
00560 
00561    /* Text length is number of buffers plus last buffer */
00562    text_len = png_ptr->zbuf_size * comp->num_output_ptr;
00563 
00564    if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
00565       text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
00566 
00567    return((int)text_len);
00568 }
00569 
00570 /* Ship the compressed text out via chunk writes */
00571 static void /* PRIVATE */
00572 png_write_compressed_data_out(png_structp png_ptr, compression_state *comp)
00573 {
00574    int i;
00575 
00576    /* Handle the no-compression case */
00577    if (comp->input)
00578    {
00579       png_write_chunk_data(png_ptr, comp->input, comp->input_len);
00580 
00581       return;
00582    }
00583 
00584 #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
00585    /* The zbuf_size test is because the code below doesn't work if zbuf_size is
00586     * '1'; simply skip it to avoid memory overwrite.
00587     */
00588    if (comp->input_len >= 2 && comp->input_len < 16384 && png_ptr->zbuf_size > 1)
00589    {
00590       unsigned int z_cmf;  /* zlib compression method and flags */
00591 
00592       /* Optimize the CMF field in the zlib stream.  This hack of the zlib
00593        * stream is compliant to the stream specification.
00594        */
00595 
00596       if (comp->num_output_ptr)
00597         z_cmf = comp->output_ptr[0][0];
00598       else
00599         z_cmf = png_ptr->zbuf[0];
00600 
00601       if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
00602       {
00603          unsigned int z_cinfo;
00604          unsigned int half_z_window_size;
00605          png_size_t uncompressed_text_size = comp->input_len;
00606 
00607          z_cinfo = z_cmf >> 4;
00608          half_z_window_size = 1 << (z_cinfo + 7);
00609 
00610          while (uncompressed_text_size <= half_z_window_size &&
00611              half_z_window_size >= 256)
00612          {
00613             z_cinfo--;
00614             half_z_window_size >>= 1;
00615          }
00616 
00617          z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
00618 
00619          if (comp->num_output_ptr)
00620          {
00621 
00622            if (comp->output_ptr[0][0] != z_cmf)
00623            {
00624               int tmp;
00625 
00626               comp->output_ptr[0][0] = (png_byte)z_cmf;
00627               tmp = comp->output_ptr[0][1] & 0xe0;
00628               tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
00629               comp->output_ptr[0][1] = (png_byte)tmp;
00630            }
00631          }
00632          else
00633          {
00634             int tmp;
00635 
00636             png_ptr->zbuf[0] = (png_byte)z_cmf;
00637             tmp = png_ptr->zbuf[1] & 0xe0;
00638             tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
00639             png_ptr->zbuf[1] = (png_byte)tmp;
00640          }
00641       }
00642 
00643       else
00644          png_error(png_ptr,
00645              "Invalid zlib compression method or flags in non-IDAT chunk");
00646    }
00647 #endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
00648 
00649    /* Write saved output buffers, if any */
00650    for (i = 0; i < comp->num_output_ptr; i++)
00651    {
00652       png_write_chunk_data(png_ptr, comp->output_ptr[i],
00653           (png_size_t)png_ptr->zbuf_size);
00654 
00655       png_free(png_ptr, comp->output_ptr[i]);
00656    }
00657 
00658    if (comp->max_output_ptr != 0)
00659       png_free(png_ptr, comp->output_ptr);
00660 
00661    /* Write anything left in zbuf */
00662    if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
00663       png_write_chunk_data(png_ptr, png_ptr->zbuf,
00664           (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
00665 
00666    /* Reset zlib for another zTXt/iTXt or image data */
00667    png_zlib_release(png_ptr);
00668 }
00669 #endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
00670 
00671 /* Write the IHDR chunk, and update the png_struct with the necessary
00672  * information.  Note that the rest of this code depends upon this
00673  * information being correct.
00674  */
00675 void /* PRIVATE */
00676 png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
00677     int bit_depth, int color_type, int compression_type, int filter_type,
00678     int interlace_type)
00679 {
00680    png_byte buf[13]; /* Buffer to store the IHDR info */
00681 
00682    png_debug(1, "in png_write_IHDR");
00683 
00684    /* Check that we have valid input data from the application info */
00685    switch (color_type)
00686    {
00687       case PNG_COLOR_TYPE_GRAY:
00688          switch (bit_depth)
00689          {
00690             case 1:
00691             case 2:
00692             case 4:
00693             case 8:
00694 #ifdef PNG_WRITE_16BIT_SUPPORTED
00695             case 16:
00696 #endif
00697                png_ptr->channels = 1; break;
00698 
00699             default:
00700                png_error(png_ptr,
00701                    "Invalid bit depth for grayscale image");
00702          }
00703          break;
00704 
00705       case PNG_COLOR_TYPE_RGB:
00706 #ifdef PNG_WRITE_16BIT_SUPPORTED
00707          if (bit_depth != 8 && bit_depth != 16)
00708 #else
00709          if (bit_depth != 8)
00710 #endif
00711             png_error(png_ptr, "Invalid bit depth for RGB image");
00712 
00713          png_ptr->channels = 3;
00714          break;
00715 
00716       case PNG_COLOR_TYPE_PALETTE:
00717          switch (bit_depth)
00718          {
00719             case 1:
00720             case 2:
00721             case 4:
00722             case 8:
00723                png_ptr->channels = 1;
00724                break;
00725 
00726             default:
00727                png_error(png_ptr, "Invalid bit depth for paletted image");
00728          }
00729          break;
00730 
00731       case PNG_COLOR_TYPE_GRAY_ALPHA:
00732          if (bit_depth != 8 && bit_depth != 16)
00733             png_error(png_ptr, "Invalid bit depth for grayscale+alpha image");
00734 
00735          png_ptr->channels = 2;
00736          break;
00737 
00738       case PNG_COLOR_TYPE_RGB_ALPHA:
00739 #ifdef PNG_WRITE_16BIT_SUPPORTED
00740          if (bit_depth != 8 && bit_depth != 16)
00741 #else
00742          if (bit_depth != 8)
00743 #endif
00744             png_error(png_ptr, "Invalid bit depth for RGBA image");
00745 
00746          png_ptr->channels = 4;
00747          break;
00748 
00749       default:
00750          png_error(png_ptr, "Invalid image color type specified");
00751    }
00752 
00753    if (compression_type != PNG_COMPRESSION_TYPE_BASE)
00754    {
00755       png_warning(png_ptr, "Invalid compression type specified");
00756       compression_type = PNG_COMPRESSION_TYPE_BASE;
00757    }
00758 
00759    /* Write filter_method 64 (intrapixel differencing) only if
00760     * 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
00761     * 2. Libpng did not write a PNG signature (this filter_method is only
00762     *    used in PNG datastreams that are embedded in MNG datastreams) and
00763     * 3. The application called png_permit_mng_features with a mask that
00764     *    included PNG_FLAG_MNG_FILTER_64 and
00765     * 4. The filter_method is 64 and
00766     * 5. The color_type is RGB or RGBA
00767     */
00768    if (
00769 #ifdef PNG_MNG_FEATURES_SUPPORTED
00770        !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
00771        ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
00772        (color_type == PNG_COLOR_TYPE_RGB ||
00773         color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
00774        (filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
00775 #endif
00776        filter_type != PNG_FILTER_TYPE_BASE)
00777    {
00778       png_warning(png_ptr, "Invalid filter type specified");
00779       filter_type = PNG_FILTER_TYPE_BASE;
00780    }
00781 
00782 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
00783    if (interlace_type != PNG_INTERLACE_NONE &&
00784        interlace_type != PNG_INTERLACE_ADAM7)
00785    {
00786       png_warning(png_ptr, "Invalid interlace type specified");
00787       interlace_type = PNG_INTERLACE_ADAM7;
00788    }
00789 #else
00790    interlace_type=PNG_INTERLACE_NONE;
00791 #endif
00792 
00793    /* Save the relevent information */
00794    png_ptr->bit_depth = (png_byte)bit_depth;
00795    png_ptr->color_type = (png_byte)color_type;
00796    png_ptr->interlaced = (png_byte)interlace_type;
00797 #ifdef PNG_MNG_FEATURES_SUPPORTED
00798    png_ptr->filter_type = (png_byte)filter_type;
00799 #endif
00800    png_ptr->compression_type = (png_byte)compression_type;
00801    png_ptr->width = width;
00802    png_ptr->height = height;
00803 
00804    png_ptr->pixel_depth = (png_byte)(bit_depth * png_ptr->channels);
00805    png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, width);
00806    /* Set the usr info, so any transformations can modify it */
00807    png_ptr->usr_width = png_ptr->width;
00808    png_ptr->usr_bit_depth = png_ptr->bit_depth;
00809    png_ptr->usr_channels = png_ptr->channels;
00810 
00811    /* Pack the header information into the buffer */
00812    png_save_uint_32(buf, width);
00813    png_save_uint_32(buf + 4, height);
00814    buf[8] = (png_byte)bit_depth;
00815    buf[9] = (png_byte)color_type;
00816    buf[10] = (png_byte)compression_type;
00817    buf[11] = (png_byte)filter_type;
00818    buf[12] = (png_byte)interlace_type;
00819 
00820    /* Write the chunk */
00821    png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
00822 
00823    /* Initialize zlib with PNG info */
00824    png_ptr->zstream.zalloc = png_zalloc;
00825    png_ptr->zstream.zfree = png_zfree;
00826    png_ptr->zstream.opaque = (voidpf)png_ptr;
00827 
00828    if (!(png_ptr->do_filter))
00829    {
00830       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
00831           png_ptr->bit_depth < 8)
00832          png_ptr->do_filter = PNG_FILTER_NONE;
00833 
00834       else
00835          png_ptr->do_filter = PNG_ALL_FILTERS;
00836    }
00837 
00838    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
00839    {
00840       if (png_ptr->do_filter != PNG_FILTER_NONE)
00841          png_ptr->zlib_strategy = Z_FILTERED;
00842 
00843       else
00844          png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
00845    }
00846 
00847    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
00848       png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
00849 
00850    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
00851       png_ptr->zlib_mem_level = 8;
00852 
00853    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
00854       png_ptr->zlib_window_bits = 15;
00855 
00856    if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
00857       png_ptr->zlib_method = 8;
00858 
00859 #ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
00860 #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
00861    if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY))
00862       png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
00863 
00864    if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL))
00865       png_ptr->zlib_text_level = png_ptr->zlib_level;
00866 
00867    if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL))
00868       png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
00869 
00870    if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS))
00871       png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
00872 
00873    if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD))
00874       png_ptr->zlib_text_method = png_ptr->zlib_method;
00875 #else
00876    png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
00877    png_ptr->zlib_text_level = png_ptr->zlib_level;
00878    png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
00879    png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
00880    png_ptr->zlib_text_method = png_ptr->zlib_method;
00881 #endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
00882 #endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
00883 
00884    /* Record that the compressor has not yet been initialized. */
00885    png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
00886 
00887    png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
00888 }
00889 
00890 /* Write the palette.  We are careful not to trust png_color to be in the
00891  * correct order for PNG, so people can redefine it to any convenient
00892  * structure.
00893  */
00894 void /* PRIVATE */
00895 png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
00896     png_uint_32 num_pal)
00897 {
00898    png_uint_32 i;
00899    png_const_colorp pal_ptr;
00900    png_byte buf[3];
00901 
00902    png_debug(1, "in png_write_PLTE");
00903 
00904    if ((
00905 #ifdef PNG_MNG_FEATURES_SUPPORTED
00906        !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
00907 #endif
00908        num_pal == 0) || num_pal > 256)
00909    {
00910       if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
00911       {
00912          png_error(png_ptr, "Invalid number of colors in palette");
00913       }
00914 
00915       else
00916       {
00917          png_warning(png_ptr, "Invalid number of colors in palette");
00918          return;
00919       }
00920    }
00921 
00922    if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
00923    {
00924       png_warning(png_ptr,
00925           "Ignoring request to write a PLTE chunk in grayscale PNG");
00926 
00927       return;
00928    }
00929 
00930    png_ptr->num_palette = (png_uint_16)num_pal;
00931    png_debug1(3, "num_palette = %d", png_ptr->num_palette);
00932 
00933    png_write_chunk_header(png_ptr, png_PLTE, (png_uint_32)(num_pal * 3));
00934 #ifdef PNG_POINTER_INDEXING_SUPPORTED
00935 
00936    for (i = 0, pal_ptr = palette; i < num_pal; i++, pal_ptr++)
00937    {
00938       buf[0] = pal_ptr->red;
00939       buf[1] = pal_ptr->green;
00940       buf[2] = pal_ptr->blue;
00941       png_write_chunk_data(png_ptr, buf, (png_size_t)3);
00942    }
00943 
00944 #else
00945    /* This is a little slower but some buggy compilers need to do this
00946     * instead
00947     */
00948    pal_ptr=palette;
00949 
00950    for (i = 0; i < num_pal; i++)
00951    {
00952       buf[0] = pal_ptr[i].red;
00953       buf[1] = pal_ptr[i].green;
00954       buf[2] = pal_ptr[i].blue;
00955       png_write_chunk_data(png_ptr, buf, (png_size_t)3);
00956    }
00957 
00958 #endif
00959    png_write_chunk_end(png_ptr);
00960    png_ptr->mode |= PNG_HAVE_PLTE;
00961 }
00962 
00963 /* Write an IDAT chunk */
00964 void /* PRIVATE */
00965 png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
00966 {
00967    png_debug(1, "in png_write_IDAT");
00968 
00969 #ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
00970    if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
00971        png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
00972    {
00973       /* Optimize the CMF field in the zlib stream.  This hack of the zlib
00974        * stream is compliant to the stream specification.
00975        */
00976       unsigned int z_cmf = data[0];  /* zlib compression method and flags */
00977 
00978       if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
00979       {
00980          /* Avoid memory underflows and multiplication overflows.
00981           *
00982           * The conditions below are practically always satisfied;
00983           * however, they still must be checked.
00984           */
00985          if (length >= 2 &&
00986              png_ptr->height < 16384 && png_ptr->width < 16384)
00987          {
00988             /* Compute the maximum possible length of the datastream */
00989 
00990             /* Number of pixels, plus for each row a filter byte
00991              * and possibly a padding byte, so increase the maximum
00992              * size to account for these.
00993              */
00994             unsigned int z_cinfo;
00995             unsigned int half_z_window_size;
00996             png_uint_32 uncompressed_idat_size = png_ptr->height *
00997                 ((png_ptr->width *
00998                 png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
00999 
01000             /* If it's interlaced, each block of 8 rows is sent as up to
01001              * 14 rows, i.e., 6 additional rows, each with a filter byte
01002              * and possibly a padding byte
01003              */
01004             if (png_ptr->interlaced)
01005                uncompressed_idat_size += ((png_ptr->height + 7)/8) *
01006                    (png_ptr->bit_depth < 8 ? 12 : 6);
01007 
01008             z_cinfo = z_cmf >> 4;
01009             half_z_window_size = 1 << (z_cinfo + 7);
01010 
01011             while (uncompressed_idat_size <= half_z_window_size &&
01012                 half_z_window_size >= 256)
01013             {
01014                z_cinfo--;
01015                half_z_window_size >>= 1;
01016             }
01017 
01018             z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
01019 
01020             if (data[0] != z_cmf)
01021             {
01022                int tmp;
01023                data[0] = (png_byte)z_cmf;
01024                tmp = data[1] & 0xe0;
01025                tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
01026                data[1] = (png_byte)tmp;
01027             }
01028          }
01029       }
01030 
01031       else
01032          png_error(png_ptr,
01033              "Invalid zlib compression method or flags in IDAT");
01034    }
01035 #endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
01036 
01037    png_write_complete_chunk(png_ptr, png_IDAT, data, length);
01038    png_ptr->mode |= PNG_HAVE_IDAT;
01039 
01040    /* Prior to 1.5.4 this code was replicated in every caller (except at the
01041     * end, where it isn't technically necessary).  Since this function has
01042     * flushed the data we can safely reset the zlib output buffer here.
01043     */
01044    png_ptr->zstream.next_out = png_ptr->zbuf;
01045    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
01046 }
01047 
01048 /* Write an IEND chunk */
01049 void /* PRIVATE */
01050 png_write_IEND(png_structp png_ptr)
01051 {
01052    png_debug(1, "in png_write_IEND");
01053 
01054    png_write_complete_chunk(png_ptr, png_IEND, NULL, (png_size_t)0);
01055    png_ptr->mode |= PNG_HAVE_IEND;
01056 }
01057 
01058 #ifdef PNG_WRITE_gAMA_SUPPORTED
01059 /* Write a gAMA chunk */
01060 void /* PRIVATE */
01061 png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
01062 {
01063    png_byte buf[4];
01064 
01065    png_debug(1, "in png_write_gAMA");
01066 
01067    /* file_gamma is saved in 1/100,000ths */
01068    png_save_uint_32(buf, (png_uint_32)file_gamma);
01069    png_write_complete_chunk(png_ptr, png_gAMA, buf, (png_size_t)4);
01070 }
01071 #endif
01072 
01073 #ifdef PNG_WRITE_sRGB_SUPPORTED
01074 /* Write a sRGB chunk */
01075 void /* PRIVATE */
01076 png_write_sRGB(png_structp png_ptr, int srgb_intent)
01077 {
01078    png_byte buf[1];
01079 
01080    png_debug(1, "in png_write_sRGB");
01081 
01082    if (srgb_intent >= PNG_sRGB_INTENT_LAST)
01083       png_warning(png_ptr,
01084           "Invalid sRGB rendering intent specified");
01085 
01086    buf[0]=(png_byte)srgb_intent;
01087    png_write_complete_chunk(png_ptr, png_sRGB, buf, (png_size_t)1);
01088 }
01089 #endif
01090 
01091 #ifdef PNG_WRITE_iCCP_SUPPORTED
01092 /* Write an iCCP chunk */
01093 void /* PRIVATE */
01094 png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
01095     png_const_charp profile, int profile_len)
01096 {
01097    png_size_t name_len;
01098    png_charp new_name;
01099    compression_state comp;
01100    int embedded_profile_len = 0;
01101 
01102    png_debug(1, "in png_write_iCCP");
01103 
01104    comp.num_output_ptr = 0;
01105    comp.max_output_ptr = 0;
01106    comp.output_ptr = NULL;
01107    comp.input = NULL;
01108    comp.input_len = 0;
01109 
01110    if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0)
01111       return;
01112 
01113    if (compression_type != PNG_COMPRESSION_TYPE_BASE)
01114       png_warning(png_ptr, "Unknown compression type in iCCP chunk");
01115 
01116    if (profile == NULL)
01117       profile_len = 0;
01118 
01119    if (profile_len > 3)
01120       embedded_profile_len =
01121           ((*( (png_const_bytep)profile    ))<<24) |
01122           ((*( (png_const_bytep)profile + 1))<<16) |
01123           ((*( (png_const_bytep)profile + 2))<< 8) |
01124           ((*( (png_const_bytep)profile + 3))    );
01125 
01126    if (embedded_profile_len < 0)
01127    {
01128       png_warning(png_ptr,
01129           "Embedded profile length in iCCP chunk is negative");
01130 
01131       png_free(png_ptr, new_name);
01132       return;
01133    }
01134 
01135    if (profile_len < embedded_profile_len)
01136    {
01137       png_warning(png_ptr,
01138           "Embedded profile length too large in iCCP chunk");
01139 
01140       png_free(png_ptr, new_name);
01141       return;
01142    }
01143 
01144    if (profile_len > embedded_profile_len)
01145    {
01146       png_warning(png_ptr,
01147           "Truncating profile to actual length in iCCP chunk");
01148 
01149       profile_len = embedded_profile_len;
01150    }
01151 
01152    if (profile_len)
01153       profile_len = png_text_compress(png_ptr, profile,
01154           (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp);
01155 
01156    /* Make sure we include the NULL after the name and the compression type */
01157    png_write_chunk_header(png_ptr, png_iCCP,
01158        (png_uint_32)(name_len + profile_len + 2));
01159 
01160    new_name[name_len + 1] = 0x00;
01161 
01162    png_write_chunk_data(png_ptr, (png_bytep)new_name,
01163        (png_size_t)(name_len + 2));
01164 
01165    if (profile_len)
01166    {
01167       comp.input_len = profile_len;
01168       png_write_compressed_data_out(png_ptr, &comp);
01169    }
01170 
01171    png_write_chunk_end(png_ptr);
01172    png_free(png_ptr, new_name);
01173 }
01174 #endif
01175 
01176 #ifdef PNG_WRITE_sPLT_SUPPORTED
01177 /* Write a sPLT chunk */
01178 void /* PRIVATE */
01179 png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
01180 {
01181    png_size_t name_len;
01182    png_charp new_name;
01183    png_byte entrybuf[10];
01184    png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
01185    png_size_t palette_size = entry_size * spalette->nentries;
01186    png_sPLT_entryp ep;
01187 #ifndef PNG_POINTER_INDEXING_SUPPORTED
01188    int i;
01189 #endif
01190 
01191    png_debug(1, "in png_write_sPLT");
01192 
01193    if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0)
01194       return;
01195 
01196    /* Make sure we include the NULL after the name */
01197    png_write_chunk_header(png_ptr, png_sPLT,
01198        (png_uint_32)(name_len + 2 + palette_size));
01199 
01200    png_write_chunk_data(png_ptr, (png_bytep)new_name,
01201        (png_size_t)(name_len + 1));
01202 
01203    png_write_chunk_data(png_ptr, &spalette->depth, (png_size_t)1);
01204 
01205    /* Loop through each palette entry, writing appropriately */
01206 #ifdef PNG_POINTER_INDEXING_SUPPORTED
01207    for (ep = spalette->entries; ep<spalette->entries + spalette->nentries; ep++)
01208    {
01209       if (spalette->depth == 8)
01210       {
01211          entrybuf[0] = (png_byte)ep->red;
01212          entrybuf[1] = (png_byte)ep->green;
01213          entrybuf[2] = (png_byte)ep->blue;
01214          entrybuf[3] = (png_byte)ep->alpha;
01215          png_save_uint_16(entrybuf + 4, ep->frequency);
01216       }
01217 
01218       else
01219       {
01220          png_save_uint_16(entrybuf + 0, ep->red);
01221          png_save_uint_16(entrybuf + 2, ep->green);
01222          png_save_uint_16(entrybuf + 4, ep->blue);
01223          png_save_uint_16(entrybuf + 6, ep->alpha);
01224          png_save_uint_16(entrybuf + 8, ep->frequency);
01225       }
01226 
01227       png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
01228    }
01229 #else
01230    ep=spalette->entries;
01231    for (i = 0; i>spalette->nentries; i++)
01232    {
01233       if (spalette->depth == 8)
01234       {
01235          entrybuf[0] = (png_byte)ep[i].red;
01236          entrybuf[1] = (png_byte)ep[i].green;
01237          entrybuf[2] = (png_byte)ep[i].blue;
01238          entrybuf[3] = (png_byte)ep[i].alpha;
01239          png_save_uint_16(entrybuf + 4, ep[i].frequency);
01240       }
01241 
01242       else
01243       {
01244          png_save_uint_16(entrybuf + 0, ep[i].red);
01245          png_save_uint_16(entrybuf + 2, ep[i].green);
01246          png_save_uint_16(entrybuf + 4, ep[i].blue);
01247          png_save_uint_16(entrybuf + 6, ep[i].alpha);
01248          png_save_uint_16(entrybuf + 8, ep[i].frequency);
01249       }
01250 
01251       png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
01252    }
01253 #endif
01254 
01255    png_write_chunk_end(png_ptr);
01256    png_free(png_ptr, new_name);
01257 }
01258 #endif
01259 
01260 #ifdef PNG_WRITE_sBIT_SUPPORTED
01261 /* Write the sBIT chunk */
01262 void /* PRIVATE */
01263 png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
01264 {
01265    png_byte buf[4];
01266    png_size_t size;
01267 
01268    png_debug(1, "in png_write_sBIT");
01269 
01270    /* Make sure we don't depend upon the order of PNG_COLOR_8 */
01271    if (color_type & PNG_COLOR_MASK_COLOR)
01272    {
01273       png_byte maxbits;
01274 
01275       maxbits = (png_byte)(color_type==PNG_COLOR_TYPE_PALETTE ? 8 :
01276           png_ptr->usr_bit_depth);
01277 
01278       if (sbit->red == 0 || sbit->red > maxbits ||
01279           sbit->green == 0 || sbit->green > maxbits ||
01280           sbit->blue == 0 || sbit->blue > maxbits)
01281       {
01282          png_warning(png_ptr, "Invalid sBIT depth specified");
01283          return;
01284       }
01285 
01286       buf[0] = sbit->red;
01287       buf[1] = sbit->green;
01288       buf[2] = sbit->blue;
01289       size = 3;
01290    }
01291 
01292    else
01293    {
01294       if (sbit->gray == 0 || sbit->gray > png_ptr->usr_bit_depth)
01295       {
01296          png_warning(png_ptr, "Invalid sBIT depth specified");
01297          return;
01298       }
01299 
01300       buf[0] = sbit->gray;
01301       size = 1;
01302    }
01303 
01304    if (color_type & PNG_COLOR_MASK_ALPHA)
01305    {
01306       if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
01307       {
01308          png_warning(png_ptr, "Invalid sBIT depth specified");
01309          return;
01310       }
01311 
01312       buf[size++] = sbit->alpha;
01313    }
01314 
01315    png_write_complete_chunk(png_ptr, png_sBIT, buf, size);
01316 }
01317 #endif
01318 
01319 #ifdef PNG_WRITE_cHRM_SUPPORTED
01320 /* Write the cHRM chunk */
01321 void /* PRIVATE */
01322 png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
01323     png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
01324     png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
01325     png_fixed_point blue_y)
01326 {
01327    png_byte buf[32];
01328 
01329    png_debug(1, "in png_write_cHRM");
01330 
01331    /* Each value is saved in 1/100,000ths */
01332 #ifdef PNG_CHECK_cHRM_SUPPORTED
01333    if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
01334        green_x, green_y, blue_x, blue_y))
01335 #endif
01336    {
01337       png_save_uint_32(buf, (png_uint_32)white_x);
01338       png_save_uint_32(buf + 4, (png_uint_32)white_y);
01339 
01340       png_save_uint_32(buf + 8, (png_uint_32)red_x);
01341       png_save_uint_32(buf + 12, (png_uint_32)red_y);
01342 
01343       png_save_uint_32(buf + 16, (png_uint_32)green_x);
01344       png_save_uint_32(buf + 20, (png_uint_32)green_y);
01345 
01346       png_save_uint_32(buf + 24, (png_uint_32)blue_x);
01347       png_save_uint_32(buf + 28, (png_uint_32)blue_y);
01348 
01349       png_write_complete_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
01350    }
01351 }
01352 #endif
01353 
01354 #ifdef PNG_WRITE_tRNS_SUPPORTED
01355 /* Write the tRNS chunk */
01356 void /* PRIVATE */
01357 png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
01358     png_const_color_16p tran, int num_trans, int color_type)
01359 {
01360    png_byte buf[6];
01361 
01362    png_debug(1, "in png_write_tRNS");
01363 
01364    if (color_type == PNG_COLOR_TYPE_PALETTE)
01365    {
01366       if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
01367       {
01368          png_warning(png_ptr, "Invalid number of transparent colors specified");
01369          return;
01370       }
01371 
01372       /* Write the chunk out as it is */
01373       png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans);
01374    }
01375 
01376    else if (color_type == PNG_COLOR_TYPE_GRAY)
01377    {
01378       /* One 16 bit value */
01379       if (tran->gray >= (1 << png_ptr->bit_depth))
01380       {
01381          png_warning(png_ptr,
01382              "Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
01383 
01384          return;
01385       }
01386 
01387       png_save_uint_16(buf, tran->gray);
01388       png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)2);
01389    }
01390 
01391    else if (color_type == PNG_COLOR_TYPE_RGB)
01392    {
01393       /* Three 16 bit values */
01394       png_save_uint_16(buf, tran->red);
01395       png_save_uint_16(buf + 2, tran->green);
01396       png_save_uint_16(buf + 4, tran->blue);
01397 #ifdef PNG_WRITE_16BIT_SUPPORTED
01398       if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
01399 #else
01400       if (buf[0] | buf[2] | buf[4])
01401 #endif
01402       {
01403          png_warning(png_ptr,
01404            "Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
01405          return;
01406       }
01407 
01408       png_write_complete_chunk(png_ptr, png_tRNS, buf, (png_size_t)6);
01409    }
01410 
01411    else
01412    {
01413       png_warning(png_ptr, "Can't write tRNS with an alpha channel");
01414    }
01415 }
01416 #endif
01417 
01418 #ifdef PNG_WRITE_bKGD_SUPPORTED
01419 /* Write the background chunk */
01420 void /* PRIVATE */
01421 png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
01422 {
01423    png_byte buf[6];
01424 
01425    png_debug(1, "in png_write_bKGD");
01426 
01427    if (color_type == PNG_COLOR_TYPE_PALETTE)
01428    {
01429       if (
01430 #ifdef PNG_MNG_FEATURES_SUPPORTED
01431           (png_ptr->num_palette ||
01432           (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
01433 #endif
01434          back->index >= png_ptr->num_palette)
01435       {
01436          png_warning(png_ptr, "Invalid background palette index");
01437          return;
01438       }
01439 
01440       buf[0] = back->index;
01441       png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
01442    }
01443 
01444    else if (color_type & PNG_COLOR_MASK_COLOR)
01445    {
01446       png_save_uint_16(buf, back->red);
01447       png_save_uint_16(buf + 2, back->green);
01448       png_save_uint_16(buf + 4, back->blue);
01449 #ifdef PNG_WRITE_16BIT_SUPPORTED
01450       if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
01451 #else
01452       if (buf[0] | buf[2] | buf[4])
01453 #endif
01454       {
01455          png_warning(png_ptr,
01456              "Ignoring attempt to write 16-bit bKGD chunk when bit_depth is 8");
01457 
01458          return;
01459       }
01460 
01461       png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)6);
01462    }
01463 
01464    else
01465    {
01466       if (back->gray >= (1 << png_ptr->bit_depth))
01467       {
01468          png_warning(png_ptr,
01469              "Ignoring attempt to write bKGD chunk out-of-range for bit_depth");
01470 
01471          return;
01472       }
01473 
01474       png_save_uint_16(buf, back->gray);
01475       png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)2);
01476    }
01477 }
01478 #endif
01479 
01480 #ifdef PNG_WRITE_hIST_SUPPORTED
01481 /* Write the histogram */
01482 void /* PRIVATE */
01483 png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist)
01484 {
01485    int i;
01486    png_byte buf[3];
01487 
01488    png_debug(1, "in png_write_hIST");
01489 
01490    if (num_hist > (int)png_ptr->num_palette)
01491    {
01492       png_debug2(3, "num_hist = %d, num_palette = %d", num_hist,
01493           png_ptr->num_palette);
01494 
01495       png_warning(png_ptr, "Invalid number of histogram entries specified");
01496       return;
01497    }
01498 
01499    png_write_chunk_header(png_ptr, png_hIST, (png_uint_32)(num_hist * 2));
01500 
01501    for (i = 0; i < num_hist; i++)
01502    {
01503       png_save_uint_16(buf, hist[i]);
01504       png_write_chunk_data(png_ptr, buf, (png_size_t)2);
01505    }
01506 
01507    png_write_chunk_end(png_ptr);
01508 }
01509 #endif
01510 
01511 #if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
01512     defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
01513 /* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
01514  * and if invalid, correct the keyword rather than discarding the entire
01515  * chunk.  The PNG 1.0 specification requires keywords 1-79 characters in
01516  * length, forbids leading or trailing whitespace, multiple internal spaces,
01517  * and the non-break space (0x80) from ISO 8859-1.  Returns keyword length.
01518  *
01519  * The new_key is allocated to hold the corrected keyword and must be freed
01520  * by the calling routine.  This avoids problems with trying to write to
01521  * static keywords without having to have duplicate copies of the strings.
01522  */
01523 png_size_t /* PRIVATE */
01524 png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key)
01525 {
01526    png_size_t key_len;
01527    png_const_charp ikp;
01528    png_charp kp, dp;
01529    int kflag;
01530    int kwarn=0;
01531 
01532    png_debug(1, "in png_check_keyword");
01533 
01534    *new_key = NULL;
01535 
01536    if (key == NULL || (key_len = png_strlen(key)) == 0)
01537    {
01538       png_warning(png_ptr, "zero length keyword");
01539       return ((png_size_t)0);
01540    }
01541 
01542    png_debug1(2, "Keyword to be checked is '%s'", key);
01543 
01544    *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
01545 
01546    if (*new_key == NULL)
01547    {
01548       png_warning(png_ptr, "Out of memory while procesing keyword");
01549       return ((png_size_t)0);
01550    }
01551 
01552    /* Replace non-printing characters with a blank and print a warning */
01553    for (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++)
01554    {
01555       if ((png_byte)*ikp < 0x20 ||
01556          ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1))
01557       {
01558          PNG_WARNING_PARAMETERS(p)
01559 
01560          png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x,
01561             (png_byte)*ikp);
01562          png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1");
01563          *dp = ' ';
01564       }
01565 
01566       else
01567       {
01568          *dp = *ikp;
01569       }
01570    }
01571    *dp = '\0';
01572 
01573    /* Remove any trailing white space. */
01574    kp = *new_key + key_len - 1;
01575    if (*kp == ' ')
01576    {
01577       png_warning(png_ptr, "trailing spaces removed from keyword");
01578 
01579       while (*kp == ' ')
01580       {
01581          *(kp--) = '\0';
01582          key_len--;
01583       }
01584    }
01585 
01586    /* Remove any leading white space. */
01587    kp = *new_key;
01588    if (*kp == ' ')
01589    {
01590       png_warning(png_ptr, "leading spaces removed from keyword");
01591 
01592       while (*kp == ' ')
01593       {
01594          kp++;
01595          key_len--;
01596       }
01597    }
01598 
01599    png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
01600 
01601    /* Remove multiple internal spaces. */
01602    for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
01603    {
01604       if (*kp == ' ' && kflag == 0)
01605       {
01606          *(dp++) = *kp;
01607          kflag = 1;
01608       }
01609 
01610       else if (*kp == ' ')
01611       {
01612          key_len--;
01613          kwarn = 1;
01614       }
01615 
01616       else
01617       {
01618          *(dp++) = *kp;
01619          kflag = 0;
01620       }
01621    }
01622    *dp = '\0';
01623    if (kwarn)
01624       png_warning(png_ptr, "extra interior spaces removed from keyword");
01625 
01626    if (key_len == 0)
01627    {
01628       png_free(png_ptr, *new_key);
01629       png_warning(png_ptr, "Zero length keyword");
01630    }
01631 
01632    if (key_len > 79)
01633    {
01634       png_warning(png_ptr, "keyword length must be 1 - 79 characters");
01635       (*new_key)[79] = '\0';
01636       key_len = 79;
01637    }
01638 
01639    return (key_len);
01640 }
01641 #endif
01642 
01643 #ifdef PNG_WRITE_tEXt_SUPPORTED
01644 /* Write a tEXt chunk */
01645 void /* PRIVATE */
01646 png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
01647     png_size_t text_len)
01648 {
01649    png_size_t key_len;
01650    png_charp new_key;
01651 
01652    png_debug(1, "in png_write_tEXt");
01653 
01654    if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
01655       return;
01656 
01657    if (text == NULL || *text == '\0')
01658       text_len = 0;
01659 
01660    else
01661       text_len = png_strlen(text);
01662 
01663    /* Make sure we include the 0 after the key */
01664    png_write_chunk_header(png_ptr, png_tEXt,
01665        (png_uint_32)(key_len + text_len + 1));
01666    /*
01667     * We leave it to the application to meet PNG-1.0 requirements on the
01668     * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
01669     * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
01670     * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
01671     */
01672    png_write_chunk_data(png_ptr, (png_bytep)new_key,
01673        (png_size_t)(key_len + 1));
01674 
01675    if (text_len)
01676       png_write_chunk_data(png_ptr, (png_const_bytep)text,
01677           (png_size_t)text_len);
01678 
01679    png_write_chunk_end(png_ptr);
01680    png_free(png_ptr, new_key);
01681 }
01682 #endif
01683 
01684 #ifdef PNG_WRITE_zTXt_SUPPORTED
01685 /* Write a compressed text chunk */
01686 void /* PRIVATE */
01687 png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
01688     png_size_t text_len, int compression)
01689 {
01690    png_size_t key_len;
01691    png_byte buf;
01692    png_charp new_key;
01693    compression_state comp;
01694 
01695    png_debug(1, "in png_write_zTXt");
01696 
01697    comp.num_output_ptr = 0;
01698    comp.max_output_ptr = 0;
01699    comp.output_ptr = NULL;
01700    comp.input = NULL;
01701    comp.input_len = 0;
01702 
01703    if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
01704    {
01705       png_free(png_ptr, new_key);
01706       return;
01707    }
01708 
01709    if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
01710    {
01711       png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
01712       png_free(png_ptr, new_key);
01713       return;
01714    }
01715 
01716    text_len = png_strlen(text);
01717 
01718    /* Compute the compressed data; do it now for the length */
01719    text_len = png_text_compress(png_ptr, text, text_len, compression,
01720        &comp);
01721 
01722    /* Write start of chunk */
01723    png_write_chunk_header(png_ptr, png_zTXt,
01724        (png_uint_32)(key_len+text_len + 2));
01725 
01726    /* Write key */
01727    png_write_chunk_data(png_ptr, (png_bytep)new_key,
01728        (png_size_t)(key_len + 1));
01729 
01730    png_free(png_ptr, new_key);
01731 
01732    buf = (png_byte)compression;
01733 
01734    /* Write compression */
01735    png_write_chunk_data(png_ptr, &buf, (png_size_t)1);
01736 
01737    /* Write the compressed data */
01738    comp.input_len = text_len;
01739    png_write_compressed_data_out(png_ptr, &comp);
01740 
01741    /* Close the chunk */
01742    png_write_chunk_end(png_ptr);
01743 }
01744 #endif
01745 
01746 #ifdef PNG_WRITE_iTXt_SUPPORTED
01747 /* Write an iTXt chunk */
01748 void /* PRIVATE */
01749 png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key,
01750     png_const_charp lang, png_const_charp lang_key, png_const_charp text)
01751 {
01752    png_size_t lang_len, key_len, lang_key_len, text_len;
01753    png_charp new_lang;
01754    png_charp new_key = NULL;
01755    png_byte cbuf[2];
01756    compression_state comp;
01757 
01758    png_debug(1, "in png_write_iTXt");
01759 
01760    comp.num_output_ptr = 0;
01761    comp.max_output_ptr = 0;
01762    comp.output_ptr = NULL;
01763    comp.input = NULL;
01764 
01765    if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
01766       return;
01767 
01768    if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0)
01769    {
01770       png_warning(png_ptr, "Empty language field in iTXt chunk");
01771       new_lang = NULL;
01772       lang_len = 0;
01773    }
01774 
01775    if (lang_key == NULL)
01776       lang_key_len = 0;
01777 
01778    else
01779       lang_key_len = png_strlen(lang_key);
01780 
01781    if (text == NULL)
01782       text_len = 0;
01783 
01784    else
01785       text_len = png_strlen(text);
01786 
01787    /* Compute the compressed data; do it now for the length */
01788    text_len = png_text_compress(png_ptr, text, text_len, compression - 2,
01789        &comp);
01790 
01791 
01792    /* Make sure we include the compression flag, the compression byte,
01793     * and the NULs after the key, lang, and lang_key parts
01794     */
01795 
01796    png_write_chunk_header(png_ptr, png_iTXt, (png_uint_32)(
01797         5 /* comp byte, comp flag, terminators for key, lang and lang_key */
01798         + key_len
01799         + lang_len
01800         + lang_key_len
01801         + text_len));
01802 
01803    /* We leave it to the application to meet PNG-1.0 requirements on the
01804     * contents of the text.  PNG-1.0 through PNG-1.2 discourage the use of
01805     * any non-Latin-1 characters except for NEWLINE.  ISO PNG will forbid them.
01806     * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
01807     */
01808    png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1));
01809 
01810    /* Set the compression flag */
01811    if (compression == PNG_ITXT_COMPRESSION_NONE ||
01812        compression == PNG_TEXT_COMPRESSION_NONE)
01813       cbuf[0] = 0;
01814 
01815    else /* compression == PNG_ITXT_COMPRESSION_zTXt */
01816       cbuf[0] = 1;
01817 
01818    /* Set the compression method */
01819    cbuf[1] = 0;
01820 
01821    png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
01822 
01823    cbuf[0] = 0;
01824    png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf),
01825        (png_size_t)(lang_len + 1));
01826 
01827    png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf),
01828        (png_size_t)(lang_key_len + 1));
01829 
01830    png_write_compressed_data_out(png_ptr, &comp);
01831 
01832    png_write_chunk_end(png_ptr);
01833 
01834    png_free(png_ptr, new_key);
01835    png_free(png_ptr, new_lang);
01836 }
01837 #endif
01838 
01839 #ifdef PNG_WRITE_oFFs_SUPPORTED
01840 /* Write the oFFs chunk */
01841 void /* PRIVATE */
01842 png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
01843     int unit_type)
01844 {
01845    png_byte buf[9];
01846 
01847    png_debug(1, "in png_write_oFFs");
01848 
01849    if (unit_type >= PNG_OFFSET_LAST)
01850       png_warning(png_ptr, "Unrecognized unit type for oFFs chunk");
01851 
01852    png_save_int_32(buf, x_offset);
01853    png_save_int_32(buf + 4, y_offset);
01854    buf[8] = (png_byte)unit_type;
01855 
01856    png_write_complete_chunk(png_ptr, png_oFFs, buf, (png_size_t)9);
01857 }
01858 #endif
01859 #ifdef PNG_WRITE_pCAL_SUPPORTED
01860 /* Write the pCAL chunk (described in the PNG extensions document) */
01861 void /* PRIVATE */
01862 png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
01863     png_int_32 X1, int type, int nparams, png_const_charp units,
01864     png_charpp params)
01865 {
01866    png_size_t purpose_len, units_len, total_len;
01867    png_size_tp params_len;
01868    png_byte buf[10];
01869    png_charp new_purpose;
01870    int i;
01871 
01872    png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
01873 
01874    if (type >= PNG_EQUATION_LAST)
01875       png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
01876 
01877    purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
01878    png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
01879    units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
01880    png_debug1(3, "pCAL units length = %d", (int)units_len);
01881    total_len = purpose_len + units_len + 10;
01882 
01883    params_len = (png_size_tp)png_malloc(png_ptr,
01884        (png_alloc_size_t)(nparams * png_sizeof(png_size_t)));
01885 
01886    /* Find the length of each parameter, making sure we don't count the
01887     * null terminator for the last parameter.
01888     */
01889    for (i = 0; i < nparams; i++)
01890    {
01891       params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
01892       png_debug2(3, "pCAL parameter %d length = %lu", i,
01893           (unsigned long)params_len[i]);
01894       total_len += params_len[i];
01895    }
01896 
01897    png_debug1(3, "pCAL total length = %d", (int)total_len);
01898    png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
01899    png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, purpose_len);
01900    png_save_int_32(buf, X0);
01901    png_save_int_32(buf + 4, X1);
01902    buf[8] = (png_byte)type;
01903    buf[9] = (png_byte)nparams;
01904    png_write_chunk_data(png_ptr, buf, (png_size_t)10);
01905    png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len);
01906 
01907    png_free(png_ptr, new_purpose);
01908 
01909    for (i = 0; i < nparams; i++)
01910    {
01911       png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
01912    }
01913 
01914    png_free(png_ptr, params_len);
01915    png_write_chunk_end(png_ptr);
01916 }
01917 #endif
01918 
01919 #ifdef PNG_WRITE_sCAL_SUPPORTED
01920 /* Write the sCAL chunk */
01921 void /* PRIVATE */
01922 png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
01923     png_const_charp height)
01924 {
01925    png_byte buf[64];
01926    png_size_t wlen, hlen, total_len;
01927 
01928    png_debug(1, "in png_write_sCAL_s");
01929 
01930    wlen = png_strlen(width);
01931    hlen = png_strlen(height);
01932    total_len = wlen + hlen + 2;
01933 
01934    if (total_len > 64)
01935    {
01936       png_warning(png_ptr, "Can't write sCAL (buffer too small)");
01937       return;
01938    }
01939 
01940    buf[0] = (png_byte)unit;
01941    png_memcpy(buf + 1, width, wlen + 1);      /* Append the '\0' here */
01942    png_memcpy(buf + wlen + 2, height, hlen);  /* Do NOT append the '\0' here */
01943 
01944    png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
01945    png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
01946 }
01947 #endif
01948 
01949 #ifdef PNG_WRITE_pHYs_SUPPORTED
01950 /* Write the pHYs chunk */
01951 void /* PRIVATE */
01952 png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
01953     png_uint_32 y_pixels_per_unit,
01954     int unit_type)
01955 {
01956    png_byte buf[9];
01957 
01958    png_debug(1, "in png_write_pHYs");
01959 
01960    if (unit_type >= PNG_RESOLUTION_LAST)
01961       png_warning(png_ptr, "Unrecognized unit type for pHYs chunk");
01962 
01963    png_save_uint_32(buf, x_pixels_per_unit);
01964    png_save_uint_32(buf + 4, y_pixels_per_unit);
01965    buf[8] = (png_byte)unit_type;
01966 
01967    png_write_complete_chunk(png_ptr, png_pHYs, buf, (png_size_t)9);
01968 }
01969 #endif
01970 
01971 #ifdef PNG_WRITE_tIME_SUPPORTED
01972 /* Write the tIME chunk.  Use either png_convert_from_struct_tm()
01973  * or png_convert_from_time_t(), or fill in the structure yourself.
01974  */
01975 void /* PRIVATE */
01976 png_write_tIME(png_structp png_ptr, png_const_timep mod_time)
01977 {
01978    png_byte buf[7];
01979 
01980    png_debug(1, "in png_write_tIME");
01981 
01982    if (mod_time->month  > 12 || mod_time->month  < 1 ||
01983        mod_time->day    > 31 || mod_time->day    < 1 ||
01984        mod_time->hour   > 23 || mod_time->second > 60)
01985    {
01986       png_warning(png_ptr, "Invalid time specified for tIME chunk");
01987       return;
01988    }
01989 
01990    png_save_uint_16(buf, mod_time->year);
01991    buf[2] = mod_time->month;
01992    buf[3] = mod_time->day;
01993    buf[4] = mod_time->hour;
01994    buf[5] = mod_time->minute;
01995    buf[6] = mod_time->second;
01996 
01997    png_write_complete_chunk(png_ptr, png_tIME, buf, (png_size_t)7);
01998 }
01999 #endif
02000 
02001 /* Initializes the row writing capability of libpng */
02002 void /* PRIVATE */
02003 png_write_start_row(png_structp png_ptr)
02004 {
02005 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
02006    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
02007 
02008    /* Start of interlace block */
02009    static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
02010 
02011    /* Offset to next interlace block */
02012    static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
02013 
02014    /* Start of interlace block in the y direction */
02015    static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
02016 
02017    /* Offset to next interlace block in the y direction */
02018    static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
02019 #endif
02020 
02021    png_alloc_size_t buf_size;
02022    int usr_pixel_depth;
02023 
02024    png_debug(1, "in png_write_start_row");
02025 
02026    usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth;
02027    buf_size = PNG_ROWBYTES(usr_pixel_depth, png_ptr->width) + 1;
02028 
02029    /* 1.5.6: added to allow checking in the row write code. */
02030    png_ptr->transformed_pixel_depth = png_ptr->pixel_depth;
02031    png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth;
02032 
02033    /* Set up row buffer */
02034    png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size);
02035 
02036    png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE;
02037 
02038 #ifdef PNG_WRITE_FILTER_SUPPORTED
02039    /* Set up filtering buffer, if using this filter */
02040    if (png_ptr->do_filter & PNG_FILTER_SUB)
02041    {
02042       png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1);
02043 
02044       png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
02045    }
02046 
02047    /* We only need to keep the previous row if we are using one of these. */
02048    if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
02049    {
02050       /* Set up previous row buffer */
02051       png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size);
02052 
02053       if (png_ptr->do_filter & PNG_FILTER_UP)
02054       {
02055          png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
02056             png_ptr->rowbytes + 1);
02057 
02058          png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
02059       }
02060 
02061       if (png_ptr->do_filter & PNG_FILTER_AVG)
02062       {
02063          png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
02064              png_ptr->rowbytes + 1);
02065 
02066          png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
02067       }
02068 
02069       if (png_ptr->do_filter & PNG_FILTER_PAETH)
02070       {
02071          png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
02072              png_ptr->rowbytes + 1);
02073 
02074          png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
02075       }
02076    }
02077 #endif /* PNG_WRITE_FILTER_SUPPORTED */
02078 
02079 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
02080    /* If interlaced, we need to set up width and height of pass */
02081    if (png_ptr->interlaced)
02082    {
02083       if (!(png_ptr->transformations & PNG_INTERLACE))
02084       {
02085          png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
02086              png_pass_ystart[0]) / png_pass_yinc[0];
02087 
02088          png_ptr->usr_width = (png_ptr->width + png_pass_inc[0] - 1 -
02089              png_pass_start[0]) / png_pass_inc[0];
02090       }
02091 
02092       else
02093       {
02094          png_ptr->num_rows = png_ptr->height;
02095          png_ptr->usr_width = png_ptr->width;
02096       }
02097    }
02098 
02099    else
02100 #endif
02101    {
02102       png_ptr->num_rows = png_ptr->height;
02103       png_ptr->usr_width = png_ptr->width;
02104    }
02105 
02106    png_zlib_claim(png_ptr, PNG_ZLIB_FOR_IDAT);
02107    png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
02108    png_ptr->zstream.next_out = png_ptr->zbuf;
02109 }
02110 
02111 /* Internal use only.  Called when finished processing a row of data. */
02112 void /* PRIVATE */
02113 png_write_finish_row(png_structp png_ptr)
02114 {
02115 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
02116    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
02117 
02118    /* Start of interlace block */
02119    static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
02120 
02121    /* Offset to next interlace block */
02122    static PNG_CONST png_byte png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
02123 
02124    /* Start of interlace block in the y direction */
02125    static PNG_CONST png_byte png_pass_ystart[7] = {0, 0, 4, 0, 2, 0, 1};
02126 
02127    /* Offset to next interlace block in the y direction */
02128    static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
02129 #endif
02130 
02131    int ret;
02132 
02133    png_debug(1, "in png_write_finish_row");
02134 
02135    /* Next row */
02136    png_ptr->row_number++;
02137 
02138    /* See if we are done */
02139    if (png_ptr->row_number < png_ptr->num_rows)
02140       return;
02141 
02142 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
02143    /* If interlaced, go to next pass */
02144    if (png_ptr->interlaced)
02145    {
02146       png_ptr->row_number = 0;
02147       if (png_ptr->transformations & PNG_INTERLACE)
02148       {
02149          png_ptr->pass++;
02150       }
02151 
02152       else
02153       {
02154          /* Loop until we find a non-zero width or height pass */
02155          do
02156          {
02157             png_ptr->pass++;
02158 
02159             if (png_ptr->pass >= 7)
02160                break;
02161 
02162             png_ptr->usr_width = (png_ptr->width +
02163                 png_pass_inc[png_ptr->pass] - 1 -
02164                 png_pass_start[png_ptr->pass]) /
02165                 png_pass_inc[png_ptr->pass];
02166 
02167             png_ptr->num_rows = (png_ptr->height +
02168                 png_pass_yinc[png_ptr->pass] - 1 -
02169                 png_pass_ystart[png_ptr->pass]) /
02170                 png_pass_yinc[png_ptr->pass];
02171 
02172             if (png_ptr->transformations & PNG_INTERLACE)
02173                break;
02174 
02175          } while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
02176 
02177       }
02178 
02179       /* Reset the row above the image for the next pass */
02180       if (png_ptr->pass < 7)
02181       {
02182          if (png_ptr->prev_row != NULL)
02183             png_memset(png_ptr->prev_row, 0,
02184                 (png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
02185                 png_ptr->usr_bit_depth, png_ptr->width)) + 1);
02186 
02187          return;
02188       }
02189    }
02190 #endif
02191 
02192    /* If we get here, we've just written the last row, so we need
02193       to flush the compressor */
02194    do
02195    {
02196       /* Tell the compressor we are done */
02197       ret = deflate(&png_ptr->zstream, Z_FINISH);
02198 
02199       /* Check for an error */
02200       if (ret == Z_OK)
02201       {
02202          /* Check to see if we need more room */
02203          if (!(png_ptr->zstream.avail_out))
02204          {
02205             png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
02206             png_ptr->zstream.next_out = png_ptr->zbuf;
02207             png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
02208          }
02209       }
02210 
02211       else if (ret != Z_STREAM_END)
02212       {
02213          if (png_ptr->zstream.msg != NULL)
02214             png_error(png_ptr, png_ptr->zstream.msg);
02215 
02216          else
02217             png_error(png_ptr, "zlib error");
02218       }
02219    } while (ret != Z_STREAM_END);
02220 
02221    /* Write any extra space */
02222    if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
02223    {
02224       png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
02225           png_ptr->zstream.avail_out);
02226    }
02227 
02228    png_zlib_release(png_ptr);
02229    png_ptr->zstream.data_type = Z_BINARY;
02230 }
02231 
02232 #ifdef PNG_WRITE_INTERLACING_SUPPORTED
02233 /* Pick out the correct pixels for the interlace pass.
02234  * The basic idea here is to go through the row with a source
02235  * pointer and a destination pointer (sp and dp), and copy the
02236  * correct pixels for the pass.  As the row gets compacted,
02237  * sp will always be >= dp, so we should never overwrite anything.
02238  * See the default: case for the easiest code to understand.
02239  */
02240 void /* PRIVATE */
02241 png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
02242 {
02243    /* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
02244 
02245    /* Start of interlace block */
02246    static PNG_CONST png_byte png_pass_start[7] = {0, 4, 0, 2, 0, 1, 0};
02247 
02248    /* Offset to next interlace block */
02249    static PNG_CONST png_byte  png_pass_inc[7] = {8, 8, 4, 4, 2, 2, 1};
02250 
02251    png_debug(1, "in png_do_write_interlace");
02252 
02253    /* We don't have to do anything on the last pass (6) */
02254    if (pass < 6)
02255    {
02256       /* Each pixel depth is handled separately */
02257       switch (row_info->pixel_depth)
02258       {
02259          case 1:
02260          {
02261             png_bytep sp;
02262             png_bytep dp;
02263             int shift;
02264             int d;
02265             int value;
02266             png_uint_32 i;
02267             png_uint_32 row_width = row_info->width;
02268 
02269             dp = row;
02270             d = 0;
02271             shift = 7;
02272 
02273             for (i = png_pass_start[pass]; i < row_width;
02274                i += png_pass_inc[pass])
02275             {
02276                sp = row + (png_size_t)(i >> 3);
02277                value = (int)(*sp >> (7 - (int)(i & 0x07))) & 0x01;
02278                d |= (value << shift);
02279 
02280                if (shift == 0)
02281                {
02282                   shift = 7;
02283                   *dp++ = (png_byte)d;
02284                   d = 0;
02285                }
02286 
02287                else
02288                   shift--;
02289 
02290             }
02291             if (shift != 7)
02292                *dp = (png_byte)d;
02293 
02294             break;
02295          }
02296 
02297          case 2:
02298          {
02299             png_bytep sp;
02300             png_bytep dp;
02301             int shift;
02302             int d;
02303             int value;
02304             png_uint_32 i;
02305             png_uint_32 row_width = row_info->width;
02306 
02307             dp = row;
02308             shift = 6;
02309             d = 0;
02310 
02311             for (i = png_pass_start[pass]; i < row_width;
02312                i += png_pass_inc[pass])
02313             {
02314                sp = row + (png_size_t)(i >> 2);
02315                value = (*sp >> ((3 - (int)(i & 0x03)) << 1)) & 0x03;
02316                d |= (value << shift);
02317 
02318                if (shift == 0)
02319                {
02320                   shift = 6;
02321                   *dp++ = (png_byte)d;
02322                   d = 0;
02323                }
02324 
02325                else
02326                   shift -= 2;
02327             }
02328             if (shift != 6)
02329                *dp = (png_byte)d;
02330 
02331             break;
02332          }
02333 
02334          case 4:
02335          {
02336             png_bytep sp;
02337             png_bytep dp;
02338             int shift;
02339             int d;
02340             int value;
02341             png_uint_32 i;
02342             png_uint_32 row_width = row_info->width;
02343 
02344             dp = row;
02345             shift = 4;
02346             d = 0;
02347             for (i = png_pass_start[pass]; i < row_width;
02348                 i += png_pass_inc[pass])
02349             {
02350                sp = row + (png_size_t)(i >> 1);
02351                value = (*sp >> ((1 - (int)(i & 0x01)) << 2)) & 0x0f;
02352                d |= (value << shift);
02353 
02354                if (shift == 0)
02355                {
02356                   shift = 4;
02357                   *dp++ = (png_byte)d;
02358                   d = 0;
02359                }
02360 
02361                else
02362                   shift -= 4;
02363             }
02364             if (shift != 4)
02365                *dp = (png_byte)d;
02366 
02367             break;
02368          }
02369 
02370          default:
02371          {
02372             png_bytep sp;
02373             png_bytep dp;
02374             png_uint_32 i;
02375             png_uint_32 row_width = row_info->width;
02376             png_size_t pixel_bytes;
02377 
02378             /* Start at the beginning */
02379             dp = row;
02380 
02381             /* Find out how many bytes each pixel takes up */
02382             pixel_bytes = (row_info->pixel_depth >> 3);
02383 
02384             /* Loop through the row, only looking at the pixels that matter */
02385             for (i = png_pass_start[pass]; i < row_width;
02386                i += png_pass_inc[pass])
02387             {
02388                /* Find out where the original pixel is */
02389                sp = row + (png_size_t)i * pixel_bytes;
02390 
02391                /* Move the pixel */
02392                if (dp != sp)
02393                   png_memcpy(dp, sp, pixel_bytes);
02394 
02395                /* Next pixel */
02396                dp += pixel_bytes;
02397             }
02398             break;
02399          }
02400       }
02401       /* Set new row width */
02402       row_info->width = (row_info->width +
02403           png_pass_inc[pass] - 1 -
02404           png_pass_start[pass]) /
02405           png_pass_inc[pass];
02406 
02407       row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth,
02408           row_info->width);
02409    }
02410 }
02411 #endif
02412 
02413 /* This filters the row, chooses which filter to use, if it has not already
02414  * been specified by the application, and then writes the row out with the
02415  * chosen filter.
02416  */
02417 static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
02418    png_size_t row_bytes);
02419 
02420 #define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
02421 #define PNG_HISHIFT 10
02422 #define PNG_LOMASK ((png_uint_32)0xffffL)
02423 #define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
02424 void /* PRIVATE */
02425 png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
02426 {
02427    png_bytep best_row;
02428 #ifdef PNG_WRITE_FILTER_SUPPORTED
02429    png_bytep prev_row, row_buf;
02430    png_uint_32 mins, bpp;
02431    png_byte filter_to_do = png_ptr->do_filter;
02432    png_size_t row_bytes = row_info->rowbytes;
02433 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
02434    int num_p_filters = png_ptr->num_prev_filters;
02435 #endif
02436 
02437    png_debug(1, "in png_write_find_filter");
02438 
02439 #ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
02440   if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS)
02441   {
02442      /* These will never be selected so we need not test them. */
02443      filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH);
02444   }
02445 #endif
02446 
02447    /* Find out how many bytes offset each pixel is */
02448    bpp = (row_info->pixel_depth + 7) >> 3;
02449 
02450    prev_row = png_ptr->prev_row;
02451 #endif
02452    best_row = png_ptr->row_buf;
02453 #ifdef PNG_WRITE_FILTER_SUPPORTED
02454    row_buf = best_row;
02455    mins = PNG_MAXSUM;
02456 
02457    /* The prediction method we use is to find which method provides the
02458     * smallest value when summing the absolute values of the distances
02459     * from zero, using anything >= 128 as negative numbers.  This is known
02460     * as the "minimum sum of absolute differences" heuristic.  Other
02461     * heuristics are the "weighted minimum sum of absolute differences"
02462     * (experimental and can in theory improve compression), and the "zlib
02463     * predictive" method (not implemented yet), which does test compressions
02464     * of lines using different filter methods, and then chooses the
02465     * (series of) filter(s) that give minimum compressed data size (VERY
02466     * computationally expensive).
02467     *
02468     * GRR 980525:  consider also
02469     *
02470     *   (1) minimum sum of absolute differences from running average (i.e.,
02471     *       keep running sum of non-absolute differences & count of bytes)
02472     *       [track dispersion, too?  restart average if dispersion too large?]
02473     *
02474     *  (1b) minimum sum of absolute differences from sliding average, probably
02475     *       with window size <= deflate window (usually 32K)
02476     *
02477     *   (2) minimum sum of squared differences from zero or running average
02478     *       (i.e., ~ root-mean-square approach)
02479     */
02480 
02481 
02482    /* We don't need to test the 'no filter' case if this is the only filter
02483     * that has been chosen, as it doesn't actually do anything to the data.
02484     */
02485    if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE)
02486    {
02487       png_bytep rp;
02488       png_uint_32 sum = 0;
02489       png_size_t i;
02490       int v;
02491 
02492       for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++)
02493       {
02494          v = *rp;
02495          sum += (v < 128) ? v : 256 - v;
02496       }
02497 
02498 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
02499       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
02500       {
02501          png_uint_32 sumhi, sumlo;
02502          int j;
02503          sumlo = sum & PNG_LOMASK;
02504          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */
02505 
02506          /* Reduce the sum if we match any of the previous rows */
02507          for (j = 0; j < num_p_filters; j++)
02508          {
02509             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
02510             {
02511                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
02512                    PNG_WEIGHT_SHIFT;
02513 
02514                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
02515                    PNG_WEIGHT_SHIFT;
02516             }
02517          }
02518 
02519          /* Factor in the cost of this filter (this is here for completeness,
02520           * but it makes no sense to have a "cost" for the NONE filter, as
02521           * it has the minimum possible computational cost - none).
02522           */
02523          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
02524              PNG_COST_SHIFT;
02525 
02526          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >>
02527              PNG_COST_SHIFT;
02528 
02529          if (sumhi > PNG_HIMASK)
02530             sum = PNG_MAXSUM;
02531 
02532          else
02533             sum = (sumhi << PNG_HISHIFT) + sumlo;
02534       }
02535 #endif
02536       mins = sum;
02537    }
02538 
02539    /* Sub filter */
02540    if (filter_to_do == PNG_FILTER_SUB)
02541    /* It's the only filter so no testing is needed */
02542    {
02543       png_bytep rp, lp, dp;
02544       png_size_t i;
02545 
02546       for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
02547            i++, rp++, dp++)
02548       {
02549          *dp = *rp;
02550       }
02551 
02552       for (lp = row_buf + 1; i < row_bytes;
02553          i++, rp++, lp++, dp++)
02554       {
02555          *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
02556       }
02557 
02558       best_row = png_ptr->sub_row;
02559    }
02560 
02561    else if (filter_to_do & PNG_FILTER_SUB)
02562    {
02563       png_bytep rp, dp, lp;
02564       png_uint_32 sum = 0, lmins = mins;
02565       png_size_t i;
02566       int v;
02567 
02568 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
02569       /* We temporarily increase the "minimum sum" by the factor we
02570        * would reduce the sum of this filter, so that we can do the
02571        * early exit comparison without scaling the sum each time.
02572        */
02573       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
02574       {
02575          int j;
02576          png_uint_32 lmhi, lmlo;
02577          lmlo = lmins & PNG_LOMASK;
02578          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
02579 
02580          for (j = 0; j < num_p_filters; j++)
02581          {
02582             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
02583             {
02584                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
02585                    PNG_WEIGHT_SHIFT;
02586 
02587                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
02588                    PNG_WEIGHT_SHIFT;
02589             }
02590          }
02591 
02592          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
02593              PNG_COST_SHIFT;
02594 
02595          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
02596              PNG_COST_SHIFT;
02597 
02598          if (lmhi > PNG_HIMASK)
02599             lmins = PNG_MAXSUM;
02600 
02601          else
02602             lmins = (lmhi << PNG_HISHIFT) + lmlo;
02603       }
02604 #endif
02605 
02606       for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp;
02607            i++, rp++, dp++)
02608       {
02609          v = *dp = *rp;
02610 
02611          sum += (v < 128) ? v : 256 - v;
02612       }
02613 
02614       for (lp = row_buf + 1; i < row_bytes;
02615          i++, rp++, lp++, dp++)
02616       {
02617          v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
02618 
02619          sum += (v < 128) ? v : 256 - v;
02620 
02621          if (sum > lmins)  /* We are already worse, don't continue. */
02622             break;
02623       }
02624 
02625 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
02626       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
02627       {
02628          int j;
02629          png_uint_32 sumhi, sumlo;
02630          sumlo = sum & PNG_LOMASK;
02631          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
02632 
02633          for (j = 0; j < num_p_filters; j++)
02634          {
02635             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB)
02636             {
02637                sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >>
02638                    PNG_WEIGHT_SHIFT;
02639 
02640                sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >>
02641                    PNG_WEIGHT_SHIFT;
02642             }
02643          }
02644 
02645          sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
02646              PNG_COST_SHIFT;
02647 
02648          sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >>
02649              PNG_COST_SHIFT;
02650 
02651          if (sumhi > PNG_HIMASK)
02652             sum = PNG_MAXSUM;
02653 
02654          else
02655             sum = (sumhi << PNG_HISHIFT) + sumlo;
02656       }
02657 #endif
02658 
02659       if (sum < mins)
02660       {
02661          mins = sum;
02662          best_row = png_ptr->sub_row;
02663       }
02664    }
02665 
02666    /* Up filter */
02667    if (filter_to_do == PNG_FILTER_UP)
02668    {
02669       png_bytep rp, dp, pp;
02670       png_size_t i;
02671 
02672       for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
02673           pp = prev_row + 1; i < row_bytes;
02674           i++, rp++, pp++, dp++)
02675       {
02676          *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
02677       }
02678 
02679       best_row = png_ptr->up_row;
02680    }
02681 
02682    else if (filter_to_do & PNG_FILTER_UP)
02683    {
02684       png_bytep rp, dp, pp;
02685       png_uint_32 sum = 0, lmins = mins;
02686       png_size_t i;
02687       int v;
02688 
02689 
02690 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
02691       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
02692       {
02693          int j;
02694          png_uint_32 lmhi, lmlo;
02695          lmlo = lmins & PNG_LOMASK;
02696          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
02697 
02698          for (j = 0; j < num_p_filters; j++)
02699          {
02700             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
02701             {
02702                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
02703                    PNG_WEIGHT_SHIFT;
02704 
02705                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
02706                    PNG_WEIGHT_SHIFT;
02707             }
02708          }
02709 
02710          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
02711              PNG_COST_SHIFT;
02712 
02713          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >>
02714              PNG_COST_SHIFT;
02715 
02716          if (lmhi > PNG_HIMASK)
02717             lmins = PNG_MAXSUM;
02718 
02719          else
02720             lmins = (lmhi << PNG_HISHIFT) + lmlo;
02721       }
02722 #endif
02723 
02724       for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
02725           pp = prev_row + 1; i < row_bytes; i++)
02726       {
02727          v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
02728 
02729          sum += (v < 128) ? v : 256 - v;
02730 
02731          if (sum > lmins)  /* We are already worse, don't continue. */
02732             break;
02733       }
02734 
02735 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
02736       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
02737       {
02738          int j;
02739          png_uint_32 sumhi, sumlo;
02740          sumlo = sum & PNG_LOMASK;
02741          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
02742 
02743          for (j = 0; j < num_p_filters; j++)
02744          {
02745             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP)
02746             {
02747                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
02748                    PNG_WEIGHT_SHIFT;
02749 
02750                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
02751                    PNG_WEIGHT_SHIFT;
02752             }
02753          }
02754 
02755          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
02756              PNG_COST_SHIFT;
02757 
02758          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >>
02759              PNG_COST_SHIFT;
02760 
02761          if (sumhi > PNG_HIMASK)
02762             sum = PNG_MAXSUM;
02763 
02764          else
02765             sum = (sumhi << PNG_HISHIFT) + sumlo;
02766       }
02767 #endif
02768 
02769       if (sum < mins)
02770       {
02771          mins = sum;
02772          best_row = png_ptr->up_row;
02773       }
02774    }
02775 
02776    /* Avg filter */
02777    if (filter_to_do == PNG_FILTER_AVG)
02778    {
02779       png_bytep rp, dp, pp, lp;
02780       png_uint_32 i;
02781 
02782       for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
02783            pp = prev_row + 1; i < bpp; i++)
02784       {
02785          *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
02786       }
02787 
02788       for (lp = row_buf + 1; i < row_bytes; i++)
02789       {
02790          *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
02791                  & 0xff);
02792       }
02793       best_row = png_ptr->avg_row;
02794    }
02795 
02796    else if (filter_to_do & PNG_FILTER_AVG)
02797    {
02798       png_bytep rp, dp, pp, lp;
02799       png_uint_32 sum = 0, lmins = mins;
02800       png_size_t i;
02801       int v;
02802 
02803 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
02804       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
02805       {
02806          int j;
02807          png_uint_32 lmhi, lmlo;
02808          lmlo = lmins & PNG_LOMASK;
02809          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
02810 
02811          for (j = 0; j < num_p_filters; j++)
02812          {
02813             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG)
02814             {
02815                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
02816                    PNG_WEIGHT_SHIFT;
02817 
02818                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
02819                    PNG_WEIGHT_SHIFT;
02820             }
02821          }
02822 
02823          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
02824              PNG_COST_SHIFT;
02825 
02826          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >>
02827              PNG_COST_SHIFT;
02828 
02829          if (lmhi > PNG_HIMASK)
02830             lmins = PNG_MAXSUM;
02831 
02832          else
02833             lmins = (lmhi << PNG_HISHIFT) + lmlo;
02834       }
02835 #endif
02836 
02837       for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
02838            pp = prev_row + 1; i < bpp; i++)
02839       {
02840          v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
02841 
02842          sum += (v < 128) ? v : 256 - v;
02843       }
02844 
02845       for (lp = row_buf + 1; i < row_bytes; i++)
02846       {
02847          v = *dp++ =
02848              (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
02849 
02850          sum += (v < 128) ? v : 256 - v;
02851 
02852          if (sum > lmins)  /* We are already worse, don't continue. */
02853             break;
02854       }
02855 
02856 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
02857       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
02858       {
02859          int j;
02860          png_uint_32 sumhi, sumlo;
02861          sumlo = sum & PNG_LOMASK;
02862          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
02863 
02864          for (j = 0; j < num_p_filters; j++)
02865          {
02866             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE)
02867             {
02868                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
02869                    PNG_WEIGHT_SHIFT;
02870 
02871                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
02872                    PNG_WEIGHT_SHIFT;
02873             }
02874          }
02875 
02876          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
02877              PNG_COST_SHIFT;
02878 
02879          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >>
02880              PNG_COST_SHIFT;
02881 
02882          if (sumhi > PNG_HIMASK)
02883             sum = PNG_MAXSUM;
02884 
02885          else
02886             sum = (sumhi << PNG_HISHIFT) + sumlo;
02887       }
02888 #endif
02889 
02890       if (sum < mins)
02891       {
02892          mins = sum;
02893          best_row = png_ptr->avg_row;
02894       }
02895    }
02896 
02897    /* Paeth filter */
02898    if (filter_to_do == PNG_FILTER_PAETH)
02899    {
02900       png_bytep rp, dp, pp, cp, lp;
02901       png_size_t i;
02902 
02903       for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
02904           pp = prev_row + 1; i < bpp; i++)
02905       {
02906          *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
02907       }
02908 
02909       for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
02910       {
02911          int a, b, c, pa, pb, pc, p;
02912 
02913          b = *pp++;
02914          c = *cp++;
02915          a = *lp++;
02916 
02917          p = b - c;
02918          pc = a - c;
02919 
02920 #ifdef PNG_USE_ABS
02921          pa = abs(p);
02922          pb = abs(pc);
02923          pc = abs(p + pc);
02924 #else
02925          pa = p < 0 ? -p : p;
02926          pb = pc < 0 ? -pc : pc;
02927          pc = (p + pc) < 0 ? -(p + pc) : p + pc;
02928 #endif
02929 
02930          p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
02931 
02932          *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
02933       }
02934       best_row = png_ptr->paeth_row;
02935    }
02936 
02937    else if (filter_to_do & PNG_FILTER_PAETH)
02938    {
02939       png_bytep rp, dp, pp, cp, lp;
02940       png_uint_32 sum = 0, lmins = mins;
02941       png_size_t i;
02942       int v;
02943 
02944 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
02945       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
02946       {
02947          int j;
02948          png_uint_32 lmhi, lmlo;
02949          lmlo = lmins & PNG_LOMASK;
02950          lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK;
02951 
02952          for (j = 0; j < num_p_filters; j++)
02953          {
02954             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
02955             {
02956                lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >>
02957                    PNG_WEIGHT_SHIFT;
02958 
02959                lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >>
02960                    PNG_WEIGHT_SHIFT;
02961             }
02962          }
02963 
02964          lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
02965              PNG_COST_SHIFT;
02966 
02967          lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >>
02968              PNG_COST_SHIFT;
02969 
02970          if (lmhi > PNG_HIMASK)
02971             lmins = PNG_MAXSUM;
02972 
02973          else
02974             lmins = (lmhi << PNG_HISHIFT) + lmlo;
02975       }
02976 #endif
02977 
02978       for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
02979           pp = prev_row + 1; i < bpp; i++)
02980       {
02981          v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
02982 
02983          sum += (v < 128) ? v : 256 - v;
02984       }
02985 
02986       for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
02987       {
02988          int a, b, c, pa, pb, pc, p;
02989 
02990          b = *pp++;
02991          c = *cp++;
02992          a = *lp++;
02993 
02994 #ifndef PNG_SLOW_PAETH
02995          p = b - c;
02996          pc = a - c;
02997 #ifdef PNG_USE_ABS
02998          pa = abs(p);
02999          pb = abs(pc);
03000          pc = abs(p + pc);
03001 #else
03002          pa = p < 0 ? -p : p;
03003          pb = pc < 0 ? -pc : pc;
03004          pc = (p + pc) < 0 ? -(p + pc) : p + pc;
03005 #endif
03006          p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
03007 #else /* PNG_SLOW_PAETH */
03008          p = a + b - c;
03009          pa = abs(p - a);
03010          pb = abs(p - b);
03011          pc = abs(p - c);
03012 
03013          if (pa <= pb && pa <= pc)
03014             p = a;
03015 
03016          else if (pb <= pc)
03017             p = b;
03018 
03019          else
03020             p = c;
03021 #endif /* PNG_SLOW_PAETH */
03022 
03023          v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
03024 
03025          sum += (v < 128) ? v : 256 - v;
03026 
03027          if (sum > lmins)  /* We are already worse, don't continue. */
03028             break;
03029       }
03030 
03031 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
03032       if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED)
03033       {
03034          int j;
03035          png_uint_32 sumhi, sumlo;
03036          sumlo = sum & PNG_LOMASK;
03037          sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK;
03038 
03039          for (j = 0; j < num_p_filters; j++)
03040          {
03041             if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH)
03042             {
03043                sumlo = (sumlo * png_ptr->filter_weights[j]) >>
03044                    PNG_WEIGHT_SHIFT;
03045 
03046                sumhi = (sumhi * png_ptr->filter_weights[j]) >>
03047                    PNG_WEIGHT_SHIFT;
03048             }
03049          }
03050 
03051          sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
03052              PNG_COST_SHIFT;
03053 
03054          sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >>
03055              PNG_COST_SHIFT;
03056 
03057          if (sumhi > PNG_HIMASK)
03058             sum = PNG_MAXSUM;
03059 
03060          else
03061             sum = (sumhi << PNG_HISHIFT) + sumlo;
03062       }
03063 #endif
03064 
03065       if (sum < mins)
03066       {
03067          best_row = png_ptr->paeth_row;
03068       }
03069    }
03070 #endif /* PNG_WRITE_FILTER_SUPPORTED */
03071 
03072    /* Do the actual writing of the filtered row data from the chosen filter. */
03073    png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
03074 
03075 #ifdef PNG_WRITE_FILTER_SUPPORTED
03076 #ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
03077    /* Save the type of filter we picked this time for future calculations */
03078    if (png_ptr->num_prev_filters > 0)
03079    {
03080       int j;
03081 
03082       for (j = 1; j < num_p_filters; j++)
03083       {
03084          png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1];
03085       }
03086 
03087       png_ptr->prev_filters[j] = best_row[0];
03088    }
03089 #endif
03090 #endif /* PNG_WRITE_FILTER_SUPPORTED */
03091 }
03092 
03093 
03094 /* Do the actual writing of a previously filtered row. */
03095 static void
03096 png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
03097    png_size_t avail/*includes filter byte*/)
03098 {
03099    png_debug(1, "in png_write_filtered_row");
03100 
03101    png_debug1(2, "filter = %d", filtered_row[0]);
03102    /* Set up the zlib input buffer */
03103 
03104    png_ptr->zstream.next_in = filtered_row;
03105    png_ptr->zstream.avail_in = 0;
03106    /* Repeat until we have compressed all the data */
03107    do
03108    {
03109       int ret; /* Return of zlib */
03110 
03111       /* Record the number of bytes available - zlib supports at least 65535
03112        * bytes at one step, depending on the size of the zlib type 'uInt', the
03113        * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h).
03114        * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e.
03115        * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a
03116        * uInt.  ZLIB_IO_MAX can be safely reduced to cause zlib to be called
03117        * with smaller chunks of data.
03118        */
03119       if (png_ptr->zstream.avail_in == 0)
03120       {
03121          if (avail > ZLIB_IO_MAX)
03122          {
03123             png_ptr->zstream.avail_in  = ZLIB_IO_MAX;
03124             avail -= ZLIB_IO_MAX;
03125          }
03126 
03127          else
03128          {
03129             /* So this will fit in the available uInt space: */
03130             png_ptr->zstream.avail_in = (uInt)avail;
03131             avail = 0;
03132          }
03133       }
03134 
03135       /* Compress the data */
03136       ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
03137 
03138       /* Check for compression errors */
03139       if (ret != Z_OK)
03140       {
03141          if (png_ptr->zstream.msg != NULL)
03142             png_error(png_ptr, png_ptr->zstream.msg);
03143 
03144          else
03145             png_error(png_ptr, "zlib error");
03146       }
03147 
03148       /* See if it is time to write another IDAT */
03149       if (!(png_ptr->zstream.avail_out))
03150       {
03151          /* Write the IDAT and reset the zlib output buffer */
03152          png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
03153       }
03154    /* Repeat until all data has been compressed */
03155    } while (avail > 0 || png_ptr->zstream.avail_in > 0);
03156 
03157    /* Swap the current and previous rows */
03158    if (png_ptr->prev_row != NULL)
03159    {
03160       png_bytep tptr;
03161 
03162       tptr = png_ptr->prev_row;
03163       png_ptr->prev_row = png_ptr->row_buf;
03164       png_ptr->row_buf = tptr;
03165    }
03166 
03167    /* Finish row - updates counters and flushes zlib if last row */
03168    png_write_finish_row(png_ptr);
03169 
03170 #ifdef PNG_WRITE_FLUSH_SUPPORTED
03171    png_ptr->flush_rows++;
03172 
03173    if (png_ptr->flush_dist > 0 &&
03174        png_ptr->flush_rows >= png_ptr->flush_dist)
03175    {
03176       png_write_flush(png_ptr);
03177    }
03178 #endif
03179 }
03180 #endif /* PNG_WRITE_SUPPORTED */

Generated on Thu May 24 2012 04:19:42 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.