Separate png_compress_IDAT into w/c

I.e. write/compress, also remove some trailing spaces and clean up pnglibconf
stuff.

Signed-off-by: John Bowler <jbowler@acm.org>
This commit is contained in:
John Bowler 2015-11-30 21:00:22 -08:00
parent 8978eba436
commit 8fe2eac47f
5 changed files with 189 additions and 163 deletions

View File

@ -566,7 +566,7 @@ struct png_struct_def
* wherein !(r==g==b).
*/
#endif /* RGB_TO_GRAY */
#endif /* TRANFORM_MECH */
#endif /* TRANSFORM_MECH */
#ifdef PNG_READ_SUPPORTED
/* These, and IDAT_size below, control how much input and output (at most) is
@ -599,12 +599,7 @@ struct png_struct_def
int zlib_set_window_bits;
int zlib_set_mem_level;
int zlib_set_strategy;
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
#endif /* WRITE */
/* ERROR HANDLING */
#ifdef PNG_SETJMP_SUPPORTED
@ -748,14 +743,23 @@ struct png_struct_def
* zlib expects a 'zstream' as the fundamental control structure, it allows
* all the parameters to be passed as one pointer.
*/
png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */
z_stream zstream; /* decompression structure */
unsigned int zstream_start:1; /* before first byte of stream */
unsigned int zstream_ended:1; /* no more zlib output available */
unsigned int zstream_error:1; /* zlib error message has been output */
png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */
# ifdef PNG_WRITE_SUPPORTED
png_compression_bufferp zbuffer_list; /* Created on demand during write */
png_compression_bufferp *zbuffer_end; /* 'next' field of current buffer */
png_uint_32 zbuffer_len; /* Length of data in list */
unsigned int zbuffer_start; /* Bytes written from start */
# endif /* WRITE */
# ifdef PNG_READ_SUPPORTED
unsigned int zstream_ended:1; /* no more zlib output available [read] */
unsigned int zstream_error:1; /* zlib error message has been output [read] */
# endif /* READ */
# ifdef PNG_PROGRESSIVE_READ_SUPPORTED
unsigned int zstream_eod :1; /* all the required uncompressed data has been
* received; set by the zstream using code for
* its own purposes. */
* its own purposes. [progressive read] */
# endif /* PROGRESSIVE_READ */
/* MNG SUPPORT */
#ifdef PNG_MNG_FEATURES_SUPPORTED

View File

