compression code unification

Unify the compression code so that inflate calls are localized to a common
routine.  Ground work for filter selection support.  Minor API changes to use
void* not byte* for data parameters.  Unification of some of the compression
code with the decompression code; IDAT_size replaces IDAT_read_size and
zbuffer_size, IDAT reading and writing is no longer controlled by the size of
the compression buffer.

Signed-off-by: John Bowler <jbowler@acm.org>
This commit is contained in:
John Bowler 2015-11-30 13:39:49 -08:00
parent 6bbc74d880
commit 4792c8a751
15 changed files with 609 additions and 537 deletions

9
png.c
View File

@ -112,7 +112,7 @@ png_reset_crc(png_structrp png_ptr)
* trouble of calculating it.
*/
void /* PRIVATE */
png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length)
png_calculate_crc(png_structrp png_ptr, png_const_voidp ptr, png_size_t length)
{
int need_crc = 1;
@ -137,6 +137,7 @@ png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length)
if (need_crc != 0 && length > 0)
{
uLong crc = png_ptr->crc; /* Should never issue a warning */
const Bytef* rptr = png_voidcast(const Bytef*,ptr);
do
{
@ -151,19 +152,19 @@ png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length)
else
safe_length = (uInt)/*SAFE*/length;
crc = crc32(crc, ptr, safe_length);
crc = crc32(crc, PNGZ_INPUT_CAST(rptr), safe_length);
/* The following should never issue compiler warnings; if they do the
* target system has characteristics that will probably violate other
* assumptions within the libpng code.
*/
ptr += safe_length;
rptr += safe_length;
length -= safe_length;
}
while (length > 0);
/* And the following is always safe because the crc is only 32 bits. */
png_ptr->crc = (png_uint_32)crc;
png_ptr->crc = 0xFFFFFFFFU & crc;
}
}

6
png.h
View File

@ -1150,8 +1150,8 @@ PNG_EXPORTA(12, png_structp, png_create_write_struct_2,
PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr));
/* Write a PNG chunk - size, type, (optional) data, CRC. */
PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep
chunk_name, png_const_bytep data, size_t length));
PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr,
png_const_bytep chunk_name, png_const_voidp data, size_t length));
/* Write the start of a PNG chunk - length and chunk name. */
PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr,
@ -1159,7 +1159,7 @@ PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr,
/* Write the data of a PNG chunk started with png_write_chunk_start(). */
PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr,
png_const_bytep data, size_t length));
png_const_voidp data, size_t length));
/* Finish a chunk started with png_write_chunk_start() (includes CRC). */
PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr));

View File

@ -1150,26 +1150,11 @@ png_get_compression_buffer_size(png_const_structrp png_ptr)
if (png_ptr == NULL)
return 0;
#ifdef PNG_WRITE_SUPPORTED
if (png_ptr->read_struct)
{
# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
return png_ptr->IDAT_read_size;
# else
return PNG_IDAT_READ_SIZE;
# endif
}
else
return png_ptr->zbuffer_size;
#else /* !WRITE */
# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
return png_ptr->IDAT_read_size;
# else
return PNG_IDAT_READ_SIZE;
# endif
#endif /* WRITE */
# if defined(PNG_SEQUENTIAL_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
return png_ptr->IDAT_size;
# else
return PNG_IDAT_READ_SIZE; /* progressive reader */
# endif
}
#ifdef PNG_SET_USER_LIMITS_SUPPORTED

View File

@ -97,7 +97,6 @@ struct png_info_def
/* iCCP chunk data. */
png_charp iccp_name; /* profile name */
png_bytep iccp_profile; /* International Color Consortium profile data */
png_uint_32 iccp_proflen; /* ICC profile data length */
#endif
#ifdef PNG_TEXT_SUPPORTED
@ -215,7 +214,7 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
/* Storage for unknown chunks that the library doesn't recognize. */
png_unknown_chunkp unknown_chunks;
/* The type of this field is limited by the type of
/* The type of this field is limited by the type of
* png_struct::user_chunk_cache_max, else overflow can occur.
*/
int unknown_chunks_num;

View File

