mirror of
https://git.code.sf.net/p/libpng/code.git
synced 2025-07-10 18:04:09 +02:00
Write code update
Implemented better defaulting of zlib settings based on image properties. Implemented pass-through of png_write_rows when the rows can be used directly (a common case) optimizing the handling of previous-row buffering. Removed the METHODICAL filter selection method and disabled the HEURISTIC one; the first was ridiculously slow (though useful for experiments) the second doesn't work. Filter selection is temporarily disabled (it defaults to the lowest numbered filter in the list; typically 'none'). New handling of compression settings (incomplete), new PNG compression level (not yet visible in an API). Back ported 'PNG_FAST_FILTERS' from 1.6 (in png.h). There are minimal API changes beyond removal of the selection options. Work is still to be done to investigate a filter selection mechanism that is at least as good as the previous one. Signed-off-by: John Bowler <jbowler@acm.org>
This commit is contained in:
parent
1fd42d849d
commit
cde9b583a8
@ -1609,10 +1609,10 @@ read_png(struct display *dp, const char *filename)
|
||||
png_alloc_size_t rb = png_get_rowbytes(dp->read_pp, dp->ip);
|
||||
|
||||
/* The size calc can overflow. */
|
||||
if (MAX_SIZE/rb < dp->h)
|
||||
if ((MAX_SIZE-dp->h)/rb < dp->h)
|
||||
png_error(dp->read_pp, "image too large");
|
||||
|
||||
dp->size = rb * dp->h;
|
||||
dp->size = rb * dp->h + dp->h/*filter byte*/;
|
||||
}
|
||||
|
||||
display_clean_read(dp);
|
||||
@ -1826,18 +1826,21 @@ write_png(struct display *dp, const char *destname)
|
||||
static void
|
||||
set_windowBits_hi(struct display *dp)
|
||||
{
|
||||
/* windowBits is in the range 8..15, but it is said that setting '8'
|
||||
* prevents adequate search even if the image size is 256 bytes or less.
|
||||
/* windowBits is in the range 8..15 but zlib maps '8' to '9' so it is only
|
||||
* worth using if the data size is 256 byte or less.
|
||||
*/
|
||||
int wb = MAX_WBITS; /* for large images */
|
||||
int i = VLSIZE(windowBits_IDAT);
|
||||
|
||||
while (wb > 9 && dp->size <= 1U<<(wb-1)) --wb;
|
||||
while (wb > 8 && dp->size <= 1U<<(wb-1)) --wb;
|
||||
|
||||
while (--i >= 0) if (VLNAME(windowBits_IDAT)[i].name == range_hi) break;
|
||||
|
||||
assert(i > 0); /* vl_windowBits_IDAT always has a RANGE() */
|
||||
assert(i > 1); /* vl_windowBits_IDAT always has a RANGE() */
|
||||
VLNAME(windowBits_IDAT)[i].value = wb;
|
||||
|
||||
assert(VLNAME(windowBits_IDAT)[--i].name == range_lo);
|
||||
VLNAME(windowBits_IDAT)[i].value = wb > 8 ? 9 : 8;
|
||||
}
|
||||
|
||||
static int
|
||||
|
43
png.h
43
png.h
@ -1690,25 +1690,14 @@ PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action,
|
||||
* ignored if SUB is set; this is because these filter pairs are equivalent
|
||||
* when there is no previous row.
|
||||
*
|
||||
* 2) PNG_SELECT_FILTER_METHODICALLY_SUPPORTED:
|
||||
* If SELECT_FILTER_METHODICALLY is 'on' libpng tries all the filters in the
|
||||
* list and selects the one which gives the shortest compressed row, favoring
|
||||
* earlier filters.
|
||||
* 2) PNG_SELECT_FILTER_SUPPORTED:
|
||||
* libpng will buffer rows until enough data is available to perform a
|
||||
* reasonable filter selection heuristic then select filters for at least the
|
||||
* first buffered row.
|
||||
*
|
||||
* 3) PNG_SELECT_FILTER_HEURISTICALLY_SUPPORTED:
|
||||
* If SELECT_FILTER_HEURISTICALLY is 'on' libpng tests the start of each row
|
||||
* (a few thousand bytes at most) to see which filter is likely to produce
|
||||
* best compression.
|
||||
*
|
||||
* 4) If neither (2) nor (3) libpng selects the first filter in the list (there
|
||||
* is no warning that this will happen - check the #defines if you need to
|
||||
* know.)
|
||||
*
|
||||
* The seletion options are turned 'on' using png_set_option(method,
|
||||
* PNG_OPTION_ON) and turned off with PNG_OPTION_OFF. If a selection method is
|
||||
* turned off it will never be used, if neither option is turned on or off (i.e.
|
||||
* if png_set_option is not called) the first supported option (2) or (3) will
|
||||
* be used.
|
||||
* 3) !PNG_SELECT_FILTER_SUPPORTED:
|
||||
* libpng selects the first filter in the list (there is no warning that this
|
||||
* will happen - check the #defines if you need to know.)
|
||||
*
|
||||
* If you intend to use 'previous row' filters in an image set either the UP or
|
||||
* PAETH filter before the first call to png_write_row, depending on whether you
|
||||
@ -1717,12 +1706,6 @@ PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action,
|
||||
* You can also select AVG on the first row; it uses half the value of the
|
||||
* preceding byte as a predictor and is not likely to have very good
|
||||
* performance.
|
||||
*
|
||||
* The SELECT_FILTER_METHODICALLY option is slow and memory intensive, but it is
|
||||
* almost certain to produce the smallest PNG file. Depending on the image data
|
||||
* the HEURISTIC option may improve results significantly over the NONE filter
|
||||
* and it has little overall effect on compression speed, however it can
|
||||
* sometimes produce larger files than not using any filtering.
|
||||
*/
|
||||
PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
|
||||
int filters));
|
||||
@ -1752,12 +1735,12 @@ PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
|
||||
#define PNG_FILTER_AVG PNG_FILTER_MASK(PNG_FILTER_VALUE_AVG)
|
||||
#define PNG_FILTER_PAETH PNG_FILTER_MASK(PNG_FILTER_VALUE_PAETH)
|
||||
|
||||
/* Then two convenience values. PNG_NO_FILTERS is the same as
|
||||
/* Then three convenience values. PNG_NO_FILTERS is the same as
|
||||
* PNG_FILTER_VALUE_NONE, but this is harmless because they mean the same thing.
|
||||
*/
|
||||
#define PNG_NO_FILTERS 0x00
|
||||
#define PNG_ALL_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP | \
|
||||
PNG_FILTER_AVG | PNG_FILTER_PAETH)
|
||||
#define PNG_NO_FILTERS 0x00
|
||||
#define PNG_FAST_FILTERS (PNG_FILTER_NONE | PNG_FILTER_SUB | PNG_FILTER_UP)
|
||||
#define PNG_ALL_FILTERS (PNG_FAST_FILTERS | PNG_FILTER_AVG | PNG_FILTER_PAETH)
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */
|
||||
@ -3629,9 +3612,7 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
|
||||
#define PNG_EXTENSIONS 0 /* BOTH: enable or disable extensions */
|
||||
#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */
|
||||
#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */
|
||||
#define PNG_SELECT_FILTER_HEURISTICALLY 6 /* SOFTWARE: see png_set_filter */
|
||||
#define PNG_SELECT_FILTER_METHODICALLY 8 /* SOFTWARE: see png_set_filter */
|
||||
#define PNG_OPTION_NEXT 10 /* Next option - numbers must be even */
|
||||
#define PNG_OPTION_NEXT 6 /* Next option - numbers must be even */
|
||||
|
||||
/* Return values: NOTE: there are four values and 'off' is *not* zero */
|
||||
#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */
|
||||
|
22
pngpriv.h
22
pngpriv.h
@ -1080,10 +1080,6 @@ PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr,
|
||||
PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr,
|
||||
png_const_voidp ptr, png_size_t length),PNG_EMPTY);
|
||||
|
||||
#ifdef PNG_WRITE_FLUSH_SUPPORTED
|
||||
PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY);
|
||||
#endif
|
||||
|
||||
/* Write various chunks */
|
||||
|
||||
/* Write the IHDR chunk, and update the png_struct with the necessary
|
||||
@ -1199,9 +1195,9 @@ PNG_INTERNAL_FUNCTION(void,png_write_sCAL_s,(png_structrp png_ptr,
|
||||
#endif
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
/* Initialize the row compression mechanism. */
|
||||
PNG_INTERNAL_FUNCTION(void, png_write_start_IDAT, (png_structp png_ptr),
|
||||
PNG_EMPTY);
|
||||
PNG_INTERNAL_FUNCTION(void,png_write_start_IDAT,(png_structrp png_ptr),
|
||||
PNG_EMPTY);
|
||||
/* Do any required initialization before IDAT or row processing starts. */
|
||||
|
||||
/* Choose the best filter to use and filter the row data then write it out. If
|
||||
* WRITE_FILTERING is not supported this just writes the data out with a zero
|
||||
@ -1226,11 +1222,21 @@ enum
|
||||
# define PNG_IDAT_END(f) (((f) & ~png_pass_first_row) == \
|
||||
(png_row_end+png_pass_last_row+png_pass_last))
|
||||
};
|
||||
PNG_INTERNAL_FUNCTION(void, png_write_filter_row, (png_structrp png_ptr,
|
||||
PNG_INTERNAL_FUNCTION(void,png_write_png_data,(png_structrp png_ptr,
|
||||
png_bytep prev_pixels, png_const_bytep unfiltered_row, png_uint_32 x,
|
||||
unsigned int width/*pixels*/, unsigned int row_info_flags),
|
||||
PNG_EMPTY);
|
||||
|
||||
PNG_INTERNAL_FUNCTION(void,png_write_png_rows,(png_structrp png_ptr,
|
||||
png_const_bytep *rows, png_uint_32 num_rows), PNG_EMPTY);
|
||||
/* As above but rows[num_rows] of correctly (PNG) formated but unfiltered
|
||||
* data are passed in. For an interlaced image the rows will be interlaced
|
||||
* rows and therefore may be narrower than the image width.
|
||||
*
|
||||
* This function advances png_structp::pass and png_structp::row_number as
|
||||
* required.
|
||||
*/
|
||||
|
||||
/* Release memory used by the deflate mechanism */
|
||||
PNG_INTERNAL_FUNCTION(void, png_deflate_destroy, (png_structp png_ptr),
|
||||
PNG_EMPTY);
|
||||
|
67
pngstruct.h
67
pngstruct.h
@ -26,14 +26,14 @@
|
||||
#ifndef ZLIB_CONST
|
||||
/* We must ensure that zlib uses 'const' in declarations. */
|
||||
# define ZLIB_CONST
|
||||
#endif
|
||||
#endif /* !ZLIB_CONST */
|
||||
|
||||
#include PNG_ZLIB_HEADER
|
||||
|
||||
#ifdef const
|
||||
/* zlib.h sometimes #defines const to nothing, undo this. */
|
||||
# undef const
|
||||
#endif
|
||||
#endif /* const */
|
||||
|
||||
/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility
|
||||
* with older builds.
|
||||
@ -41,10 +41,10 @@
|
||||
#if ZLIB_VERNUM < 0x1260
|
||||
# define PNGZ_MSG_CAST(s) png_constcast(char*,s)
|
||||
# define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b)
|
||||
#else
|
||||
#else /* ZLIB_VERNUM >= 0x1260 */
|
||||
# define PNGZ_MSG_CAST(s) (s)
|
||||
# define PNGZ_INPUT_CAST(b) (b)
|
||||
#endif
|
||||
#endif /* ZLIB_VERNUM >= 0x1260 */
|
||||
|
||||
/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib
|
||||
* can handle at once. This type need be no larger than 16 bits (so maximum of
|
||||
@ -57,17 +57,17 @@
|
||||
#ifndef ZLIB_IO_MAX
|
||||
# ifdef __COVERITY__
|
||||
# define ZLIB_IO_MAX ((uInt)255U) /* else COVERITY whines */
|
||||
# else
|
||||
# else /* !COVERITY */
|
||||
# define ZLIB_IO_MAX ((uInt)-1)
|
||||
# endif /* COVERITY */
|
||||
#endif
|
||||
# endif /* !COVERITY */
|
||||
#endif /* !ZLIB_IO_MAX */
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
/* The write compression control (allocated on demand).
|
||||
* TODO: use this for the read state too.
|
||||
*/
|
||||
typedef struct png_zlib_state *png_zlib_statep;
|
||||
#endif
|
||||
#endif /* WRITE */
|
||||
|
||||
/* Colorspace support; structures used in png_struct, png_info and in internal
|
||||
* functions to hold and communicate information about the color space.
|
||||
@ -114,13 +114,13 @@ typedef struct png_colorspace
|
||||
{
|
||||
#ifdef PNG_GAMMA_SUPPORTED
|
||||
png_fixed_point gamma; /* File gamma */
|
||||
#endif
|
||||
#endif /* GAMMA */
|
||||
|
||||
#ifdef PNG_COLORSPACE_SUPPORTED
|
||||
png_xy end_points_xy; /* End points as chromaticities */
|
||||
png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */
|
||||
png_uint_16 rendering_intent; /* Rendering intent of a profile */
|
||||
#endif
|
||||
#endif /* COLORSPACE */
|
||||
|
||||
/* Flags are always defined to simplify the code. */
|
||||
png_uint_16 flags; /* As defined below */
|
||||
@ -182,7 +182,7 @@ typedef struct
|
||||
* during PNG_TC_INIT_FINAL. The field is only used on read; write
|
||||
* transforms do not modify the gamma of the data.
|
||||
*/
|
||||
# endif
|
||||
# endif /* READ_GAMMA */
|
||||
unsigned int format; /* As pngstruct::row_format below */
|
||||
unsigned int range; /* Count of range transforms */
|
||||
# define PNG_TC_CHANNELS(tc) PNG_FORMAT_CHANNELS((tc).format)
|
||||
@ -364,7 +364,7 @@ struct png_struct_def
|
||||
* accessed.)
|
||||
*/
|
||||
jmp_buf jmp_buf_local;
|
||||
#endif
|
||||
#endif /* SETJMP */
|
||||
|
||||
/* Next the frequently accessed fields. Many processors perform arithmetic
|
||||
* in the address pipeline, but frequently the amount of addition or
|
||||
@ -420,7 +420,7 @@ struct png_struct_def
|
||||
/* Options */
|
||||
#ifdef PNG_SET_OPTION_SUPPORTED
|
||||
png_uint_32 options; /* On/off state (up to 16 options) */
|
||||
#endif
|
||||
#endif /* SET_OPTIONS */
|
||||
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
|
||||
@ -428,13 +428,13 @@ struct png_struct_def
|
||||
* is in (just) the info_struct.
|
||||
*/
|
||||
png_colorspace colorspace;
|
||||
#endif
|
||||
#endif /* COLORSPACE || GAMMA */
|
||||
#endif /* READ */
|
||||
|
||||
/* Transform handling */
|
||||
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
|
||||
png_transformp transform_list; /* List of transformation to perform. */
|
||||
#endif
|
||||
#endif /* TRANSFORM_MECH */
|
||||
|
||||
/* ROW BUFFERS and CONTROL
|
||||
*
|
||||
@ -442,9 +442,9 @@ struct png_struct_def
|
||||
* filter byte (which is in next_filter.) All fields are only used during
|
||||
* IDAT processing and start of 0.
|
||||
*/
|
||||
#if defined(PNG_WRITE_FILTER_SUPPORTED) || defined(PNG_READ_SUPPORTED)
|
||||
#ifdef PNG_READ_SUPPORTED
|
||||
png_bytep row_buffer; /* primary row buffer */
|
||||
#endif /* WRITE_FILTER || READ */
|
||||
#endif /* READ */
|
||||
#if (defined(PNG_PROGRESSIVE_READ_SUPPORTED) ||\
|
||||
defined(PNG_READ_INTERLACING_SUPPORTED)) &&\
|
||||
defined(PNG_TRANSFORM_MECH_SUPPORTED)
|
||||
@ -482,10 +482,12 @@ struct png_struct_def
|
||||
unsigned int invalid_info; /* PNG_INFO_* for invalidated chunks */
|
||||
unsigned int palette_updated:1; /* png_struct::palette changed */
|
||||
#endif /* READ_TRANSFORMS */
|
||||
|
||||
#ifdef PNG_WRITE_SUPPORTED
|
||||
unsigned int write_rows :1; /* libpng has complete rows to write */
|
||||
#endif /* WRITE */
|
||||
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
|
||||
unsigned int read_started :1; /* at least one call to png_read_row */
|
||||
#endif
|
||||
#endif /* SEQUENTIAL_READ */
|
||||
#if defined (PNG_READ_INTERLACING_SUPPORTED) ||\
|
||||
defined (PNG_WRITE_INTERLACING_SUPPORTED)
|
||||
unsigned int do_interlace :1; /* libpng handles the interlace */
|
||||
@ -574,7 +576,7 @@ struct png_struct_def
|
||||
* available to zlib during read decompression.
|
||||
*/
|
||||
png_alloc_size_t read_buffer_size; /* current size of the buffer */
|
||||
#endif
|
||||
#endif /* READ */
|
||||
|
||||
#if defined(PNG_SEQUENTIAL_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
|
||||
png_uint_32 IDAT_size; /* limit on IDAT read and write IDAT size */
|
||||
@ -585,13 +587,13 @@ struct png_struct_def
|
||||
jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */
|
||||
png_longjmp_ptr longjmp_fn; /* setjmp non-local goto function. */
|
||||
size_t jmp_buf_size; /* size of *jmp_buf_ptr, if allocated */
|
||||
#endif
|
||||
#endif /* SETJMP */
|
||||
|
||||
/* Error/warning callbacks */
|
||||
png_error_ptr error_fn; /* print an error message and abort */
|
||||
#ifdef PNG_WARNINGS_SUPPORTED
|
||||
png_error_ptr warning_fn; /* print a warning and continue */
|
||||
#endif
|
||||
#endif /* WARNINGS */
|
||||
png_voidp error_ptr; /* user supplied data for the above */
|
||||
|
||||
/* MEMORY ALLOCATION */
|
||||
@ -599,7 +601,7 @@ struct png_struct_def
|
||||
png_malloc_ptr malloc_fn; /* allocate memory */
|
||||
png_free_ptr free_fn; /* free memory */
|
||||
png_voidp mem_ptr; /* user supplied data for the above */
|
||||
#endif
|
||||
#endif /* USER_MEM */
|
||||
|
||||
/* IO and BASIC READ/WRITE SUPPORT */
|
||||
png_voidp io_ptr; /* user supplied data for IO callbacks */
|
||||
@ -622,8 +624,7 @@ struct png_struct_def
|
||||
|
||||
#ifdef PNG_WRITE_FLUSH_SUPPORTED
|
||||
png_flush_ptr output_flush_fn; /* Function for flushing output */
|
||||
#endif
|
||||
|
||||
#endif /* WRITE_FLUSH */
|
||||
#endif /* WRITE */
|
||||
|
||||
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
|
||||
@ -634,14 +635,14 @@ struct png_struct_def
|
||||
* - it is decremented as memory is allocated.
|
||||
*/
|
||||
png_alloc_size_t user_chunk_malloc_max;
|
||||
#endif
|
||||
#endif /* SET_USER_LIMITS */
|
||||
#ifdef PNG_USER_LIMITS_SUPPORTED
|
||||
/* limit on total *number* of sPLT, text and unknown chunks that can be
|
||||
* stored. 0 means unlimited. This field is a counter - it is decremented
|
||||
* as chunks are encountered.
|
||||
*/
|
||||
png_uint_32 user_chunk_cache_max;
|
||||
#endif
|
||||
#endif /* USER_LIMITS */
|
||||
|
||||
/* The progressive reader gets passed data and calls application handling
|
||||
* functions when appropriate.
|
||||
@ -672,7 +673,7 @@ struct png_struct_def
|
||||
|
||||
#ifdef PNG_IO_STATE_SUPPORTED
|
||||
png_uint_32 io_state; /* tells the app read/write progress */
|
||||
#endif
|
||||
#endif /* IO_STATE */
|
||||
|
||||
/* UNKNOWN CHUNK HANDLING */
|
||||
/* TODO: this is excessively complicated, there are multiple ways of doing
|
||||
@ -686,12 +687,12 @@ struct png_struct_def
|
||||
* set_unknown_chunks interface.)
|
||||
*/
|
||||
png_voidp user_chunk_ptr;
|
||||
#endif
|
||||
#endif /* USER_CHUNKS */
|
||||
|
||||
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
|
||||
/* This is called back from the unknown chunk handling */
|
||||
png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
|
||||
#endif
|
||||
#endif /* READ_USER_CHUNKS */
|
||||
|
||||
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
|
||||
png_uint_32 known_unknown; /* Bit mask of known chunks to be treated as
|
||||
@ -703,7 +704,7 @@ struct png_struct_def
|
||||
* 'known & ~save'.
|
||||
*/
|
||||
# define png_IDATs_skipped(pp) (((pp)->known_unknown & ~(pp)->save_unknown)&1U)
|
||||
#else
|
||||
#else /* !SAVE_UNKNOWN_CHUNKS */
|
||||
# define png_IDATs_skipped(pp) ((pp)->known_unknown & 1U)
|
||||
#endif /* !SAVE_UNKNOWN_CHUNKS */
|
||||
#endif /* HANDLE_AS_UNKNOWN */
|
||||
@ -713,7 +714,7 @@ struct png_struct_def
|
||||
* followed by a PNG_HANDLE_* byte */
|
||||
unsigned int unknown_default :2; /* As PNG_HANDLE_* */
|
||||
unsigned int num_chunk_list; /* Number of entries in the list */
|
||||
#endif
|
||||
#endif /* SET_UNKNOWN_CHUNKS */
|
||||
|
||||
/* COMPRESSION AND DECOMPRESSION SUPPORT.
|
||||
*
|
||||
@ -738,7 +739,7 @@ struct png_struct_def
|
||||
/* MNG SUPPORT */
|
||||
#ifdef PNG_MNG_FEATURES_SUPPORTED
|
||||
unsigned int mng_features_permitted :3;
|
||||
#endif
|
||||
#endif /* MNG_FEATURES */
|
||||
|
||||
/* SCRATCH buffers, used when control returns to the application or a read
|
||||
* loop.
|
||||
|
BIN
pngtest.png
BIN
pngtest.png
Binary file not shown.
Before Width: | Height: | Size: 5.6 KiB After Width: | Height: | Size: 5.6 KiB |
11
pngwio.c
11
pngwio.c
@ -67,18 +67,7 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* This function is called to output any data pending writing (normally
|
||||
* to disk). After png_flush is called, there should be no data pending
|
||||
* writing in any buffers.
|
||||
*/
|
||||
#ifdef PNG_WRITE_FLUSH_SUPPORTED
|
||||
void /* PRIVATE */
|
||||
png_flush(png_structrp png_ptr)
|
||||
{
|
||||
if (png_ptr->output_flush_fn != NULL)
|
||||
png_ptr->output_flush_fn(png_ptr);
|
||||
}
|
||||
|
||||
# ifdef PNG_STDIO_SUPPORTED
|
||||
void PNGCBAPI
|
||||
png_default_flush(png_structp png_ptr)
|
||||
|
416
pngwrite.c
416
pngwrite.c
@ -487,7 +487,8 @@ png_write_end(png_structrp png_ptr, png_inforp info_ptr)
|
||||
*/
|
||||
# ifdef PNG_WRITE_FLUSH_SUPPORTED
|
||||
# ifdef PNG_WRITE_FLUSH_AFTER_IEND_SUPPORTED
|
||||
png_flush(png_ptr);
|
||||
if (png_ptr->output_flush_fn != NULL)
|
||||
png_ptr->output_flush_fn(png_ptr);
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
@ -570,65 +571,6 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
|
||||
}
|
||||
|
||||
|
||||
/* 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_write_rows(png_structrp png_ptr, png_bytepp row,
|
||||
png_uint_32 num_rows)
|
||||
{
|
||||
png_debug(1, "in png_write_rows");
|
||||
|
||||
if (png_ptr == NULL || row == NULL)
|
||||
return;
|
||||
|
||||
/* Loop through the rows */
|
||||
while (num_rows-- > 0)
|
||||
png_write_row(png_ptr, *row++);
|
||||
}
|
||||
|
||||
/* Write the image. You only need to call this function once, even
|
||||
* if you are writing an interlaced image.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_write_image(png_structrp png_ptr, png_bytepp image)
|
||||
{
|
||||
int num_pass; /* pass variables */
|
||||
|
||||
if (png_ptr == NULL || image == NULL)
|
||||
return;
|
||||
|
||||
png_debug(1, "in png_write_image");
|
||||
|
||||
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
|
||||
/* Initialize interlace handling. If image is not interlaced,
|
||||
* this will set pass to 1
|
||||
*/
|
||||
num_pass = png_set_interlace_handling(png_ptr);
|
||||
#else
|
||||
num_pass = 1;
|
||||
|
||||
if (png_ptr->interlaced)
|
||||
{
|
||||
png_app_error(png_ptr, "no interlace support");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Loop through passes */
|
||||
while (num_pass-- > 0)
|
||||
{
|
||||
png_bytepp rp = image; /* points to current row */
|
||||
png_uint_32 num_rows = png_ptr->height;
|
||||
|
||||
/* Loop through image */
|
||||
while (num_rows-- > 0)
|
||||
png_write_row(png_ptr, *rp++);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(PNG_WRITE_INTERLACING_SUPPORTED) ||\
|
||||
defined(PNG_WRITE_TRANSFORMS_SUPPORTED)
|
||||
static void
|
||||
@ -707,10 +649,10 @@ write_row_buffered(png_structrp png_ptr,
|
||||
}
|
||||
# endif /* WRITE_TRANSFORMS */
|
||||
|
||||
/* Call png_write_filter_row to write this block of data, the test on
|
||||
/* Call png_write_png_data to write this block of data, the test on
|
||||
* maxpixels says if this is the final block in the row.
|
||||
*/
|
||||
png_write_filter_row(png_ptr, prev_pixels, pixel_buffer.buffer, x,
|
||||
png_write_png_data(png_ptr, prev_pixels, pixel_buffer.buffer, x,
|
||||
max_pixels, row_info_flags);
|
||||
}
|
||||
}
|
||||
@ -824,47 +766,7 @@ interlace_row_byte(png_const_structrp png_ptr, png_bytep dp, png_const_bytep sp,
|
||||
}
|
||||
#endif /* WRITE_INTERLACING */
|
||||
|
||||
static void
|
||||
write_row_unbuffered(png_structrp png_ptr, png_const_bytep row,
|
||||
unsigned int row_info_flags)
|
||||
{
|
||||
/* Split the row into blocks of the appropriate size: */
|
||||
const unsigned int input_depth = png_ptr->row_input_pixel_depth;
|
||||
unsigned int max_pixels = png_max_pixel_block(png_ptr);
|
||||
png_uint_32 max_bytes = max_pixels;
|
||||
const unsigned int pass = png_ptr->pass;
|
||||
const png_uint_32 width = png_ptr->interlaced == PNG_INTERLACE_NONE ?
|
||||
png_ptr->width : PNG_PASS_COLS(png_ptr->width, pass);
|
||||
png_uint_32 x;
|
||||
png_byte prev_pixels[4*2*2]; /* 2 pixels up to 4 2-byte channels each */
|
||||
|
||||
/* max_pixels is at most 16 bits, input_depth is at most 64, so the product
|
||||
* always fits in 32 bits:
|
||||
*/
|
||||
max_bytes *= input_depth; /* bits */
|
||||
debug(input_depth <= 64 && (max_bytes & 7U) == 0U);
|
||||
max_bytes >>= 3;
|
||||
|
||||
memset(prev_pixels, 0U, sizeof prev_pixels);
|
||||
|
||||
for (x = 0U; x < width; x += max_pixels, row += max_bytes)
|
||||
{
|
||||
if (max_pixels > width - x)
|
||||
{
|
||||
max_bytes = width - x;
|
||||
max_pixels = (unsigned int)/*SAFE*/max_bytes;
|
||||
max_bytes = (max_bytes * input_depth + 7U) >> 3;
|
||||
}
|
||||
|
||||
debug((row_info_flags & png_row_end) == 0U); /* must be set here at end */
|
||||
if (x + max_pixels >= width)
|
||||
row_info_flags |= png_row_end;
|
||||
|
||||
png_write_filter_row(png_ptr, prev_pixels, row, x, max_pixels,
|
||||
row_info_flags);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
|
||||
static void
|
||||
write_row_core(png_structrp png_ptr, png_const_bytep row,
|
||||
unsigned int row_info_flags)
|
||||
@ -880,7 +782,8 @@ write_row_core(png_structrp png_ptr, png_const_bytep row,
|
||||
/* If control reaches this point the intermediate buffer is not required and
|
||||
* the input data can be used unmodified.
|
||||
*/
|
||||
write_row_unbuffered(png_ptr, row, row_info_flags);
|
||||
png_write_png_rows(png_ptr, &row, 1U);
|
||||
PNG_UNUSED(row_info_flags)
|
||||
}
|
||||
|
||||
/* Write a single non-interlaced row. */
|
||||
@ -888,75 +791,53 @@ static void
|
||||
write_row_non_interlaced(png_structrp png_ptr, png_const_bytep row)
|
||||
{
|
||||
const png_uint_32 row_number = png_ptr->row_number+1U;
|
||||
const int last_pass_row = row_number == png_ptr->height;
|
||||
|
||||
/* There is only one pass, so this is the last pass: */
|
||||
write_row_core(png_ptr, row,
|
||||
(row_number == 1U ? png_pass_first_row : 0) |
|
||||
(last_pass_row ? png_pass_last_row : 0) |
|
||||
png_pass_last);
|
||||
const unsigned int row_info_flags =
|
||||
(row_number == 1U ? png_pass_first_row : 0) |
|
||||
(row_number >= png_ptr->height ? png_pass_last_row : 0) |
|
||||
png_pass_last;
|
||||
|
||||
if (!last_pass_row)
|
||||
png_ptr->row_number = row_number;
|
||||
debug(png_ptr->interlaced == PNG_INTERLACE_NONE);
|
||||
|
||||
else
|
||||
{
|
||||
png_ptr->row_number = 0U;
|
||||
png_ptr->pass = 7U;
|
||||
}
|
||||
write_row_core(png_ptr, row, row_info_flags);
|
||||
}
|
||||
|
||||
/* Write a single interlaced row. */
|
||||
static void
|
||||
write_row_interlaced(png_structrp png_ptr, png_const_bytep row)
|
||||
{
|
||||
/* row_number is the row in the pass. The app must only call png_write_row
|
||||
* the correct number of times. 'pass' is set to 7U after the end.
|
||||
*/
|
||||
const png_uint_32 row_number = png_ptr->row_number+1U;
|
||||
unsigned int pass = png_ptr->pass;
|
||||
const int last_pass_row = row_number == PNG_PASS_ROWS(png_ptr->height, pass);
|
||||
const png_uint_32 height = png_ptr->height;
|
||||
const unsigned int pass = png_ptr->pass;
|
||||
const unsigned int row_info_flags =
|
||||
(row_number == 1U ? png_pass_first_row : 0) |
|
||||
(row_number == PNG_PASS_ROWS(height, pass) ? png_pass_last_row : 0) |
|
||||
(pass == PNG_LAST_PASS(png_ptr->width, height) ? png_pass_last : 0);
|
||||
|
||||
write_row_core(png_ptr, row,
|
||||
(row_number == 1U ? png_pass_first_row : 0) |
|
||||
(last_pass_row ? png_pass_last_row : 0) |
|
||||
(pass == PNG_LAST_PASS(png_ptr->width, png_ptr->height) ?
|
||||
png_pass_last : 0));
|
||||
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
|
||||
/* Check that libpng is not doing the interlace: */
|
||||
debug(png_ptr->interlaced != PNG_INTERLACE_NONE &&
|
||||
!png_ptr->do_interlace);
|
||||
# endif /* WRITE_INTERLACING */
|
||||
|
||||
if (!last_pass_row)
|
||||
png_ptr->row_number = row_number;
|
||||
|
||||
else
|
||||
{
|
||||
png_ptr->row_number = 0U;
|
||||
|
||||
do
|
||||
++pass;
|
||||
while (pass < 7U &&
|
||||
!PNG_PASS_IN_IMAGE(png_ptr->width, png_ptr->height, pass));
|
||||
|
||||
png_ptr->pass = 0x7U & pass;
|
||||
}
|
||||
write_row_core(png_ptr, row, row_info_flags);
|
||||
}
|
||||
#endif /* WRITE_TRANSFORMS */
|
||||
|
||||
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
|
||||
/* Interlace a row then write it out. */
|
||||
static int
|
||||
static void
|
||||
interlace_row(png_structrp png_ptr, png_const_bytep row)
|
||||
{
|
||||
/* row_number is in the image, it may not be in the pass and, likewise, the
|
||||
* pass may not exist.
|
||||
*/
|
||||
/* The row may not exist in the image (for this pass). */
|
||||
const png_uint_32 row_number = png_ptr->row_number; /* in image */
|
||||
const unsigned int pass = png_ptr->pass;
|
||||
const int write_row = png_ptr->width > PNG_PASS_START_COL(pass) &&
|
||||
PNG_ROW_IN_INTERLACE_PASS(row_number, pass);
|
||||
|
||||
if (write_row)
|
||||
if (png_ptr->width > PNG_PASS_START_COL(pass) &&
|
||||
PNG_ROW_IN_INTERLACE_PASS(row_number, pass))
|
||||
{
|
||||
const unsigned int row_info_flags =
|
||||
(row_number == PNG_PASS_START_ROW(pass) ?
|
||||
png_pass_first_row : 0) |
|
||||
(row_number == PNG_PASS_START_ROW(pass) ? png_pass_first_row : 0) |
|
||||
(PNG_LAST_PASS_ROW(row_number, pass, png_ptr->height) ?
|
||||
png_pass_last_row : 0) |
|
||||
(pass == PNG_LAST_PASS(png_ptr->width, png_ptr->height) ?
|
||||
@ -991,79 +872,214 @@ interlace_row(png_structrp png_ptr, png_const_bytep row)
|
||||
interlace_row_byte, input_depth >> 3);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} /* pass < 6 */
|
||||
|
||||
else /* pass 6; no interlacing required */
|
||||
else /* pass 6: no interlacing required */
|
||||
write_row_core(png_ptr, row, row_info_flags);
|
||||
}
|
||||
|
||||
if (row_number+1U < png_ptr->height)
|
||||
png_ptr->row_number = row_number+1U;
|
||||
|
||||
else
|
||||
{
|
||||
png_ptr->row_number = 0U;
|
||||
png_ptr->pass = 0x7U & (pass+1U);
|
||||
}
|
||||
/* This code must advance row_number/pass itself; the row has been
|
||||
* skipped.
|
||||
*/
|
||||
if (row_number+1U < png_ptr->height)
|
||||
png_ptr->row_number = row_number+1U;
|
||||
|
||||
return write_row;
|
||||
else
|
||||
{
|
||||
png_ptr->row_number = 0U;
|
||||
png_ptr->pass = 0x7U & (pass+1U);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WRITE_INTERLACING */
|
||||
|
||||
/* Called by user to write a row of image data */
|
||||
void PNGAPI
|
||||
png_write_row(png_structrp png_ptr, png_const_bytep row)
|
||||
/* Bottleneck API to actually write a number of rows, only exists because the
|
||||
* rows parameter to png_write_rows is wrong.
|
||||
*/
|
||||
static void
|
||||
png_write_rows_internal(png_structrp png_ptr, png_const_bytep *rows,
|
||||
png_uint_32 num_rows)
|
||||
{
|
||||
if (png_ptr != NULL)
|
||||
if (png_ptr != NULL && num_rows > 0U && rows != NULL)
|
||||
{
|
||||
const unsigned int pass = png_ptr->pass;
|
||||
const png_uint_32 row_number = png_ptr->row_number;
|
||||
|
||||
/* Unlike the read code initialization happens automatically: */
|
||||
if (row_number == 0 && pass == 0)
|
||||
png_write_start_IDAT(png_ptr); /* doesn't change row/pass/width */
|
||||
if (png_ptr->row_number == 0U && png_ptr->pass == 0U)
|
||||
{
|
||||
png_init_row_info(png_ptr);
|
||||
|
||||
else if (pass == 7U) /* too many calls; write already ended */
|
||||
# ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
|
||||
/* If the app takes a png_info from a read operation and if the app has
|
||||
* performed transforms on the data the png_info can contain IHDR
|
||||
* information that cannot be represented in PNG. The code that writes
|
||||
* the IHDR takes the color type from the png_info::format. The app
|
||||
* adds transforms, before or after writing the IHDR, then the IHDR
|
||||
* color_type stored in png_struct::color_type is used in
|
||||
* png_init_row_info above to work out the actual row format.
|
||||
*
|
||||
* Prior to 1.7.0 this was not verified (there was no easy way to do
|
||||
* so). Now we can check it here, however this is an:
|
||||
*
|
||||
* API CHANGE: in 1.7.0 an error may be flagged against bogus
|
||||
* info_struct formats even though the app had removed them itself.
|
||||
* It's just a warning at present.
|
||||
*
|
||||
* The test is that either the row_format produced by the write
|
||||
* transforms exactly matches that in the original info_struct::format
|
||||
* or that the info_struct::format was a simple mapping of the
|
||||
* color_type that ended up in the IHDR:
|
||||
*/
|
||||
if (png_ptr->row_format != png_ptr->info_format &&
|
||||
PNG_FORMAT_FROM_COLOR_TYPE(png_ptr->color_type) !=
|
||||
png_ptr->info_format)
|
||||
png_app_warning(png_ptr, "info_struct format does not match IHDR");
|
||||
# endif /* WRITE_TRANSFORMS */
|
||||
|
||||
/* Perform initialization required before IDATs are written. */
|
||||
png_write_start_IDAT(png_ptr);
|
||||
}
|
||||
|
||||
else if (png_ptr->pass >= 7U) /* too many calls; write already ended */
|
||||
{
|
||||
debug(png_ptr->row_number == 0U);
|
||||
png_app_error(png_ptr, "Too many calls to png_write_row");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Make sure there is a row to write: */
|
||||
if (row == NULL)
|
||||
{
|
||||
png_app_error(png_ptr, "NULL row pointer to png_write_row");
|
||||
return;
|
||||
}
|
||||
|
||||
if (png_ptr->interlaced == PNG_INTERLACE_NONE)
|
||||
write_row_non_interlaced(png_ptr, row);
|
||||
/* The remainder of these tests detect internal errors in libpng */
|
||||
else if (png_ptr->interlaced == PNG_INTERLACE_NONE)
|
||||
affirm(png_ptr->row_number < png_ptr->height && png_ptr->pass == 0U);
|
||||
|
||||
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
|
||||
/* Optional: libpng does the interlacing, app passes every row of the
|
||||
* image the required number of times.
|
||||
*/
|
||||
else if (png_ptr->do_interlace != 0U)
|
||||
{
|
||||
if (!interlace_row(png_ptr, row))
|
||||
return; /* row skipped; skip the write callback */
|
||||
}
|
||||
# endif
|
||||
else if (png_ptr->do_interlace)
|
||||
affirm(png_ptr->row_number < png_ptr->height);
|
||||
# endif /* WRITE_INTERLACING */
|
||||
|
||||
else /* app does the interlacing */
|
||||
write_row_interlaced(png_ptr, row);
|
||||
else /* app does interlace */
|
||||
affirm(
|
||||
PNG_PASS_IN_IMAGE(png_ptr->width, png_ptr->height, png_ptr->pass) &&
|
||||
png_ptr->row_number < PNG_PASS_ROWS(png_ptr->height, png_ptr->pass)
|
||||
);
|
||||
|
||||
/* API CHANGE: 1.7.0: this is now called after png_struct::row_number and
|
||||
* png_struct::pass have been updated and, at the end of the image, after
|
||||
* the deflate stream has been closed. The order of the call with respect
|
||||
* to the flush operation has also changed. The callback can't discover
|
||||
* any of this unless it relies on the write callbacks to find the row
|
||||
* data, and that was never predictable.
|
||||
/* First handle rows that require buffering because of the need to
|
||||
* interlace them or the need to perform write transforms.
|
||||
*/
|
||||
if (png_ptr->write_row_fn != NULL)
|
||||
(*(png_ptr->write_row_fn))(png_ptr, row_number, pass);
|
||||
} /* png_ptr != NULL */
|
||||
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
|
||||
/* libpng is doing the interlacing, but this only makes a difference to
|
||||
* the first six passes (numbered, in libpng, 0..5); the seventh pass
|
||||
* (numbered 6 by libpng) consists of complete image rows.
|
||||
*/
|
||||
if (png_ptr->do_interlace) while (num_rows > 0U && png_ptr->pass < 6)
|
||||
interlace_row(png_ptr, *rows++), --num_rows;
|
||||
# endif /* WRITE_INTERLACING */
|
||||
|
||||
# ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
|
||||
/* Transforms required however the row interlacing has already been
|
||||
* handled and we have a complete (PNG) row.
|
||||
*/
|
||||
if (png_ptr->transform_list != NULL)
|
||||
{
|
||||
if (png_ptr->interlaced == PNG_INTERLACE_NONE)
|
||||
while (num_rows > 0U)
|
||||
write_row_non_interlaced(png_ptr, *rows++), --num_rows;
|
||||
|
||||
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
|
||||
else if (png_ptr->do_interlace)
|
||||
while (num_rows > 0U)
|
||||
interlace_row(png_ptr, *rows++), --num_rows;
|
||||
# endif /* WRITE_INTERLACING */
|
||||
|
||||
else /* app does the interlacing */
|
||||
while (num_rows > 0U)
|
||||
write_row_interlaced(png_ptr, *rows++), --num_rows;
|
||||
}
|
||||
# endif /* WRITE_TRANSFORMS */
|
||||
|
||||
/* Finally handle any remaining rows that require no (libpng) interlace
|
||||
* and no transforms.
|
||||
*/
|
||||
if (num_rows > 0U)
|
||||
png_write_png_rows(png_ptr, rows, num_rows);
|
||||
|
||||
/* Repeat the checks above, but allow for end-of-image. */
|
||||
if (png_ptr->pass < 7U)
|
||||
{
|
||||
if (png_ptr->interlaced == PNG_INTERLACE_NONE)
|
||||
affirm(png_ptr->row_number < png_ptr->height &&
|
||||
png_ptr->pass == 0U);
|
||||
|
||||
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
|
||||
else if (png_ptr->do_interlace)
|
||||
affirm(png_ptr->row_number < png_ptr->height);
|
||||
# endif /* WRITE_INTERLACING */
|
||||
|
||||
else /* app does interlace */
|
||||
affirm(PNG_PASS_IN_IMAGE(png_ptr->width, png_ptr->height,
|
||||
png_ptr->pass) &&
|
||||
png_ptr->row_number <
|
||||
PNG_PASS_ROWS(png_ptr->height, png_ptr->pass));
|
||||
}
|
||||
} /* png_ptr, rows, num_rows all valid */
|
||||
|
||||
else if (png_ptr != NULL)
|
||||
png_app_warning(png_ptr, "Missing rows to row write API");
|
||||
}
|
||||
|
||||
/* ROW WRITE APIs */
|
||||
/* Called by user to write a single row of image data */
|
||||
void PNGAPI
|
||||
png_write_row(png_structrp png_ptr, png_const_bytep row)
|
||||
{
|
||||
png_debug(1, "in png_write_row");
|
||||
png_write_rows_internal(png_ptr, &row, 1U);
|
||||
}
|
||||
|
||||
/* 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_write_rows(png_structrp png_ptr, png_bytepp rows, png_uint_32 num_rows)
|
||||
{
|
||||
png_debug(1, "in png_write_rows");
|
||||
|
||||
if (png_ptr != NULL)
|
||||
png_write_rows_internal(png_ptr, png_constcast(png_const_bytep*,rows),
|
||||
num_rows);
|
||||
}
|
||||
|
||||
/* Write the image. You only need to call this function once, even
|
||||
* if you are writing an interlaced image.
|
||||
*/
|
||||
void PNGAPI
|
||||
png_write_image(png_structrp png_ptr, png_bytepp image)
|
||||
{
|
||||
png_debug(1, "in png_write_image");
|
||||
|
||||
if (png_ptr != NULL)
|
||||
{
|
||||
int num_pass = 1;
|
||||
|
||||
/* The image is always an non-interlaced image. To write it as interlaced
|
||||
* interlace handling must be present:
|
||||
*/
|
||||
if (png_ptr->interlaced)
|
||||
{
|
||||
# ifdef PNG_WRITE_INTERLACING_SUPPORTED
|
||||
num_pass = png_set_interlace_handling(png_ptr);
|
||||
# else /* !WRITE_INTERLACING */
|
||||
/* There is no recovery because the IHDR has already been written.
|
||||
*/
|
||||
png_error(png_ptr, "No interlace support");
|
||||
# endif /* !WRITE_INTERLACING */
|
||||
}
|
||||
|
||||
/* And write the whole thing, 7 times if interlacing it: */
|
||||
for (; num_pass > 0; --num_pass)
|
||||
png_write_rows(png_ptr, image, png_ptr->height);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free any memory used in png_ptr struct without freeing the struct itself. */
|
||||
@ -1074,10 +1090,6 @@ png_write_destroy(png_structrp png_ptr)
|
||||
|
||||
png_deflate_destroy(png_ptr);
|
||||
|
||||
#ifdef PNG_WRITE_FILTER_SUPPORTED
|
||||
png_free(png_ptr, png_ptr->row_buffer);
|
||||
png_ptr->row_buffer = NULL;
|
||||
#endif /* WRITE_FILTER */
|
||||
#ifdef PNG_TRANSFORM_MECH_SUPPORTED
|
||||
png_transform_free(png_ptr, &png_ptr->transform_list);
|
||||
#endif
|
||||
|
2546
pngwutil.c
2546
pngwutil.c
File diff suppressed because it is too large
Load Diff
@ -930,20 +930,36 @@ option CONVERT_tIME requires WRITE_ANCILLARY_CHUNKS
|
||||
# png_set_filter interface allowing the application to select the filter
|
||||
# used for each row.
|
||||
#
|
||||
# SELECT_FILTER_HEURISTICALLY
|
||||
# Enables code to cause libpng to choose a filter from a set passed to
|
||||
# png_set_filter. Without this code libpng just chooses the first filter in
|
||||
# the list if multiple are given.
|
||||
# SELECT_FILTER
|
||||
# Enables code to select between multiple filters on write. Without this
|
||||
# the 'first' (lowest numbered) filter will be selected an this typically
|
||||
# works out as PNG_FILTER_VALUE_NONE.
|
||||
#
|
||||
# SELECT_FILTER_METHODICALLY
|
||||
# Enables code to try all the filters in the list passed to png_set_filter
|
||||
# and choose the one which results in the least number of compressed bytes
|
||||
# added by the current row.
|
||||
# COMPRESSION_BUFFER_MAX
|
||||
# WARNING: take care if you set this. This is the maximum amount of input
|
||||
# data that the implementation of deflate can consume before it outputs a
|
||||
# Huffman table for that data. I.e. before it commits to an encoding of the
|
||||
# data it has read. This is used solely to implement a limit on the amount
|
||||
# of image data buffering that occurs inside libpng before filter selection
|
||||
# is done. Normally the limit is never reached because of the next setting,
|
||||
# but this is a compile time limit and it is intended to prevent a potential
|
||||
# DNS service as a result of an application setting the libpng equivalent of
|
||||
# volume level 11 (read the wikipedia article on "Up to eleven").
|
||||
#
|
||||
# NOTE: the image of a black cat in a coal mine obviously requires this
|
||||
# limit, but some more valid images can get very close; well over 8MByte.
|
||||
#
|
||||
# COMPRESSION_BUFFER_LIMIT
|
||||
# This is the (overrideable) default for the amount of memory libpng will
|
||||
# buffer before selecting a filter for a row. It is limited itself to
|
||||
# COMPRESSION_BUFFER_MAX as values above that level make no change (see the
|
||||
# previous paragraph.)
|
||||
#
|
||||
# See png.h for more description of these options.
|
||||
option WRITE_FILTER requires WRITE
|
||||
option SELECT_FILTER_HEURISTICALLY requires WRITE_FILTER enables SET_OPTION
|
||||
option SELECT_FILTER_METHODICALLY requires WRITE_FILTER enables SET_OPTION
|
||||
option SELECT_FILTER requires WRITE_FILTER disabled
|
||||
setting COMPRESSION_BUFFER_MAX default 8453377
|
||||
setting COMPRESSION_BUFFER_LIMIT default 8453377
|
||||
|
||||
# added at libpng-1.5.4
|
||||
|
||||
|
@ -1,8 +1,7 @@
|
||||
/* libpng 1.7.0beta80 STANDARD API DEFINITION */
|
||||
|
||||
/* pnglibconf.h - library build configuration */
|
||||
|
||||
/* Libpng version 1.7.0beta80, March 9, 2016 */
|
||||
/* libpng version 1.7.0beta80, March 9, 2016 */
|
||||
|
||||
/* Copyright (c) 1998-2016 Glenn Randers-Pehrson */
|
||||
|
||||
@ -100,8 +99,7 @@
|
||||
#define PNG_READ_tRNS_SUPPORTED
|
||||
#define PNG_READ_zTXt_SUPPORTED
|
||||
#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
|
||||
#define PNG_SELECT_FILTER_HEURISTICALLY_SUPPORTED
|
||||
#define PNG_SELECT_FILTER_METHODICALLY_SUPPORTED
|
||||
/*#undef PNG_SELECT_FILTER_SUPPORTED*/
|
||||
#define PNG_SEQUENTIAL_READ_SUPPORTED
|
||||
#define PNG_SETJMP_SUPPORTED
|
||||
#define PNG_SETTING_SUPPORTED
|
||||
@ -193,6 +191,8 @@
|
||||
/* settings */
|
||||
#define PNG_ABORT { (abort()); }
|
||||
#define PNG_API_RULE 0
|
||||
#define PNG_COMPRESSION_BUFFER_LIMIT 8453377
|
||||
#define PNG_COMPRESSION_BUFFER_MAX 8453377
|
||||
#define PNG_DEFAULT_GAMMA_ACCURACY 665
|
||||
#define PNG_DEFAULT_READ_MACROS 1
|
||||
#define PNG_GAMMA_THRESHOLD_FIXED 153
|
||||
|
Loading…
x
Reference in New Issue
Block a user