@ -1907,11 +1907,148 @@ png_start_IDAT(png_structrp png_ptr)
}
static void
png_compress_IDAT(png_structrp png_ptr, png_const_voidp input, uInt input_len,
int flush)
png_write_IDAT(png_structrp png_ptr, int end_of_image)
{
png_compression_bufferp *listp = &png_ptr->zbuffer_list;
png_compression_bufferp list;
png_uint_32 output_len = png_ptr->zbuffer_len;
png_uint_32 start = png_ptr->zbuffer_start;
png_uint_32 size = png_ptr->IDAT_size;
const png_uint_32 min_size = (end_of_image ? 1U : size);
affirm(output_len >= min_size);
/* png_struct::zbuffer_end points to the pointer to the next (unused)
* compression buffer. We don't need those blocks to produce output so
* free them now to save space. This also ensures that *zbuffer_end is
* NULL so can be used to store the list head when wrapping the list.
*/
png_free_buffer_list(png_ptr, png_ptr->zbuffer_end);
/* Write at least one chunk, of size 'size', write chunks until
* 'output_len' is less than 'min_size'.
*/
list = *listp;
/* First, if this is the very first IDAT (PNG_HAVE_IDAT not set)
* optimize the CINFO field:
*/
# ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
if ((png_ptr->mode & PNG_HAVE_IDAT) == 0U)
{
affirm(start == 0U);
optimize_cmf(list->output, png_image_size(png_ptr));
}
# endif /* WRITE_OPTIMIZE_CMF */
do /* write chunks */
{
/* 'size' is the size of the chunk to write, limited to IDAT_size:
*/
if (size > output_len) /* Z_FINISH */
size = output_len;
debug(size >= min_size);
png_write_chunk_header(png_ptr, png_IDAT, size);
do /* write the data of one chunk */
{
/* The chunk data may be split across multiple compression
* buffers. This loop moves 'list' down the available
* compression buffers.
*/
png_uint_32 avail = PNG_ROW_BUFFER_SIZE - start; /* in *list */
if (avail > output_len) /* valid bytes */
avail = output_len;
if (avail > size) /* bytes needed for chunk */
avail = size;
affirm(list != NULL && avail > 0U &&
start+avail <= PNG_ROW_BUFFER_SIZE);
png_write_chunk_data(png_ptr, list->output+start, avail);
output_len -= avail;
size -= avail;
start += avail;
if (start == PNG_ROW_BUFFER_SIZE)
{
/* End of the buffer. If all the compressed data has been
* consumed (output_len == 0) this will set list to NULL
* because of the png_free_buffer_list call above. At this
* point 'size' should be 0 too and the loop will terminate.
*/
start = 0U;
listp = &list->next;
list = *listp; /* May be NULL at the end */
}
} while (size > 0);
png_write_chunk_end(png_ptr);
size = png_ptr->IDAT_size; /* For the next chunk */
} while (output_len >= min_size);
png_ptr->mode |= PNG_HAVE_IDAT;
png_ptr->zbuffer_len = output_len;
if (output_len > 0U) /* Still got stuff to write */
{
affirm(!end_of_image && list != NULL);
/* If any compression buffers have been completely written move them
* to the end of the list so that they can be re-used and move
* 'list' to the head:
*/
if (listp != &png_ptr->zbuffer_list) /* list not at start */
{
debug(list != png_ptr->zbuffer_list /* obviously */ &&
listp != png_ptr->zbuffer_end /* because *end == NULL */);
*png_ptr->zbuffer_end = png_ptr->zbuffer_list;
*listp = NULL;
png_ptr->zbuffer_list = list;
}
/* 'list' is now at the start, so 'start' can be stored. */
png_ptr->zbuffer_start = start;
png_ptr->zbuffer_len = output_len;
}
else /* output_len == 0U; all compressed data has been written */
{
if (end_of_image)
{
png_ptr->zowner = 0U; /* release z_stream */
png_ptr->mode |= PNG_AFTER_IDAT;
}
/* Else: this is unlikely but possible; the compression code managed
* to exactly fill an IDAT chunk with the data for this block of row
* bytes so nothing is left in the buffer list. Simply reset the
* output pointers to the start of the list. This code is executed
* on Z_FINISH as well just to make the state safe.
*/
png_ptr->zstream.next_out = NULL;
png_ptr->zstream.avail_out = 0U;
png_ptr->zbuffer_start = 0U;
png_ptr->zbuffer_len = 0U;
png_ptr->zbuffer_end = &png_ptr->zbuffer_list;
} /* output_len == 0 */
}
typedef struct
{
png_compression_bufferp *zbuffer_end; /* 'next' field of current buffer */
png_uint_32 zbuffer_len; /* Length of data in list */
} png_IDAT_compression_state;
static int
png_compress_IDAT_test(png_structrp png_ptr, png_IDAT_compression_state *state,
z_stream *zstream, png_const_voidp input, uInt input_len, int flush)
{
png_uint_32 output_len = 0U;
int ret;
/* The stream must have been claimed: */
affirm(png_ptr->zowner == png_IDAT);
@ -1919,22 +2056,34 @@ png_compress_IDAT(png_structrp png_ptr, png_const_voidp input, uInt input_len,
* buffer list. next_in must be set here, avail_in comes from the input_len
* parameter:
*/
{
png_uint_32 output_len = 0U;
zstream->next_in = PNGZ_INPUT_CAST(png_voidcast(const Bytef*, input));
ret = png_compress(png_ptr, zstream, &state->zbuffer_end, input_len,
&output_len, flush);
implies(ret == Z_OK || ret == Z_FINISH, zstream->avail_in == 0U);
zstream->next_in = NULL;
zstream->avail_in = 0U; /* safety */
png_ptr->zstream.next_in =
PNGZ_INPUT_CAST(png_voidcast(const Bytef*,input));
ret = png_compress(png_ptr, &png_ptr->zstream, &png_ptr->zbuffer_end,
input_len, &output_len, flush);
implies(ret == Z_OK || ret == Z_FINISH, png_ptr->zstream.avail_in == 0U);
png_ptr->zstream.next_in = NULL;
png_ptr->zstream.avail_in = 0U; /* safety */
/* If IDAT_size is set to PNG_UINT_31_MAX the length will be larger, but
* not enough to overflow a png_uint_32.
*/
state->zbuffer_len += output_len;
return ret;
/* If IDAT_size is set to PNG_UINT_31_MAX the length will be larger, but
* not enough to overflow a png_uint_32.
*/
png_ptr->zbuffer_len += output_len;
}
}
static void
png_compress_IDAT(png_structp png_ptr, png_const_voidp input, uInt input_len,
int flush)
{
png_IDAT_compression_state state;
int ret;
state.zbuffer_end = png_ptr->zbuffer_end;
state.zbuffer_len = png_ptr->zbuffer_len;
ret = png_compress_IDAT_test(png_ptr, &state, &png_ptr->zstream, input,
input_len, flush);
png_ptr->zbuffer_end = state.zbuffer_end;
png_ptr->zbuffer_len = state.zbuffer_len;
/* Check the return code. */
if (ret == Z_OK || ret == Z_STREAM_END)
@ -1956,133 +2105,7 @@ png_compress_IDAT(png_structrp png_ptr, png_const_voidp input, uInt input_len,
* written this function call is complete.
*/
if (flush == Z_FINISH || png_ptr->zbuffer_len >= png_ptr->IDAT_size)
{
png_compression_bufferp *listp = &png_ptr->zbuffer_list;
png_compression_bufferp list;
png_uint_32 output_len = png_ptr->zbuffer_len;
png_uint_32 start = png_ptr->zbuffer_start;
png_uint_32 size = png_ptr->IDAT_size;
const png_uint_32 min_size = (flush == Z_FINISH ? 1U : size);
affirm(output_len >= min_size);
/* png_struct::zbuffer_end points to the pointer to the next (unused)
* compression buffer. We don't need those blocks to produce output so
* free them now to save space. This also ensures that *zbuffer_end is
* NULL so can be used to store the list head when wrapping the list.
*/
png_free_buffer_list(png_ptr, png_ptr->zbuffer_end);
/* Write at least one chunk, of size 'size', write chunks until
* 'output_len' is less than 'min_size'.
*/
list = *listp;
/* First, if this is the very first IDAT (PNG_HAVE_IDAT not set)
* optimize the CINFO field:
*/
# ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
if ((png_ptr->mode & PNG_HAVE_IDAT) == 0U)
{
affirm(start == 0U);
optimize_cmf(list->output, png_image_size(png_ptr));
}
# endif /* WRITE_OPTIMIZE_CMF */
do /* write chunks */
{
/* 'size' is the size of the chunk to write, limited to IDAT_size:
*/
if (size > output_len) /* Z_FINISH */
size = output_len;
debug(size >= min_size);
png_write_chunk_header(png_ptr, png_IDAT, size);
do /* write the data of one chunk */
{
/* The chunk data may be split across multiple compression
* buffers. This loop moves 'list' down the available
* compression buffers.
*/
png_uint_32 avail = PNG_ROW_BUFFER_SIZE - start; /* in *list */
if (avail > output_len) /* valid bytes */
avail = output_len;
if (avail > size) /* bytes needed for chunk */
avail = size;
affirm(list != NULL && avail > 0U &&
start+avail <= PNG_ROW_BUFFER_SIZE);
png_write_chunk_data(png_ptr, list->output+start, avail);
output_len -= avail;
size -= avail;
start += avail;
if (start == PNG_ROW_BUFFER_SIZE)
{
/* End of the buffer. If all the compressed data has been
* consumed (output_len == 0) this will set list to NULL
* because of the png_free_buffer_list call above. At this
* point 'size' should be 0 too and the loop will terminate.
*/
start = 0U;
listp = &list->next;
list = *listp; /* May be NULL at the end */
}
} while (size > 0);
png_write_chunk_end(png_ptr);
size = png_ptr->IDAT_size; /* For the next chunk */
} while (output_len >= min_size);
png_ptr->mode |= PNG_HAVE_IDAT;
png_ptr->zbuffer_len = output_len;
if (output_len > 0U) /* Still got stuff to write */
{
affirm(flush != Z_FINISH && list != NULL);
/* If any compression buffers have been completely written move them
* to the end of the list so that they can be re-used and move
* 'list' to the head:
*/
if (listp != &png_ptr->zbuffer_list) /* list not at start */
{
debug(list != png_ptr->zbuffer_list /* obviously */ &&
listp != png_ptr->zbuffer_end /* because *end == NULL */);
*png_ptr->zbuffer_end = png_ptr->zbuffer_list;
*listp = NULL;
png_ptr->zbuffer_list = list;
}
/* 'list' is now at the start, so 'start' can be stored. */
png_ptr->zbuffer_start = start;
png_ptr->zbuffer_len = output_len;
}
else /* output_len == 0U; all compressed data has been written */
{
if (flush == Z_FINISH) /* end of data */
{
png_ptr->zowner = 0U; /* release z_stream */
png_ptr->mode |= PNG_AFTER_IDAT;
}
/* Else: this is unlikely but possible; the compression code managed
* to exactly fill an IDAT chunk with the data for this block of row
* bytes so nothing is left in the buffer list. Simply reset the
* output pointers to the start of the list. This code is executed
* on Z_FINISH as well just to make the state safe.
*/
png_ptr->zstream.next_out = NULL;
png_ptr->zstream.avail_out = 0U;
png_ptr->zbuffer_start = 0U;
png_ptr->zbuffer_len = 0U;
png_ptr->zbuffer_end = &png_ptr->zbuffer_list;
} /* output_len == 0 */
} /* flush == FINISH || png_ptr->zbuffer_len >= png_ptr->IDAT_size */
png_write_IDAT(png_ptr, flush == Z_FINISH);
}
else /* ret != Z_OK && ret != Z_STREAM_END */

View File

@ -243,7 +243,7 @@ $1 == "file" && NF >= 2{
# option NAME ( (requires|enables|if) NAME* | on | off | disabled |
# sets SETTING VALUE+ )*
#
#
# Declares an option 'NAME' and describes its default setting (disabled)
# and its relationship to other options. The option is disabled
# unless *all* the options listed after 'requires' are set and at

View File

@ -125,7 +125,7 @@ file pnglibconf.h scripts/pnglibconf.dfa PNGLCONF_H
#
# To avoid confusion use -DPNG_foo_SUPPORTED= on the command line, which does
# the same thing as the #define.
#
#
# SUMMARY:
# These lines/macro settings are equivalent:
#
@ -460,7 +460,7 @@ option SET_USER_LIMITS requires USER_LIMITS
# See the comments above about how to change options and settings.
# READ/WRITE tranform support
#
#
# The internal TRANSFORM_MECH options are used to turn on (or off) the required
# support code for the read and write transforms. They are off by default,
# switching them on is not a good idea. Switching them off will cause the build
@ -496,7 +496,7 @@ option READ_16BIT requires READ enables 16BIT
option READ_TRANSFORMS requires READ
= NO_READ_TRANSFORMS READ_TRANSFORMS_NOT_SUPPORTED
option READ_QUANTIZE requires READ_TRANSFORMS enables TRANFORM_MECH
option READ_QUANTIZE requires READ_TRANSFORMS enables TRANSFORM_MECH
# Read gamma handling. Gamma processing is a core part of libpng and many of
# the capabilities are dependent on libpng performing gamma correction.

View File

@ -116,7 +116,6 @@
#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_TEXT_SUPPORTED
#define PNG_TIME_RFC1123_SUPPORTED
#define PNG_TRANFORM_MECH_SUPPORTED
#define PNG_TRANSFORM_MECH_SUPPORTED
#define PNG_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_USER_CHUNKS_SUPPORTED
@ -194,7 +193,7 @@
#define PNG_DEFAULT_GAMMA_ACCURACY 665
#define PNG_DEFAULT_READ_MACROS 1
#define PNG_GAMMA_THRESHOLD_FIXED 153
#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
#define PNG_IDAT_READ_SIZE 4096
#define PNG_INFLATE_BUF_SIZE 1024
#define PNG_MAX_GAMMA_8 11
#define PNG_QUANTIZE_BLUE_BITS 5
@ -206,7 +205,7 @@
#define PNG_USER_CHUNK_MALLOC_MAX 8000000
#define PNG_USER_HEIGHT_MAX 1000000
#define PNG_USER_WIDTH_MAX 1000000
#define PNG_ZBUF_SIZE 8192
#define PNG_ZBUF_SIZE 4096
#define PNG_ZLIB_HEADER <zlib.h>
#define PNG_ZLIB_VERNUM 0
#define PNG_Z_DEFAULT_COMPRESSION (-1)