@ -458,9 +458,9 @@
/* Just a little check that someone hasn't tried to define something
* contradictory.
*/
#if (PNG_ZBUF_SIZE > 65536L) && defined(PNG_MAX_MALLOC_64K)
#if (PNG_ZBUF_SIZE > 32768) && defined(PNG_MAX_MALLOC_64K)
# undef PNG_ZBUF_SIZE
# define PNG_ZBUF_SIZE 65536L
# define PNG_ZBUF_SIZE 32768
#endif
/* If warnings or errors are turned off the code is disabled or redirected here.
@ -1057,18 +1057,18 @@ PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY);
/* Write the "data" buffer to whatever output you are using */
PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr,
png_const_bytep data, png_size_t length),PNG_EMPTY);
png_const_voidp data, png_size_t length),PNG_EMPTY);
/* Read and check the PNG file signature */
PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr,
png_inforp info_ptr),PNG_EMPTY);
/* Read data from whatever input you are using into the "data" buffer */
PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data,
PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_voidp data,
png_size_t length),PNG_EMPTY);
/* Read bytes into buf, and update png_ptr->crc */
PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf,
PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_voidp buf,
png_uint_32 length),PNG_EMPTY);
/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */
@ -1080,7 +1080,7 @@ PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr,
* since this is the maximum buffer size we can specify.
*/
PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr,
png_const_bytep ptr, png_size_t length),PNG_EMPTY);
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);
@ -1123,7 +1123,7 @@ PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr,
#ifdef PNG_WRITE_iCCP_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr,
png_const_charp name, png_const_bytep profile), PNG_EMPTY);
png_const_charp name, png_const_voidp profile), PNG_EMPTY);
/* The profile must have been previously validated for correctness, the
* length comes from the first four bytes. Only the base, deflate,
* compression is supported.
@ -1259,7 +1259,7 @@ PNG_INTERNAL_FUNCTION(void,png_run_transform_list_backwards,
*/
#endif /* WRITE */
PNG_INTERNAL_FUNCTION(png_transformp,png_add_transform,(png_structrp png_ptr,
PNG_INTERNAL_FUNCTION(png_transformp,png_add_transform,(png_structrp png_ptr,
size_t size, png_transform_fn fn, unsigned int order),PNG_EMPTY);
/* Add a transform, using the information in 'order' to control the position
* of the transform in the list, returning a pointer to the transform. The
@ -1506,7 +1506,7 @@ PNG_INTERNAL_FUNCTION(png_transformp,png_add_transform,(png_structrp png_ptr,
* PNG_RWTR_USER PI W1
*/
PNG_INTERNAL_FUNCTION(png_transformp,png_push_transform,(png_structrp png_ptr,
PNG_INTERNAL_FUNCTION(png_transformp,png_push_transform,(png_structrp png_ptr,
size_t size, png_transform_fn fn, png_transformp *transform,
png_transform_controlp tc),PNG_EMPTY);
/* As png_add_transform except that the new transform is inserted ahead of

View File

@ -123,7 +123,7 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
* required (it will be zero in a write structure.)
*/
# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE;
png_ptr->IDAT_size = PNG_IDAT_READ_SIZE;
# endif /* SEQUENTIAL_READ */
# ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED
@ -308,17 +308,17 @@ png_start_read_image(png_structrp png_ptr)
static void
png_read_IDAT(png_structrp png_ptr)
{
/* Read more input data, up to png_struct::IDAT_read_size, stop at the
/* Read more input data, up to png_struct::IDAT_size, stop at the
* end of the IDAT stream:
*/
uInt IDAT_size = 0;
png_bytep buffer =
png_read_buffer(png_ptr, png_ptr->IDAT_read_size, 0/*error*/);
png_read_buffer(png_ptr, png_ptr->IDAT_size, 0/*error*/);
png_ptr->zstream.next_in = buffer;
while (png_ptr->chunk_name == png_IDAT &&
IDAT_size < png_ptr->IDAT_read_size)
IDAT_size < png_ptr->IDAT_size)
{
png_uint_32 l = png_ptr->chunk_length;
@ -336,10 +336,10 @@ png_read_IDAT(png_structrp png_ptr)
l = png_ptr->chunk_length;
}
/* Read from the IDAT chunk into the buffer, up to IDAT_read_size:
/* Read from the IDAT chunk into the buffer, up to png_struct::IDAT_size:
*/
if (l > png_ptr->IDAT_read_size - IDAT_size) /* SAFE: while check */
l = png_ptr->IDAT_read_size - IDAT_size;
if (l > png_ptr->IDAT_size - IDAT_size) /* SAFE: while check */
l = png_ptr->IDAT_size - IDAT_size;
png_crc_read(png_ptr, buffer+IDAT_size, l);
IDAT_size += /*SAFE*/l;

View File

@ -30,12 +30,12 @@
* to read more than 64K on a 16 bit machine.
*/
void /* PRIVATE */
png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length)
png_read_data(png_structrp png_ptr, png_voidp data, png_size_t length)
{
png_debug1(4, "reading %d bytes", (int)length);
if (png_ptr->rw_data_fn != NULL)
png_ptr->rw_data_fn(png_ptr, data, length);
png_ptr->rw_data_fn(png_ptr, png_voidcast(png_bytep,data), length);
else
png_app_error(png_ptr, "No read function");

View File

@ -129,7 +129,7 @@ png_read_sig(png_structrp png_ptr, png_inforp info_ptr)
/* Read data, and (optionally) run it through the CRC. */
void /* PRIVATE */
png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length)
png_crc_read(png_structrp png_ptr, png_voidp buf, png_uint_32 length)
{
if (png_ptr == NULL)
return;
@ -1382,8 +1382,6 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr)
{
memcpy(info_ptr->iccp_name, keyword,
keyword_length+1);
info_ptr->iccp_proflen =
profile_length;
info_ptr->iccp_profile = profile;
png_ptr->read_buffer = NULL; /*steal*/
info_ptr->free_me |= PNG_FREE_ICCP;

View File

@ -676,7 +676,6 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
info_ptr->iccp_proflen = proflen;
info_ptr->iccp_name = new_iccp_name;
info_ptr->iccp_profile = new_iccp_profile;
info_ptr->free_me |= PNG_FREE_ICCP;
@ -1531,59 +1530,15 @@ png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
void PNGAPI
png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
{
if (png_ptr == NULL)
return;
if (png_ptr == NULL)
return;
if (size == 0 || size > PNG_UINT_31_MAX)
png_error(png_ptr, "invalid compression buffer size");
if (size == 0 || size > PNG_UINT_31_MAX)
png_error(png_ptr, "invalid compression buffer size");
# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
if (png_ptr->read_struct)
{
png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
return;
}
# endif /* SEQUENTIAL_READ */
# ifdef PNG_WRITE_SUPPORTED
if (!png_ptr->read_struct)
{
if (png_ptr->zowner != 0)
{
png_warning(png_ptr,
"Compression buffer size cannot be changed because it is in use");
return;
}
/* NOTE: size is limited to 0..PNG_UINT_31_MAX (2^31-1) at this point,
* however ZLIB_IO_MAX may be smaller (for example on a 16-bit system).
*/
if (size > ZLIB_IO_MAX)
{
png_warning(png_ptr,
"Compression buffer size limited to system maximum");
size = ZLIB_IO_MAX; /* must fit */
}
if (size < 6)
{
/* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
* if this is permitted.
*/
png_warning(png_ptr,
"Compression buffer size cannot be reduced below 6");
return;
}
if (png_ptr->zbuffer_size != size)
{
png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
png_ptr->zbuffer_size = (uInt)size;
}
}
# endif /* WRITE */
# if (defined PNG_SEQUENTIAL_READ_SUPPORTED) || defined PNG_WRITE_SUPPORTED
png_ptr->IDAT_size = (uInt)/*SAFE*/size;
# endif /* SEQUENTIAL_READ || WRITE */
}
void PNGAPI

View File

@ -569,15 +569,15 @@ struct png_struct_def
#endif /* TRANFORM_MECH */
#ifdef PNG_READ_SUPPORTED
/* These, and IDAT_read_size below, control how much input and output (at
* most) is available to zlib.
/* These, and IDAT_size below, control how much input and output (at most) is
* available to zlib during read decompression.
*/
png_alloc_size_t read_buffer_size; /* current size of the buffer */
#endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
uInt IDAT_read_size; /* limit on read buffer size for IDAT */
#endif
#if defined(PNG_SEQUENTIAL_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
uInt IDAT_size; /* limit on IDAT read and write IDAT size */
#endif /* SEQUENTIAL_READ || WRITE */
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
int zlib_text_level; /* holds zlib compression level */
@ -600,8 +600,10 @@ struct png_struct_def
int zlib_set_mem_level;
int zlib_set_strategy;
png_compression_bufferp zbuffer_list; /* Created on demand during write */
uInt zbuffer_size; /* size of the actual zlib buffer */
unsigned int zbuffer_start; /* Bytes written from start */
png_uint_32 zbuffer_len; /* Length of data in list */
png_compression_bufferp zbuffer_list; /* Created on demand during write */
png_compression_bufferp *zbuffer_end; /* 'next' field of current buffer */
#endif
/* ERROR HANDLING */

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -31,11 +31,16 @@
*/
void /* PRIVATE */
png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length)
png_write_data(png_structrp png_ptr, png_const_voidp data, png_size_t length)
{
/* NOTE: write_data_fn must not change the buffer! */
/* NOTE: write_data_fn must not change the buffer!
* This cast is required because of the API; changing the type of the
* callback would require every app to change the callback and that change
* would have to be conditional on the libpng version.
*/
if (png_ptr->rw_data_fn != NULL )
png_ptr->rw_data_fn(png_ptr, png_constcast(png_bytep, data), length);
png_ptr->rw_data_fn(png_ptr,
png_constcast(png_bytep,png_voidcast(png_const_bytep,data)), length);
else
png_app_error(png_ptr, "No write function");

View File

@ -523,7 +523,7 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
/* Set the zlib control values to defaults; they can be overridden by the
* application after the struct has been created.
*/
png_ptr->zbuffer_size = PNG_ZBUF_SIZE;
png_ptr->IDAT_size = PNG_ZBUF_SIZE;
/* The 'zlib_strategy' setting is irrelevant because png_default_claim in
* pngwutil.c defaults it according to whether or not filters will be

File diff suppressed because it is too large Load Diff

View File

@ -792,19 +792,13 @@ setting DEFAULT_GAMMA_ACCURACY default 665
setting sCAL_PRECISION default 5
# This is the size of the compression buffer, and thus the size of
# an IDAT chunk. Make this whatever size you feel is best for your
# machine. One of these will be allocated per png_struct. When this
# is full, it writes the data to the disk, and does some other
# calculations. Making this an extremely small size may slow
# the library down, but you may want to experiment to determine
# where it becomes significant, if you are concerned with memory
# usage. Note that zlib allocates at least 32Kb also. For readers,
# this describes the size of the buffer available to read the data in.
# Unless this gets smaller than the size of a row (compressed),
# it should not make much difference how big this is.
# This used to control the size of the IDAT chunks on write and the size of the
# compression buffer used internally. It now solely controls the size of the
# written IDAT chunks. It can be any (zlib) uInt value, however this amount of
# data has to be buffered on write so it is recommended that a smaller size be
# used unless saving the 12-byte chunk overhead is necessary.
setting ZBUF_SIZE default 8192
setting ZBUF_SIZE default 4096
# This is the size of the decompression buffer used when counting or checking
# the decompressed size of an LZ stream from a compressed ancilliary chunk; the
@ -818,17 +812,17 @@ setting ZBUF_SIZE default 8192
setting INFLATE_BUF_SIZE default 1024
# This is the maximum amount of IDAT data that the sequential reader will
# process at one time. The setting does not affect the size of IDAT chunks
# read, just the amount read at once. Neither does it affect the progressive
# reader, which processes just the amount of data the application gives it.
# The sequential reader is currently unable to process more than one IDAT at
# once - it has to read and process each one in turn. There is no point setting
# this to a value larger than the IDAT chunks typically encountered (it would
# just waste memory) but there may be some point in reducing it below the value
# of ZBUF_SIZE (the size of IDAT chunks written by libpng.)
# This is the amount of IDAT data that the sequential reader will process at one
# time. The setting does not affect the size of IDAT chunks read, just the
# amount read at once. Neither does it affect the progressive reader, which
# processes just the amount of data the application gives it.
#
# The sequential reader will read IDAT chunks up to this limit, or the end of
# the chunks, before decompressing the next row. The value should be chosen to
# optimize the PNG data read speed, it has no significant effect on anything
# else.
setting IDAT_READ_SIZE default PNG_ZBUF_SIZE
setting IDAT_READ_SIZE default 4096
# Ancillary chunks
chunk bKGD