From 6b3d50b2cd4dbbdba3612ea77c24178c4df8b50f Mon Sep 17 00:00:00 2001 From: Glenn Randers-Pehrson Date: Thu, 31 Mar 2011 20:14:29 -0500 Subject: [PATCH] [devel] Re-initialize the zlib compressor before compressing non-IDAT chunks. --- ANNOUNCE | 51 +++++++----------------- CHANGES | 4 ++ png.h | 40 +++++++++++++------ pngconf.h | 2 +- pngmem.c | 21 +++++++--- pngpriv.h | 14 +++---- pngstruct.h | 7 ++++ pngwrite.c | 82 ++++++++++++++++++++++++++++++++++++++- pngwutil.c | 109 +++++++++++++++++++++++++++++++++++++++------------- 9 files changed, 239 insertions(+), 91 deletions(-) diff --git a/ANNOUNCE b/ANNOUNCE index 0659ae39d..c4b600e47 100644 --- a/ANNOUNCE +++ b/ANNOUNCE @@ -1,60 +1,35 @@ -Libpng 1.5.2 - March 31, 2011 +Libpng 1.5.3beta01 - April 1, 2011 -This is a public release of libpng, intended for use in production codes. +This is not intended to be a public release. It will be replaced +within a few weeks by a public version or by another test version. Files available for download: Source files with LF line endings (for Unix/Linux) and with a "configure" script - libpng-1.5.2.tar.xz (LZMA-compressed, recommended) - libpng-1.5.2.tar.gz - libpng-1.5.2.tar.bz2 + 1.5.3beta01.tar.xz (LZMA-compressed, recommended) + 1.5.3beta01.tar.gz + 1.5.3beta01.tar.bz2 Source files with CRLF line endings (for Windows), without the "configure" script - lpng152.7z (LZMA-compressed, recommended) - lpng152.zip + lp153b01.7z (LZMA-compressed, recommended) + lp153b01.zip Other information: - libpng-1.5.2-README.txt - libpng-1.5.2-LICENSE.txt + 1.5.3beta01-README.txt + 1.5.3beta01-LICENSE.txt Changes since the last public release (1.5.2): - More -Wshadow fixes for older gcc compilers. Older gcc versions apparently - check formal parameters names in function declarations (as well as - definitions) to see if they match a name in the global namespace. - Revised PNG_EXPORTA macro to not use an empty parameter, to accommodate the - old VisualC++ preprocessor. - Turned on interlace handling in png_read_png(). - Fixed gcc pendantic warnings. - Handle longjmp in Cygwin. - Fixed png_get_current_row_number() in the interlaced case. - Cleaned up ALPHA flags and transformations. - Implemented expansion to 16 bits. - Fixed mistake in the descriptions of user read_transform and write_transform - function prototypes in the manual. The row_info struct is png_row_infop. - Corrected png_get_current_row_number documentation - Fixed the read/write row callback documentation. - This documents the current behavior, where the callback is called after - every row with information pertaining to the next row. - Fixed scripts/makefile.vcwin32 - Updated contrib/pngsuite/README to add the word "modify". - Define PNG_ALLOCATED and other attributes to blank when _MSC_VER<1300. - ifdef out mask arrays in pngread.c when interlacing is not supported. - Added a hint to try CPP=/bin/cpp if "cpp -E" fails in scripts/pnglibconf.mak - and in contrib/pngminim/*/makefile, eg., on SunOS 5.10, and removed "strip" - from the makefiles. - Fixed a bug (present since libpng-1.0.7) that makes png_handle_sPLT() fail - to compile when PNG_NO_POINTER_INDEXING is defined (Chubanov Kirill) - Don't include standard header files in png.h while building the symbol table, - to avoid cpp failure on SunOS (introduced PNG_BUILDING_SYMBOL_TABLE macro). +Version 1.5.3beta01 [April 1, 2011] + Re-initialize the zlib compressor before compressing non-IDAT chunks. -Send comments/corrections/commendations to png-mng-implement at lists.sf.net +Send comments/corrections/commendations to png-mng-implement at lists.sf.net: (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement to subscribe) or to glennrp at users.sourceforge.net diff --git a/CHANGES b/CHANGES index fb069121a..f9be127eb 100644 --- a/CHANGES +++ b/CHANGES @@ -3285,6 +3285,10 @@ Version 1.5.2rc03 [March 24, 2011] to avoid cpp failure on SunOS (introduced PNG_BUILDING_SYMBOL_TABLE macro). Version 1.5.2 [March 31, 2011] + No changes. + +Version 1.5.3beta01 [April 1, 2011] + Re-initialize the zlib compressor before compressing non-IDAT chunks. Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/png.h b/png.h index 0af42b170..0601f4728 100644 --- a/png.h +++ b/png.h @@ -1,7 +1,7 @@ /* png.h - header file for PNG reference library * - * libpng version 1.5.2 - March 31, 2011 + * libpng version 1.5.3beta01 - April 1, 2011 * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -11,7 +11,7 @@ * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.5.2 - March 31, 2011: Glenn + * libpng versions 0.97, January 1998, through 1.5.3beta01 - April 1, 2011: Glenn * See also "Contributing Authors", below. * * Note about libpng version numbers: @@ -181,7 +181,7 @@ * * This code is released under the libpng license. * - * libpng versions 1.2.6, August 15, 2004, through 1.5.2, March 31, 2011, are + * libpng versions 1.2.6, August 15, 2004, through 1.5.3beta01, April 1, 2011, are * Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are * distributed according to the same disclaimer and license as libpng-1.2.5 * with the following individual added to the list of Contributing Authors: @@ -293,13 +293,13 @@ * Y2K compliance in libpng: * ========================= * - * March 31, 2011 + * April 1, 2011 * * Since the PNG Development group is an ad-hoc body, we can't make * an official declaration. * * This is your unofficial assurance that libpng from version 0.71 and - * upward through 1.5.2 are Y2K compliant. It is my belief that + * upward through 1.5.3beta01 are Y2K compliant. It is my belief that * earlier versions were also Y2K compliant. * * Libpng only has three year fields. One is a 2-byte unsigned integer @@ -355,9 +355,9 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.5.2" +#define PNG_LIBPNG_VER_STRING "1.5.3beta01" #define PNG_HEADER_VERSION_STRING \ - " libpng version 1.5.2 - March 31, 2011\n" + " libpng version 1.5.3beta01 - April 1, 2011\n" #define PNG_LIBPNG_VER_SONUM 15 #define PNG_LIBPNG_VER_DLLNUM 15 @@ -365,12 +365,12 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 5 -#define PNG_LIBPNG_VER_RELEASE 2 +#define PNG_LIBPNG_VER_RELEASE 3 /* This should match the numeric part of the final component of * PNG_LIBPNG_VER_STRING, omitting any leading zero: */ -#define PNG_LIBPNG_VER_BUILD 0 +#define PNG_LIBPNG_VER_BUILD 01 /* Release Status */ #define PNG_LIBPNG_BUILD_ALPHA 1 @@ -395,7 +395,7 @@ * version 1.0.0 was mis-numbered 100 instead of 10000). From * version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release */ -#define PNG_LIBPNG_VER 10502 /* 1.5.2 */ +#define PNG_LIBPNG_VER 10503 /* 1.5.3 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -517,7 +517,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_5_2; +typedef char* png_libpng_version_1_5_3beta01; /* Three color definitions. The order of the red, green, and blue, (and the * exact size) is not important, although the size of the fields need to @@ -1413,6 +1413,24 @@ PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr, PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr, int method)); +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION +/* Also set zlib parameters for compressing non-IDAT chunks */ +PNG_EXPORT(222, void, png_set_text_compression_level, + (png_structp png_ptr, int level)); + +PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structp png_ptr, + int mem_level)); + +PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structp png_ptr, + int strategy)); + +PNG_EXPORT(225, void, png_set_text_compression_window_bits, (png_structp + png_ptr, int window_bits)); + +PNG_EXPORT(226, void, png_set_text_compression_method, (png_structp png_ptr, + int method)); +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ + /* These next functions are called for input/output, memory, and error * handling. They are in the file pngrio.c, pngwio.c, and pngerror.c, * and call standard C I/O routines such as fread(), fwrite(), and diff --git a/pngconf.h b/pngconf.h index c82fa5866..c355573d9 100644 --- a/pngconf.h +++ b/pngconf.h @@ -1,7 +1,7 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.5.2 - March 31, 2011 + * libpng version 1.5.3beta01 - March 31, 2011 * * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) diff --git a/pngmem.c b/pngmem.c index a15d8b085..487c96bec 100644 --- a/pngmem.c +++ b/pngmem.c @@ -187,8 +187,9 @@ png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) int num_blocks; png_uint_32 total_size; png_bytep table; - int i; + int i, mem_level, window_bits; png_byte huge * hptr; + int window_bits if (ret != NULL) { @@ -196,14 +197,22 @@ png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) ret = NULL; } - if (png_ptr->zlib_window_bits > 14) - num_blocks = (int)(1 << (png_ptr->zlib_window_bits - 14)); + window_bits = + png_ptr->zlib_window_bits >= png_ptr->zlib_text_window_bits ? + png_ptr->zlib_window_bits : png_ptr->zlib_text_window_bits; + + if (window_bits > 14) + num_blocks = (int)(1 << (window_bits - 14)); else num_blocks = 1; - if (png_ptr->zlib_mem_level >= 7) - num_blocks += (int)(1 << (png_ptr->zlib_mem_level - 7)); + mem_level = + png_ptr->zlib_mem_level >= png_ptr->zlib_text_mem_level ? + png_ptr->zlib_mem_level : png_ptr->zlib_text_mem_level; + + if (mem_level >= 7) + num_blocks += (int)(1 << (mem_level - 7)); else num_blocks++; @@ -277,7 +286,7 @@ png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED) { # ifndef PNG_USER_MEM_SUPPORTED if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0) - png_error(png_ptr, "Out of Memory"); /* Note "o" and "M" */ + png_error(png_ptr, "Out of Memory"); /* Note "O" and "M" */ else png_warning(png_ptr, "Out of Memory"); diff --git a/pngpriv.h b/pngpriv.h index a7e3b5272..5bc4f38a6 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -345,13 +345,13 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp; /* 0x200000L unused */ /* 0x400000L unused */ #define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000L /* Added to libpng-1.4.0 */ - /* 0x1000000L unused */ - /* 0x2000000L unused */ - /* 0x4000000L unused */ - /* 0x8000000L unused */ - /* 0x10000000L unused */ - /* 0x20000000L unused */ - /* 0x40000000L unused */ +#define PNG_FLAG_ZTXT_CUSTOM_STRATEGY 0x1000000L /* 5 lines added */ +#define PNG_FLAG_ZTXT_CUSTOM_LEVEL 0x2000000L /* to libpng-1.5.2 */ +#define PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL 0x4000000L +#define PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS 0x8000000L +#define PNG_FLAG_ZTXT_CUSTOM_METHOD 0x10000000L + /* 0x20000000L unused */ + /* 0x40000000L unused */ #define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \ PNG_FLAG_CRC_ANCILLARY_NOWARN) diff --git a/pngstruct.h b/pngstruct.h index 8d781faef..47d65be82 100644 --- a/pngstruct.h +++ b/pngstruct.h @@ -69,6 +69,13 @@ struct png_struct_def int zlib_window_bits; /* holds zlib compression window bits */ int zlib_mem_level; /* holds zlib compression memory level */ int zlib_strategy; /* holds zlib compression strategy */ +/* Added at libpng 1.5.2 */ + int zlib_text_level; /* holds zlib compression level */ + int zlib_text_method; /* holds zlib compression method */ + int zlib_text_window_bits; /* holds zlib compression window bits */ + int zlib_text_mem_level; /* holds zlib compression memory level */ + int zlib_text_strategy; /* holds zlib compression strategy */ +/* End of material added at libpng 1.5.2 */ png_uint_32 width; /* width of image in pixels */ png_uint_32 height; /* height of image in pixels */ diff --git a/pngwrite.c b/pngwrite.c index 9277a9516..c7611ee9b 100644 --- a/pngwrite.c +++ b/pngwrite.c @@ -1,7 +1,7 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.5.1 [February 3, 2011] + * Last changed in libpng 1.5.3 [(PENDING RELEASE)] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -1491,6 +1491,86 @@ png_set_compression_method(png_structp png_ptr, int method) png_ptr->zlib_method = method; } +/* The following were added to libpng-1.5.2 */ +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION +void PNGAPI +png_set_text_compression_level(png_structp png_ptr, int level) +{ + png_debug(1, "in png_set_text_compression_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_LEVEL; + png_ptr->zlib_text_level = level; +} + +void PNGAPI +png_set_text_compression_mem_level(png_structp png_ptr, int mem_level) +{ + png_debug(1, "in png_set_text_compression_mem_level"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL; + png_ptr->zlib_text_mem_level = mem_level; +} + +void PNGAPI +png_set_text_compression_strategy(png_structp png_ptr, int strategy) +{ + png_debug(1, "in png_set_text_compression_strategy"); + + if (png_ptr == NULL) + return; + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_STRATEGY; + png_ptr->zlib_text_strategy = strategy; +} + +void PNGAPI +png_set_text_compression_window_bits(png_structp png_ptr, int window_bits) +{ + if (png_ptr == NULL) + return; + + if (window_bits > 15) + png_warning(png_ptr, "Only compression windows <= 32k supported by PNG"); + + else if (window_bits < 8) + png_warning(png_ptr, "Only compression windows >= 256 supported by PNG"); + +#ifndef WBITS_8_OK + /* Avoid libpng bug with 256-byte windows */ + if (window_bits == 8) + { + png_warning(png_ptr, "Text compression window is being reset to 512"); + window_bits = 9; + } + +#endif + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS; + png_ptr->zlib_text_window_bits = window_bits; +} + +void PNGAPI +png_set_text_compression_method(png_structp png_ptr, int method) +{ + png_debug(1, "in png_set_text_compression_method"); + + if (png_ptr == NULL) + return; + + if (method != 8) + png_warning(png_ptr, "Only compression method 8 is supported by PNG"); + + png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_METHOD; + png_ptr->zlib_text_method = method; +} +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ +/* end of API added to libpng-1.5.2 */ + void PNGAPI png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn) { diff --git a/pngwutil.c b/pngwutil.c index 2c35785aa..44ef005b4 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -1,7 +1,7 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.5.0 [January 6, 2011] + * Last changed in libpng 1.5.3 [(PENDING RELEASE)] * Copyright (c) 1998-2011 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -256,9 +256,33 @@ png_text_compress(png_structp png_ptr, * wouldn't cause a failure, just a slowdown due to swapping). */ + /* Initialize the compressor. To do: Why do we need this? */ + ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_text_level, + png_ptr->zlib_text_method, png_ptr->zlib_text_window_bits, + png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy); + + if (ret != Z_OK) + { + if (ret == Z_VERSION_ERROR) + png_error(png_ptr, + "zlib failed to initialize compressor for text-- version error"); + + if (ret == Z_STREAM_ERROR) + png_error(png_ptr, + "zlib failed to initialize compressor for text-- stream error"); + + if (ret == Z_MEM_ERROR) + png_error(png_ptr, + "zlib failed to initialize compressor for text-- mem error"); + + png_error(png_ptr, "zlib failed to initialize compressor for text"); + } + /* Set up the compression buffers */ + /* TODO: the following cast hides a potential overflow problem. */ png_ptr->zstream.avail_in = (uInt)text_len; + /* NOTE: assume zlib doesn't overwrite the input */ png_ptr->zstream.next_in = (Bytef *)text; png_ptr->zstream.avail_out = png_ptr->zbuf_size; @@ -437,7 +461,6 @@ png_write_compressed_data_out(png_structp png_ptr, compression_state *comp) /* Reset zlib for another zTXt/iTXt or image data */ deflateReset(&png_ptr->zstream); - png_ptr->zstream.data_type = Z_BINARY; } #endif @@ -632,34 +655,34 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height, if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD)) png_ptr->zlib_method = 8; +#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY)) + png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL)) + png_ptr->zlib_text_level = Z_DEFAULT_COMPRESSION; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL)) + png_ptr->zlib_text_mem_level = 8; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS)) + png_ptr->zlib_text_window_bits = 15; + + if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD)) + png_ptr->zlib_text_method = 8; +#else + png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY; + png_ptr->zlib_text_level = Z_DEFAULT_COMPRESSION; + png_ptr->zlib_text_mem_level = 8; + png_ptr->zlib_text_window_bits = 15; + png_ptr->zlib_text_method = 8; +#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION */ + + /* Initialize the zlib compressor */ ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, png_ptr->zlib_method, png_ptr->zlib_window_bits, png_ptr->zlib_mem_level, png_ptr->zlib_strategy); - if (ret != Z_OK) - { - if (ret == Z_VERSION_ERROR) - png_error(png_ptr, - "zlib failed to initialize compressor -- version error"); - - if (ret == Z_STREAM_ERROR) - png_error(png_ptr, - "zlib failed to initialize compressor -- stream error"); - - if (ret == Z_MEM_ERROR) - png_error(png_ptr, - "zlib failed to initialize compressor -- mem error"); - - png_error(png_ptr, "zlib failed to initialize compressor"); - } - - png_ptr->zstream.next_out = png_ptr->zbuf; - png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; - /* libpng is not interested in zstream.data_type, so set it - * to a predefined value, to avoid its evaluation inside zlib - */ - png_ptr->zstream.data_type = Z_BINARY; - png_ptr->mode = PNG_HAVE_IHDR; } @@ -750,7 +773,39 @@ png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length) if (!(png_ptr->mode & PNG_HAVE_IDAT) && png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE) { - unsigned int z_cmf = data[0]; /* zlib compression method and flags */ + int ret; + unsigned int z_cmf; /* zlib compression method and flags */ + + ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level, + png_ptr->zlib_method, png_ptr->zlib_window_bits, + png_ptr->zlib_mem_level, png_ptr->zlib_strategy); + + if (ret != Z_OK) + { + if (ret == Z_VERSION_ERROR) + png_error(png_ptr, + "zlib failed to initialize compressor -- version error"); + + if (ret == Z_STREAM_ERROR) + png_error(png_ptr, + "zlib failed to initialize compressor -- stream error"); + + if (ret == Z_MEM_ERROR) + png_error(png_ptr, + "zlib failed to initialize compressor -- mem error"); + + png_error(png_ptr, "zlib failed to initialize compressor"); + } + + png_ptr->zstream.next_out = png_ptr->zbuf; + png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size; + /* libpng is not interested in zstream.data_type, so set it + * to a predefined value, to avoid its evaluation inside zlib + */ + png_ptr->zstream.data_type = Z_BINARY; + + z_cmf = data[0]; + if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70) { /* Avoid memory underflows and multiplication overflows.