/* pngwrite.c - general routines to write a PNG file
*
* libpng 1.2.8 - December 3, 2004
* For conditions of distribution and use, see copyright notice in png.h
* Copyright (c) 1998-2004 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*/
/* get internal access to png.h */
#define PNG_INTERNAL
#include "png.h"
#ifdef PNG_WRITE_SUPPORTED
/* Writes all the PNG information. This is the suggested way to use the
* library. If you have a new chunk to add, make a function to write it,
* and put it in the correct location here. If you want the chunk written
* after the image data, put it in png_write_end(). I strongly encourage
* you to supply a PNG_INFO_ flag, and check info_ptr->valid before writing
* the chunk, as that will keep the code from breaking if you want to just
* write a plain PNG file. If you have long comments, I suggest writing
* them in png_write_end(), and compressing them.
*/
void PNGAPI
{
{
#if defined(PNG_MNG_FEATURES_SUPPORTED)
{
}
#endif
/* write IHDR information. */
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
#else
0);
#endif
/* the rest of these check to see if the valid field has the appropriate
flag set, and if it does, writes the chunk. */
#if defined(PNG_WRITE_gAMA_SUPPORTED)
{
# ifdef PNG_FLOATING_POINT_SUPPORTED
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
# endif
#endif
}
#endif
#if defined(PNG_WRITE_sRGB_SUPPORTED)
#endif
#if defined(PNG_WRITE_iCCP_SUPPORTED)
#endif
#if defined(PNG_WRITE_sBIT_SUPPORTED)
#endif
#if defined(PNG_WRITE_cHRM_SUPPORTED)
{
#ifdef PNG_FLOATING_POINT_SUPPORTED
#else
# ifdef PNG_FIXED_POINT_SUPPORTED
# endif
#endif
}
#endif
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
if (info_ptr->unknown_chunks_num)
{
up++)
{
if (keep != PNG_HANDLE_CHUNK_NEVER &&
{
}
}
}
#endif
}
}
void PNGAPI
{
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
int i;
#endif
#if defined(PNG_WRITE_tRNS_SUPPORTED)
{
#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
/* invert the alpha channel (in tRNS) */
{
int j;
}
#endif
}
#endif
#if defined(PNG_WRITE_bKGD_SUPPORTED)
#endif
#if defined(PNG_WRITE_hIST_SUPPORTED)
#endif
#if defined(PNG_WRITE_oFFs_SUPPORTED)
#endif
#if defined(PNG_WRITE_pCAL_SUPPORTED)
#endif
#if defined(PNG_WRITE_sCAL_SUPPORTED)
#if defined(PNG_FLOATING_POINT_SUPPORTED) && !defined(PNG_NO_STDIO)
#else
#ifdef PNG_FIXED_POINT_SUPPORTED
#else
"png_write_sCAL not supported; sCAL chunk not written.\n");
#endif
#endif
#endif
#if defined(PNG_WRITE_pHYs_SUPPORTED)
#endif
#if defined(PNG_WRITE_tIME_SUPPORTED)
{
}
#endif
#if defined(PNG_WRITE_sPLT_SUPPORTED)
for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
#endif
#if defined(PNG_WRITE_TEXT_SUPPORTED)
/* Check to see if we need to write text chunks */
{
/* an internationalized chunk? */
{
#if defined(PNG_WRITE_iTXt_SUPPORTED)
/* write international chunk */
#else
#endif
/* Mark this chunk as written */
}
/* If we want a compressed text chunk */
{
#if defined(PNG_WRITE_zTXt_SUPPORTED)
/* write compressed chunk */
#else
#endif
/* Mark this chunk as written */
}
{
#if defined(PNG_WRITE_tEXt_SUPPORTED)
/* write uncompressed chunk */
0);
#else
#endif
/* Mark this chunk as written */
}
}
#endif
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
if (info_ptr->unknown_chunks_num)
{
up++)
{
if (keep != PNG_HANDLE_CHUNK_NEVER &&
{
}
}
}
#endif
}
/* Writes the end of the PNG file. If you don't want to write comments or
* time information, you can pass NULL for info. If you already wrote these
* in png_write_info(), do not write them again here. If you have long
* comments, I suggest writing them here, and compressing them.
*/
void PNGAPI
{
/* see if user wants us to write information chunks */
{
#if defined(PNG_WRITE_TEXT_SUPPORTED)
int i; /* local index variable */
#endif
#if defined(PNG_WRITE_tIME_SUPPORTED)
/* check to see if user has supplied a time chunk */
#endif
#if defined(PNG_WRITE_TEXT_SUPPORTED)
/* loop through comment chunks */
{
/* an internationalized chunk? */
{
#if defined(PNG_WRITE_iTXt_SUPPORTED)
/* write international chunk */
#else
#endif
/* Mark this chunk as written */
}
{
#if defined(PNG_WRITE_zTXt_SUPPORTED)
/* write compressed chunk */
#else
#endif
/* Mark this chunk as written */
}
{
#if defined(PNG_WRITE_tEXt_SUPPORTED)
/* write uncompressed chunk */
#else
#endif
/* Mark this chunk as written */
}
}
#endif
#if defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED)
if (info_ptr->unknown_chunks_num)
{
up++)
{
if (keep != PNG_HANDLE_CHUNK_NEVER &&
{
}
}
}
#endif
}
/* write end of PNG file */
#if 0
/* This flush, added in libpng-1.0.8, causes some applications to crash
because they do not set png_ptr->output_flush_fn */
#endif
}
#if defined(PNG_WRITE_tIME_SUPPORTED)
#if !defined(_WIN32_WCE)
/* "time.h" functions are not supported on WindowsCE */
void PNGAPI
{
}
void PNGAPI
{
}
#endif
#endif
/* Initialize png_ptr structure, and allocate any memory needed */
{
#ifdef PNG_USER_MEM_SUPPORTED
}
/* Alternate initialize png_ptr structure, and allocate any memory needed */
{
#endif /* PNG_USER_MEM_SUPPORTED */
#ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD
#endif
#endif
int i;
#ifdef PNG_USER_MEM_SUPPORTED
#else
#endif /* PNG_USER_MEM_SUPPORTED */
return (NULL);
#if !defined(PNG_1_0_X)
#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
#endif
#endif /* PNG_1_0_X */
/* added at libpng-1.2.6 */
#endif
#ifdef PNG_SETJMP_SUPPORTED
#ifdef USE_FAR_KEYWORD
#else
#endif
{
return (NULL);
}
#ifdef USE_FAR_KEYWORD
#endif
#endif
#ifdef PNG_USER_MEM_SUPPORTED
#endif /* PNG_USER_MEM_SUPPORTED */
i=0;
do
{
if(user_png_ver[i] != png_libpng_ver[i])
} while (png_libpng_ver[i++]);
{
/* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
* we must recompile any applications that use any older library version.
* For versions after libpng 1.0, we will be compatible, so we need
* only check the first digit.
*/
{
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
if (user_png_ver)
{
}
#endif
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
#endif
"Incompatible libpng version in application and library");
}
}
/* initialize zbuf - compression buffer */
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
#endif
#ifdef PNG_SETJMP_SUPPORTED
/* Applications that neglect to set up their own setjmp() and then encounter
a png_error() will longjmp here. Since the jmpbuf is then meaningless we
abort instead of returning. */
#ifdef USE_FAR_KEYWORD
PNG_ABORT();
#else
PNG_ABORT();
#endif
#endif
return (png_ptr);
}
/* Initialize png_ptr structure, and allocate any memory needed */
void PNGAPI
{
/* We only come here via pre-1.0.7-compiled applications */
}
void PNGAPI
{
/* We only come here via pre-1.0.12-compiled applications */
#if !defined(PNG_NO_STDIO) && !defined(_WIN32_WCE)
{
if (user_png_ver)
{
}
}
#endif
{
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
#endif
"The png struct allocated by the application for writing is too small.");
}
{
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
#endif
"The info struct allocated by the application for writing is too small.");
}
}
void PNGAPI
{
#ifdef PNG_SETJMP_SUPPORTED
#endif
int i = 0;
do
{
if (user_png_ver[i] != png_libpng_ver[i])
{
#ifdef PNG_LEGACY_SUPPORTED
#else
"Application uses deprecated png_write_init() and should be recompiled.");
break;
#endif
}
} while (png_libpng_ver[i++]);
#ifdef PNG_SETJMP_SUPPORTED
/* save jump buffer and error functions */
#endif
{
}
/* reset all variables to 0 */
/* added at libpng-1.2.6 */
#endif
#if !defined(PNG_1_0_X)
#ifdef PNG_ASSEMBLER_CODE_SUPPORTED
#endif
#endif /* PNG_1_0_X */
#ifdef PNG_SETJMP_SUPPORTED
/* restore jump buffer */
#endif
/* initialize zbuf - compression buffer */
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
#endif
}
/* Write a few rows of image data. If the image is interlaced,
* either you will have to write the 7 sub images, or, if you
* have called png_set_interlace_handling(), you will have to
* "write" the image seven times.
*/
void PNGAPI
{
png_uint_32 i; /* row counter */
/* loop through the rows */
{
}
}
/* Write the image. You only need to call this function once, even
* if you are writing an interlaced image.
*/
void PNGAPI
{
png_uint_32 i; /* row index */
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
/* intialize interlace handling. If image is not interlaced,
this will set pass to 1 */
#else
num_pass = 1;
#endif
/* loop through passes */
{
/* loop through image */
{
}
}
}
/* called by user to write a row of image data */
void PNGAPI
{
/* initialize transformations and other stuff if first time */
{
/* make sure we wrote the header info */
"png_write_info was never called before png_write_row.");
/* check for transforms that have been set but were defined out */
#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
#endif
#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
#endif
#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && defined(PNG_READ_PACKSWAP_SUPPORTED)
#endif
#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
#endif
#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
#endif
#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
#endif
#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
#endif
}
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
/* if interlaced and not interested in row, return */
{
{
case 0:
{
return;
}
break;
case 1:
{
return;
}
break;
case 2:
{
return;
}
break;
case 3:
{
return;
}
break;
case 4:
{
return;
}
break;
case 5:
{
return;
}
break;
case 6:
{
return;
}
break;
}
}
#endif
/* set up row info for transformations */
/* Copy user's row into buffer, leaving room for filter byte. */
#if defined(PNG_WRITE_INTERLACING_SUPPORTED)
/* handle interlacing */
{
/* this should always get caught above, but still ... */
{
return;
}
}
#endif
/* handle other transformations */
if (png_ptr->transformations)
#if defined(PNG_MNG_FEATURES_SUPPORTED)
/* Write filter_method 64 (intrapixel differencing) only if
* 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
* 2. Libpng did not write a PNG signature (this filter_method is only
* used in PNG datastreams that are embedded in MNG datastreams) and
* 3. The application called png_permit_mng_features with a mask that
* included PNG_FLAG_MNG_FILTER_64 and
* 4. The filter_method is 64 and
* 5. The color_type is RGB or RGBA
*/
{
/* Intrapixel differencing */
}
#endif
/* Find a filter if necessary, filter the row and write it out. */
}
#if defined(PNG_WRITE_FLUSH_SUPPORTED)
/* Set the automatic flush interval or 0 to turn flushing off */
void PNGAPI
{
}
/* flush the current output buffers now */
void PNGAPI
{
int wrote_IDAT;
/* We have already written out all of the data */
return;
do
{
int ret;
/* compress the data */
wrote_IDAT = 0;
/* check for compression errors */
{
else
}
{
/* write the IDAT and reset the zlib output buffer */
wrote_IDAT = 1;
}
} while(wrote_IDAT == 1);
/* If there is any data left to be output, write it into a new IDAT */
{
/* write the IDAT and reset the zlib output buffer */
}
png_ptr->flush_rows = 0;
}
#endif /* PNG_WRITE_FLUSH_SUPPORTED */
/* free all memory used by the write */
void PNGAPI
{
#ifdef PNG_USER_MEM_SUPPORTED
#endif
if (png_ptr_ptr != NULL)
{
png_ptr = *png_ptr_ptr;
#ifdef PNG_USER_MEM_SUPPORTED
#endif
}
if (info_ptr_ptr != NULL)
info_ptr = *info_ptr_ptr;
{
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
if (png_ptr->num_chunk_list)
{
}
#endif
#ifdef PNG_USER_MEM_SUPPORTED
#else
#endif
*info_ptr_ptr = NULL;
}
{
#ifdef PNG_USER_MEM_SUPPORTED
#else
#endif
*png_ptr_ptr = NULL;
}
}
/* Free any memory used in png_ptr struct (old method) */
void /* PRIVATE */
{
#ifdef PNG_SETJMP_SUPPORTED
#endif
#ifdef PNG_USER_MEM_SUPPORTED
#endif
/* free any memory zlib uses */
/* free our memory. png_free checks NULL for us. */
#if defined(PNG_TIME_RFC1123_SUPPORTED)
#endif
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED)
#endif
#ifdef PNG_SETJMP_SUPPORTED
/* reset structure */
#endif
#ifdef PNG_USER_MEM_SUPPORTED
#endif
#ifdef PNG_USER_MEM_SUPPORTED
#endif
#ifdef PNG_SETJMP_SUPPORTED
#endif
}
/* Allow the application to select one or more row filters to use. */
void PNGAPI
{
#if defined(PNG_MNG_FEATURES_SUPPORTED)
#endif
if (method == PNG_FILTER_TYPE_BASE)
{
{
case 5:
case 6:
}
/* If we have allocated the row_buf, this means we have already started
* with the image and we should have allocated all of the filter buffers
* that have been selected. If prev_row isn't already allocated, then
* it is too late to start using the filters that need it, since we
* will be missing the data in the previous row. If an application
* wants to start and stop using particular filters during compression,
* it should start out with all of the filters, and then add and
* remove them after the start of compression.
*/
{
{
}
{
{
}
else
{
}
}
{
{
}
else
{
}
}
{
{
}
else
{
}
}
}
}
else
}
/* This allows us to influence the way in which libpng chooses the "best"
* filter for the current scanline. While the "minimum-sum-of-absolute-
* differences metric is relatively fast and effective, there is some
* question as to whether it can be improved upon by trying to keep the
* filtered data going to zlib more consistent, hopefully resulting in
* better compression.
*/
#if defined(PNG_WRITE_WEIGHTED_FILTER_SUPPORTED) /* GRR 970116 */
void PNGAPI
{
int i;
{
return;
}
{
}
{
num_weights = 0;
}
if (num_weights > 0)
{
{
/* To make sure that the weighting starts out fairly */
for (i = 0; i < num_weights; i++)
{
}
}
{
for (i = 0; i < num_weights; i++)
{
png_ptr->inv_filter_weights[i] =
}
}
for (i = 0; i < num_weights; i++)
{
if (filter_weights[i] < 0.0)
{
png_ptr->inv_filter_weights[i] =
}
else
{
png_ptr->inv_filter_weights[i] =
png_ptr->filter_weights[i] =
}
}
}
/* If, in the future, there are other filter methods, this would
* need to be based on png_ptr->filter.
*/
{
for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
{
png_ptr->inv_filter_costs[i] =
}
}
/* Here is where we set the relative costs of the different filters. We
* should take the desired compression level into account when setting
* the costs, so that Paeth, for instance, has a high relative cost at low
* compression levels, while it has a lower relative cost at higher
* compression settings. The filter types are in order of increasing
* relative cost, so it would be possible to do this with an algorithm.
*/
for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
{
{
png_ptr->inv_filter_costs[i] =
}
else if (filter_costs[i] >= 1.0)
{
png_ptr->inv_filter_costs[i] =
png_ptr->filter_costs[i] =
}
}
}
#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
void PNGAPI
{
}
void PNGAPI
{
}
void PNGAPI
{
}
void PNGAPI
{
if (window_bits > 15)
else if (window_bits < 8)
#ifndef WBITS_8_OK
/* avoid libpng bug with 256-byte windows */
if (window_bits == 8)
{
window_bits=9;
}
#endif
}
void PNGAPI
{
if (method != 8)
}
void PNGAPI
{
}
#if defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
void PNGAPI
{
}
#endif
#if defined(PNG_INFO_IMAGE_SUPPORTED)
void PNGAPI
{
#if defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
/* invert the alpha channel from opacity to transparency */
#endif
/* Write the file header information. */
/* ------ these transformations don't touch the info structure ------- */
#if defined(PNG_WRITE_INVERT_SUPPORTED)
/* invert monochrome pixels */
#endif
#if defined(PNG_WRITE_SHIFT_SUPPORTED)
/* Shift the pixels up to a legal bit depth and fill in
* as appropriate to correctly scale the image.
*/
if ((transforms & PNG_TRANSFORM_SHIFT)
#endif
#if defined(PNG_WRITE_PACK_SUPPORTED)
/* pack pixels into bytes */
if (transforms & PNG_TRANSFORM_PACKING)
#endif
#if defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
/* swap location of alpha bytes from ARGB to RGBA */
#endif
#if defined(PNG_WRITE_FILLER_SUPPORTED)
* RGB (4 channels -> 3 channels). The second parameter is not used.
*/
#endif
#if defined(PNG_WRITE_BGR_SUPPORTED)
/* flip BGR pixels to RGB */
if (transforms & PNG_TRANSFORM_BGR)
#endif
#if defined(PNG_WRITE_SWAP_SUPPORTED)
/* swap bytes of 16-bit files to most significant byte first */
#endif
#if defined(PNG_WRITE_PACKSWAP_SUPPORTED)
/* swap bits of 1, 2, 4 bit packed pixel formats */
if (transforms & PNG_TRANSFORM_PACKSWAP)
#endif
/* ----------------------- end of transformations ------------------- */
/* write the bits */
/* It is REQUIRED to call this to finish writing the rest of the file */
/* quiet compiler warnings */ return;
}
#endif
#endif /* PNG_WRITE_SUPPORTED */