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. * trouble of calculating it.
*/ */
void /* PRIVATE */ 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; 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) if (need_crc != 0 && length > 0)
{ {
uLong crc = png_ptr->crc; /* Should never issue a warning */ uLong crc = png_ptr->crc; /* Should never issue a warning */
const Bytef* rptr = png_voidcast(const Bytef*,ptr);
do do
{ {
@ -151,19 +152,19 @@ png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length)
else else
safe_length = (uInt)/*SAFE*/length; 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 /* The following should never issue compiler warnings; if they do the
* target system has characteristics that will probably violate other * target system has characteristics that will probably violate other
* assumptions within the libpng code. * assumptions within the libpng code.
*/ */
ptr += safe_length; rptr += safe_length;
length -= safe_length; length -= safe_length;
} }
while (length > 0); while (length > 0);
/* And the following is always safe because the crc is only 32 bits. */ /* 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)); PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr));
/* Write a PNG chunk - size, type, (optional) data, CRC. */ /* Write a PNG chunk - size, type, (optional) data, CRC. */
PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr,
chunk_name, png_const_bytep data, size_t length)); png_const_bytep chunk_name, png_const_voidp data, size_t length));
/* Write the start of a PNG chunk - length and chunk name. */ /* Write the start of a PNG chunk - length and chunk name. */
PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr, 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(). */ /* 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_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). */ /* Finish a chunk started with png_write_chunk_start() (includes CRC). */
PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr)); 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) if (png_ptr == NULL)
return 0; return 0;
#ifdef PNG_WRITE_SUPPORTED # if defined(PNG_SEQUENTIAL_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
if (png_ptr->read_struct) return png_ptr->IDAT_size;
{ # else
# ifdef PNG_SEQUENTIAL_READ_SUPPORTED return PNG_IDAT_READ_SIZE; /* progressive reader */
return png_ptr->IDAT_read_size; # endif
# 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 */
} }
#ifdef PNG_SET_USER_LIMITS_SUPPORTED #ifdef PNG_SET_USER_LIMITS_SUPPORTED

View File

@ -97,7 +97,6 @@ struct png_info_def
/* iCCP chunk data. */ /* iCCP chunk data. */
png_charp iccp_name; /* profile name */ png_charp iccp_name; /* profile name */
png_bytep iccp_profile; /* International Color Consortium profile data */ png_bytep iccp_profile; /* International Color Consortium profile data */
png_uint_32 iccp_proflen; /* ICC profile data length */
#endif #endif
#ifdef PNG_TEXT_SUPPORTED #ifdef PNG_TEXT_SUPPORTED

View File

@ -458,9 +458,9 @@
/* Just a little check that someone hasn't tried to define something /* Just a little check that someone hasn't tried to define something
* contradictory. * 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 # undef PNG_ZBUF_SIZE
# define PNG_ZBUF_SIZE 65536L # define PNG_ZBUF_SIZE 32768
#endif #endif
/* If warnings or errors are turned off the code is disabled or redirected here. /* 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 */ /* Write the "data" buffer to whatever output you are using */
PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr, 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 */ /* Read and check the PNG file signature */
PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr,
png_inforp info_ptr),PNG_EMPTY); png_inforp info_ptr),PNG_EMPTY);
/* Read data from whatever input you are using into the "data" buffer */ /* 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); png_size_t length),PNG_EMPTY);
/* Read bytes into buf, and update png_ptr->crc */ /* 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); png_uint_32 length),PNG_EMPTY);
/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */ /* 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. * since this is the maximum buffer size we can specify.
*/ */
PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr, 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 #ifdef PNG_WRITE_FLUSH_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY); 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 #ifdef PNG_WRITE_iCCP_SUPPORTED
PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr, 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 /* The profile must have been previously validated for correctness, the
* length comes from the first four bytes. Only the base, deflate, * length comes from the first four bytes. Only the base, deflate,
* compression is supported. * compression is supported.

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.) * required (it will be zero in a write structure.)
*/ */
# ifdef PNG_SEQUENTIAL_READ_SUPPORTED # 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 */ # endif /* SEQUENTIAL_READ */
# ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED # ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED
@ -308,17 +308,17 @@ png_start_read_image(png_structrp png_ptr)
static void static void
png_read_IDAT(png_structrp png_ptr) 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: * end of the IDAT stream:
*/ */
uInt IDAT_size = 0; uInt IDAT_size = 0;
png_bytep buffer = 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; png_ptr->zstream.next_in = buffer;
while (png_ptr->chunk_name == png_IDAT && 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; png_uint_32 l = png_ptr->chunk_length;
@ -336,10 +336,10 @@ png_read_IDAT(png_structrp png_ptr)
l = png_ptr->chunk_length; 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 */ if (l > png_ptr->IDAT_size - IDAT_size) /* SAFE: while check */
l = png_ptr->IDAT_read_size - IDAT_size; l = png_ptr->IDAT_size - IDAT_size;
png_crc_read(png_ptr, buffer+IDAT_size, l); png_crc_read(png_ptr, buffer+IDAT_size, l);
IDAT_size += /*SAFE*/l; IDAT_size += /*SAFE*/l;

View File

@ -30,12 +30,12 @@
* to read more than 64K on a 16 bit machine. * to read more than 64K on a 16 bit machine.
*/ */
void /* PRIVATE */ 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); png_debug1(4, "reading %d bytes", (int)length);
if (png_ptr->rw_data_fn != NULL) 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 else
png_app_error(png_ptr, "No read function"); 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. */ /* Read data, and (optionally) run it through the CRC. */
void /* PRIVATE */ 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) if (png_ptr == NULL)
return; return;
@ -1382,8 +1382,6 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr)
{ {
memcpy(info_ptr->iccp_name, keyword, memcpy(info_ptr->iccp_name, keyword,
keyword_length+1); keyword_length+1);
info_ptr->iccp_proflen =
profile_length;
info_ptr->iccp_profile = profile; info_ptr->iccp_profile = profile;
png_ptr->read_buffer = NULL; /*steal*/ png_ptr->read_buffer = NULL; /*steal*/
info_ptr->free_me |= PNG_FREE_ICCP; 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); 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_name = new_iccp_name;
info_ptr->iccp_profile = new_iccp_profile; info_ptr->iccp_profile = new_iccp_profile;
info_ptr->free_me |= PNG_FREE_ICCP; 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 void PNGAPI
png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size) png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
{ {
if (png_ptr == NULL) if (png_ptr == NULL)
return; return;
if (size == 0 || size > PNG_UINT_31_MAX) if (size == 0 || size > PNG_UINT_31_MAX)
png_error(png_ptr, "invalid compression buffer size"); png_error(png_ptr, "invalid compression buffer size");
# ifdef PNG_SEQUENTIAL_READ_SUPPORTED # if (defined PNG_SEQUENTIAL_READ_SUPPORTED) || defined PNG_WRITE_SUPPORTED
if (png_ptr->read_struct) png_ptr->IDAT_size = (uInt)/*SAFE*/size;
{ # endif /* SEQUENTIAL_READ || WRITE */
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 */
} }
void PNGAPI void PNGAPI

View File

@ -569,15 +569,15 @@ struct png_struct_def
#endif /* TRANFORM_MECH */ #endif /* TRANFORM_MECH */
#ifdef PNG_READ_SUPPORTED #ifdef PNG_READ_SUPPORTED
/* These, and IDAT_read_size below, control how much input and output (at /* These, and IDAT_size below, control how much input and output (at most) is
* most) is available to zlib. * available to zlib during read decompression.
*/ */
png_alloc_size_t read_buffer_size; /* current size of the buffer */ png_alloc_size_t read_buffer_size; /* current size of the buffer */
#endif #endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED #if defined(PNG_SEQUENTIAL_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
uInt IDAT_read_size; /* limit on read buffer size for IDAT */ uInt IDAT_size; /* limit on IDAT read and write IDAT size */
#endif #endif /* SEQUENTIAL_READ || WRITE */
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED #ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
int zlib_text_level; /* holds zlib compression level */ int zlib_text_level; /* holds zlib compression level */
@ -600,8 +600,10 @@ struct png_struct_def
int zlib_set_mem_level; int zlib_set_mem_level;
int zlib_set_strategy; int zlib_set_strategy;
png_compression_bufferp zbuffer_list; /* Created on demand during write */ unsigned int zbuffer_start; /* Bytes written from start */
uInt zbuffer_size; /* size of the actual zlib buffer */ 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 #endif
/* ERROR HANDLING */ /* 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 */ 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 ) 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 else
png_app_error(png_ptr, "No write function"); 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 /* Set the zlib control values to defaults; they can be overridden by the
* application after the struct has been created. * 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 /* The 'zlib_strategy' setting is irrelevant because png_default_claim in
* pngwutil.c defaults it according to whether or not filters will be * 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 setting sCAL_PRECISION default 5
# This is the size of the compression buffer, and thus the size of # This used to control the size of the IDAT chunks on write and the size of the
# an IDAT chunk. Make this whatever size you feel is best for your # compression buffer used internally. It now solely controls the size of the
# machine. One of these will be allocated per png_struct. When this # written IDAT chunks. It can be any (zlib) uInt value, however this amount of
# is full, it writes the data to the disk, and does some other # data has to be buffered on write so it is recommended that a smaller size be
# calculations. Making this an extremely small size may slow # used unless saving the 12-byte chunk overhead is necessary.
# 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.
setting ZBUF_SIZE default 8192 setting ZBUF_SIZE default 4096
# This is the size of the decompression buffer used when counting or checking # 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 # 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 setting INFLATE_BUF_SIZE default 1024
# This is the maximum amount of IDAT data that the sequential reader will # This is the amount of IDAT data that the sequential reader will process at one
# process at one time. The setting does not affect the size of IDAT chunks # time. The setting does not affect the size of IDAT chunks read, just the
# read, just the amount read at once. Neither does it affect the progressive # amount read at once. Neither does it affect the progressive reader, which
# reader, which processes just the amount of data the application gives it. # 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 # The sequential reader will read IDAT chunks up to this limit, or the end of
# this to a value larger than the IDAT chunks typically encountered (it would # the chunks, before decompressing the next row. The value should be chosen to
# just waste memory) but there may be some point in reducing it below the value # optimize the PNG data read speed, it has no significant effect on anything
# of ZBUF_SIZE (the size of IDAT chunks written by libpng.) # else.
setting IDAT_READ_SIZE default PNG_ZBUF_SIZE setting IDAT_READ_SIZE default 4096
# Ancillary chunks # Ancillary chunks
chunk bKGD chunk bKGD