diff options
author | Glenn Randers-Pehrson <glennrp at users.sourceforge.net> | 2013-04-02 18:33:47 -0500 |
---|---|---|
committer | Glenn Randers-Pehrson <glennrp at users.sourceforge.net> | 2013-04-02 18:34:59 -0500 |
commit | e7962f03154fdcd61caca795fc07edf62285f0a7 (patch) | |
tree | 5e55545d59b71a5bd20e253904209985c3be5492 | |
parent | 1bcd3f702dce32a4e298cb98147dfbd2b2944921 (diff) | |
download | libpng-e7962f03154fdcd61caca795fc07edf62285f0a7.tar.gz |
Imported from pngcrush-1.7.56.tarv1.7.56
-rw-r--r-- | ChangeLog.html | 11 | ||||
-rw-r--r-- | pngcrush.c | 249 | ||||
-rw-r--r-- | pngcrush.h | 2 |
3 files changed, 192 insertions, 70 deletions
diff --git a/ChangeLog.html b/ChangeLog.html index d0ad5456f..d1202fd07 100644 --- a/ChangeLog.html +++ b/ChangeLog.html @@ -3,7 +3,16 @@ Change log: -Version 1.7.55 (built with libpng-1.6.1rc01 and zlib-1.2.7-1) +Version 1.7.56 (built with libpng-1.6.1 and zlib-1.2.7-1) + Only use pngcrush_debug_malloc() and pngcrush_debug_free() if the result + is going to be shown. + Added PNG_PASS_ROWS, PNG_UNUSED, and other macro definitions, when building + with libpng-1.4.x and older libpng versions. + Multiplied rowbytes by 8/bit_depth when using the system library because + we do not call png_read_transform_info(). This prevents a crash when + reading sub-8-bit input files. + +Version 1.7.55 (built with libpng-1.6.1 and zlib-1.2.7-1) Version 1.7.54 (built with libpng-1.6.1rc01 and zlib-1.2.7-1) diff --git a/pngcrush.c b/pngcrush.c index 68541ae82..36f44f9b5 100644 --- a/pngcrush.c +++ b/pngcrush.c @@ -80,7 +80,7 @@ * */ -#define PNGCRUSH_VERSION "1.7.55" +#define PNGCRUSH_VERSION "1.7.56" /* Experimental: define these if you wish, but, good luck. #define PNGCRUSH_COUNT_COLORS @@ -246,7 +246,12 @@ * See also the "pngzop" directory under the pmt.sourceforge.net project. * Note paragraph 1.c above; zopfli always writes "7" in CINFO. * - * 5. Implement palette-building (from ImageMagick-6.7.0 or later, minus + * 5. Optionally recognize any sRGB iCCP profile and replace it with the + * sRGB chunk. Turn this option on if the "-reduce" option is on. Also, + * if "-reduce" is on, delete any gAMA and cHRM chunks if the sRGB chunk + * is being written. + * + * 6. Implement palette-building (from ImageMagick-6.7.0 or later, minus * the "PNG8" part) -- actually ImageMagick puts the transparent colors * first, then the semitransparent colors, and finally the opaque colors, * and does not sort colors by frequency of use but just adds them @@ -257,24 +262,24 @@ * package which counts RGB pixels in an image; this and its supporting * lib/libppmcmap.c would need to be revised to count RGBA pixels instead. * - * 6. Improve the -help output and/or write a good man page. + * 7. Improve the -help output and/or write a good man page. * - * 7. Finish pplt (MNG partial palette) feature. + * 8. Finish pplt (MNG partial palette) feature. * - * 8. Remove text-handling and color-handling features and put + * 9. Remove text-handling and color-handling features and put * those in a separate program or programs, to avoid unnecessary * recompressing. Note that in pngcrush-1.7.34, pngcrush began doing * this extra work only once instead of for every trial, so the potential * benefit in CPU savings is much smaller now. * - * 9. Add a "pcRu" ancillary chunk that keeps track of the best method, + * 10. Add a "pcRu" ancillary chunk that keeps track of the best method, * methods already tried, and whether "loco crushing" was effective. * - * 10. Try both transformed and untransformed colors when "-loco" is used. + * 11. Try both transformed and untransformed colors when "-loco" is used. * - * 11. Move the Photoshop-fixing stuff into a separate program. + * 12. Move the Photoshop-fixing stuff into a separate program. * - * 12. GRR: More generally (superset of previous 3 items): split into + * 13. GRR: More generally (superset of previous 3 items): split into * separate "edit" and "crush" programs (or functions). Former is fully * libpng-aware, much like current pngcrush; latter makes little or no use of * libpng (maybe IDAT-compression parts only?), instead handling virtually @@ -294,6 +299,15 @@ Change log: +Version 1.7.56 (built with libpng-1.6.1 and zlib-1.2.7-1) + Only use pngcrush_debug_malloc() and pngcrush_debug_free() if the result + is going to be shown. + Added PNG_PASS_ROWS, PNG_UNUSED, and other macro definitions, when building + with libpng-1.4.x and older libpng versions. + Multiplied rowbytes by 8/bit_depth when using the system library because + we do not call png_read_transform_info(). This prevents a crash when + reading sub-8-bit input files. + Version 1.7.55 (built with libpng-1.6.1 and zlib-1.2.7-1) Version 1.7.54 (built with libpng-1.6.1rc01 and zlib-1.2.7-1) @@ -1070,6 +1084,44 @@ Version 1.1.4: added ability to restrict brute_force to one or more filter #define PNGCRUSH_LIBPNG_VER 10007 #endif +# ifndef PNG_UNUSED +# define PNG_UNUSED(param) (void)param; +# endif + +#if (PNG_LIBPNG_VER < 10500) +/* Two macros to return the first row and first column of the original, + * full, image which appears in a given pass. 'pass' is in the range 0 + * to 6 and the result is in the range 0 to 7. + */ +#define PNG_PASS_START_ROW(pass) (((1&~(pass))<<(3-((pass)>>1)))&7) +#define PNG_PASS_START_COL(pass) (((1& (pass))<<(3-(((pass)+1)>>1)))&7) + +/* A macro to return the offset between pixels in the output row for a pair of + * pixels in the input - effectively the inverse of the 'COL_SHIFT' macro that + * follows. Note that ROW_OFFSET is the offset from one row to the next whereas + * COL_OFFSET is from one column to the next, within a row. + */ +#define PNG_PASS_ROW_OFFSET(pass) ((pass)>2?(8>>(((pass)-1)>>1)):8) +#define PNG_PASS_COL_OFFSET(pass) (1<<((7-(pass))>>1)) + +/* Two macros to help evaluate the number of rows or columns in each + * pass. This is expressed as a shift - effectively log2 of the number or + * rows or columns in each 8x8 tile of the original image. + */ +#define PNG_PASS_ROW_SHIFT(pass) ((pass)>2?(8-(pass))>>1:3) +#define PNG_PASS_COL_SHIFT(pass) ((pass)>1?(7-(pass))>>1:3) + +/* Hence two macros to determine the number of rows or columns in a given + * pass of an image given its height or width. In fact these macros may + * return non-zero even though the sub-image is empty, because the other + * dimension may be empty for a small image. + */ +#define PNG_PASS_ROWS(height, pass) (((height)+(((1<<PNG_PASS_ROW_SHIFT(pass))\ + -1)-PNG_PASS_START_ROW(pass)))>>PNG_PASS_ROW_SHIFT(pass)) +#define PNG_PASS_COLS(width, pass) (((width)+(((1<<PNG_PASS_COL_SHIFT(pass))\ + -1)-PNG_PASS_START_COL(pass)))>>PNG_PASS_COL_SHIFT(pass)) +#endif /* PNG_LIBPNG_VER < 10500 */ + #if PNGCRUSH_LIBPNG_VER >= 10500 /* "#include <zlib.h>" is not provided by libpng15 */ #ifdef PNGCRUSH_H @@ -1080,10 +1132,6 @@ Version 1.1.4: added ability to restrict brute_force to one or more filter # include <zlib.h> #endif -# ifndef PNG_UNUSED -# define PNG_UNUSED(param) (void)param; -# endif - /* Not provided by libpng16 */ # include <string.h> @@ -1114,7 +1162,7 @@ Version 1.1.4: added ability to restrict brute_force to one or more filter # define png_memset memset # endif # endif -#endif +#endif /* PNGCRUSH_LIBPNG_VER >= 10500 */ #if PNGCRUSH_LIBPNG_VER < 10800 || defined(PNGCRUSH_H) @@ -1365,7 +1413,7 @@ png_uint_32 pngcrush_crc; #define STR_BUF_SIZE 256 #define MAX_IDAT_SIZE 524288L -#define MAX_METHODS 150 +#define MAX_METHODS 200 #define MAX_METHODSP1 (MAX_METHODS+1) #define DEFAULT_METHODS 10 #define FAKE_PAUSE_STRING "P" @@ -1417,7 +1465,11 @@ static int found_cHRM = 0; static int premultiply = 0; static int interlace_method = 0; +#if (PNG_LIBPNG_VER < 10400) +png_size_t max_bytes; +#else png_alloc_size_t max_bytes; +#endif /* 0: not premultipled * 1: premultiplied input (input has .ppng suffix) @@ -1683,8 +1735,8 @@ int pngcrush_crc_finish(png_structp png_ptr, png_uint_32 skip); void png_save_uint_32(png_bytep buf, png_uint_32 i); #ifdef PNG_USER_MEM_SUPPORTED -png_voidp png_debug_malloc(png_structp png_ptr, png_uint_32 size); -void png_debug_free(png_structp png_ptr, png_voidp ptr); +png_voidp pngcrush_debug_malloc(png_structp png_ptr, png_uint_32 size); +void pngcrush_debug_free(png_structp png_ptr, png_voidp ptr); #endif void pngcrush_pause(void); @@ -2036,13 +2088,13 @@ static int maximum_allocation = 0; -png_voidp png_debug_malloc(png_structp png_ptr, png_uint_32 size) +png_voidp pngcrush_debug_malloc(png_structp png_ptr, png_uint_32 size) { /* * png_malloc has already tested for NULL; png_create_struct calls - * png_debug_malloc directly (with png_ptr == NULL prior to libpng-1.2.0 - * which is OK since we are not using a user mem_ptr) + * pngcrush_debug_malloc directly (with png_ptr == NULL prior to + * libpng-1.2.0 which is OK since we are not using a user mem_ptr) */ if (size == 0) @@ -2074,10 +2126,10 @@ png_voidp png_debug_malloc(png_structp png_ptr, png_uint_32 size) /* Free a pointer. It is removed from the list at the same time. */ -void png_debug_free(png_structp png_ptr, png_voidp ptr) +void pngcrush_debug_free(png_structp png_ptr, png_voidp ptr) { if (png_ptr == NULL) - fprintf(STDERR, "NULL pointer to png_debug_free.\n"); + fprintf(STDERR, "NULL pointer to pngcrush_debug_free.\n"); if (ptr == 0) { #if 0 /* This happens all the time. */ fprintf(STDERR, "WARNING: freeing NULL pointer\n"); @@ -2424,7 +2476,6 @@ void show_result(void) } #endif /* PNG_USER_MEM_SUPPORTED */ if (found_acTL_chunk == 2) - if (verbose > 0) fprintf(STDERR, " **** Discarded APNG chunks. ****\n"); } @@ -2806,6 +2857,7 @@ int main(int argc, char *argv[]) } row_buf = (png_bytep) NULL; + P2(" row_buf = %p\n",row_buf); number_of_open_files = 0; do_color_count = 0; do_color_count = do_color_count; /* silence compiler warning */ @@ -3877,16 +3929,17 @@ int main(int argc, char *argv[]) { # ifdef PNG_USER_MEM_SUPPORTED - mng_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, - (png_voidp) NULL, (png_error_ptr) png_cexcept_error, - (png_error_ptr) NULL, (png_voidp) NULL, - (png_malloc_ptr) png_debug_malloc, - (png_free_ptr) png_debug_free); -# else - mng_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - (png_voidp) NULL, (png_error_ptr) png_cexcept_error, - (png_error_ptr) NULL); + if (verbose > 0) + mng_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, + (png_voidp) NULL, (png_error_ptr) png_cexcept_error, + (png_error_ptr) NULL, (png_voidp) NULL, + (png_malloc_ptr) pngcrush_debug_malloc, + (png_free_ptr) pngcrush_debug_free); + else # endif + mng_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, + (png_voidp) NULL, (png_error_ptr) png_cexcept_error, + (png_error_ptr) NULL); if (mng_ptr == NULL) fprintf(STDERR, "pngcrush could not create mng_ptr"); @@ -4250,16 +4303,17 @@ int main(int argc, char *argv[]) png_uint_32 row_length; P1( "Allocating read and write structures\n"); #ifdef PNG_USER_MEM_SUPPORTED - read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, - (png_voidp) NULL, (png_error_ptr) png_cexcept_error, - (png_error_ptr) NULL, (png_voidp) NULL, - (png_malloc_ptr) png_debug_malloc, - (png_free_ptr) png_debug_free); -#else - read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, - (png_voidp) NULL, (png_error_ptr) png_cexcept_error, - (png_error_ptr) NULL); + if (verbose > 0) + read_ptr = png_create_read_struct_2(PNG_LIBPNG_VER_STRING, + (png_voidp) NULL, (png_error_ptr) png_cexcept_error, + (png_error_ptr) NULL, (png_voidp) NULL, + (png_malloc_ptr) pngcrush_debug_malloc, + (png_free_ptr) pngcrush_debug_free); + else #endif /* PNG_USER_MEM_SUPPORTED */ + read_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, + (png_voidp) NULL, (png_error_ptr) png_cexcept_error, + (png_error_ptr) NULL); if (read_ptr == NULL) Throw "pngcrush could not create read_ptr"; @@ -4318,16 +4372,19 @@ int main(int argc, char *argv[]) if (nosave == 0) { #ifdef PNG_USER_MEM_SUPPORTED - write_ptr = png_create_write_struct_2(PNG_LIBPNG_VER_STRING, - (png_voidp) NULL, (png_error_ptr) png_cexcept_error, - (png_error_ptr) NULL, (png_voidp) NULL, - (png_malloc_ptr) png_debug_malloc, - (png_free_ptr) png_debug_free); -#else - write_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, - (png_voidp) NULL, (png_error_ptr) png_cexcept_error, - (png_error_ptr) NULL); + if (verbose > 0) + write_ptr = png_create_write_struct_2( + PNG_LIBPNG_VER_STRING, + (png_voidp) NULL, (png_error_ptr) png_cexcept_error, + (png_error_ptr) NULL, (png_voidp) NULL, + (png_malloc_ptr) pngcrush_debug_malloc, + (png_free_ptr) pngcrush_debug_free); + else #endif + write_ptr = png_create_write_struct( + PNG_LIBPNG_VER_STRING, + (png_voidp) NULL, (png_error_ptr) png_cexcept_error, + (png_error_ptr) NULL); if (write_ptr == NULL) Throw "pngcrush could not create write_ptr"; @@ -4809,9 +4866,10 @@ int main(int argc, char *argv[]) need_expand = 1; } - if (output_color_type && output_color_type != 3 && + if (output_color_type != 0 && + output_color_type != 3 && output_bit_depth < 8) - output_bit_depth = 8; + output_bit_depth = 8; if ((output_color_type == 2 || output_color_type == 6) @@ -4832,6 +4890,7 @@ int main(int argc, char *argv[]) { png_set_packing(read_ptr); } + if (output_color_type == 0 && output_bit_depth < 8) { png_color_8 true_bits; @@ -4934,11 +4993,12 @@ int main(int argc, char *argv[]) { if (keep_chunk("bKGD", argv)) { - if ((input_color_type == 2 - || input_color_type == 6) - && (output_color_type == 0 - || output_color_type == 4)) - background->gray = background->green; + if ((input_color_type == 2 || + input_color_type == 6) && + (output_color_type == 0 || + output_color_type == 4)) + background->gray = background->green; + png_set_bKGD(write_ptr, write_info_ptr, background); } @@ -4973,16 +5033,17 @@ int main(int argc, char *argv[]) if (found_cHRM && png_get_cHRM_fixed (read_ptr, read_info_ptr, &white_x, &white_y, &red_x, &red_y, &green_x, &green_y, &blue_x, - &blue_y)) { - if (keep_chunk("cHRM", argv)) + &blue_y)) { + if (keep_chunk("cHRM", argv)) + { png_set_cHRM_fixed(write_ptr, write_info_ptr, white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y); + } } - } } #else { @@ -5789,19 +5850,26 @@ int main(int argc, char *argv[]) * does not check the PNG_FLAG_ROW_INIT flag and does not * initialize the row or issue a warning. * - * However, pngcrush fails to read interlaced PNGs properly - * when png_read_update_info() is called here. */ - - /* png_read_update_info(read_ptr, read_info_ptr); */ #ifdef PNGCRUSH_H png_read_transform_info(read_ptr, read_info_ptr); #else - /* Some pngcrush capabilities are lacking with the system + /* Some pngcrush capabilities are lacking when the system * libpng is used instead of the one bundled with pngcrush * * To do: list those capabilities here */ + + /* pngcrush fails to read interlaced PNGs properly + * when png_read_update_info() is called here. + */ + + /* png_read_update_info(read_ptr, read_info_ptr); */ + + /* Workaround is to multiply rowbytes by 8/bit_depth + * to allow for unpacking, wherever we allocate a + * row buffer. + */ #endif /* This is the default case (nosave == 1 -> perf-testing @@ -5906,6 +5974,13 @@ int main(int argc, char *argv[]) png_uint_32 h = height; rowbytes = png_get_rowbytes(read_ptr, read_info_ptr); +#ifndef PNGCRUSH_H + /* We must do this because we could not call + * png_read_update_info(). + */ + if (input_bit_depth < 8) + rowbytes *= 8/input_bit_depth; +#endif if (rowbytes < 16384 && h < 16384) { if (rowbytes * h < 16384) @@ -5918,7 +5993,11 @@ int main(int argc, char *argv[]) */ png_uint_32 w = width; unsigned int pd = channels * output_bit_depth; +#if (PNG_LIBPNG_VER < 10400) + png_size_t cb_base; +#else png_alloc_size_t cb_base; +#endif int interlace_pass; for (cb_base=0, interlace_pass=0; @@ -6028,6 +6107,12 @@ int main(int argc, char *argv[]) png_uint_32 rowbytes; rowbytes = png_get_rowbytes(read_ptr, read_info_ptr); +#ifndef PNGCRUSH_H + if (input_bit_depth < 8) + rowbytes *= 8/input_bit_depth; +#endif + + P2("rowbytes = %lud\n",rowbytes; rowbytes_s = (png_size_t) rowbytes; if (rowbytes == (png_uint_32) rowbytes_s) @@ -6054,6 +6139,13 @@ int main(int argc, char *argv[]) read_row_length > write_row_length ? read_row_length : write_row_length; +#ifndef PNGCRUSH_H + /* We must do this because we could not call + * png_read_update_info(). + */ + if (input_bit_depth < 8) + row_length *= 8/input_bit_depth; +#endif # ifdef PNGCRUSH_MULTIPLE_ROWS row_buf = (png_bytep) png_malloc(read_ptr, @@ -6066,6 +6158,8 @@ int main(int argc, char *argv[]) } #endif /* PNGCRUSH_LARGE */ + P2(" row_buf = %p\n",row_buf); + if (row_buf == NULL) png_error(read_ptr, "Insufficient memory to allocate row buffer"); @@ -6080,15 +6174,18 @@ int main(int argc, char *argv[]) */ } + P2("allocated rowbuf.\n"); + #ifdef PNGCRUSH_MULTIPLE_ROWS row_pointers = (png_bytepp) png_malloc(read_ptr, rows_at_a_time * sizeof(png_bytepp)); + P2("allocated row_pointers.\n"); + for (i = 0; i < rows_at_a_time; i++) row_pointers[i] = row_buf + i * row_length; #endif - P2("allocated rowbuf.\n"); pngcrush_pause(); num_pass = png_set_interlace_handling(read_ptr); @@ -6461,21 +6558,33 @@ int main(int argc, char *argv[]) } /* } GRR: added for %-navigation (2) */ - P1( "Destroying data structs\n"); + P1( "Destroying read data structs\n"); if (row_buf != (png_bytep) NULL) { + P2(" row_buf = %p\n",row_buf); + P2( "Destroying row_buf\n"); + /* Crash has been observed here when using the + * system libpng instead of the bundled one. + * It seems to have to do with the workaround for + * png_read_transform_info() not being exported + * in libpng-1.5.6 and later. + */ png_free(read_ptr, row_buf); row_buf = (png_bytep) NULL; } + P2( "Destroyed data row_buf\n"); #ifdef PNGCRUSH_MULTIPLE_ROWS if (row_pointers != (png_bytepp) NULL) { + P1( "Destroying row_pointers\n"); png_free(read_ptr, row_pointers); row_pointers = (png_bytepp) NULL; } + P2( "Destroyed data row_pointers\n"); #endif png_destroy_read_struct(&read_ptr, &read_info_ptr, &end_info_ptr); + P2( "Destroyed data structs\n"); if (nosave == 0) { #ifdef PNGCRUSH_LOCO @@ -6682,7 +6791,11 @@ int main(int argc, char *argv[]) show_result(); #ifdef PNG_iCCP_SUPPORTED if (iccp_length) + { free(iccp_text); + iccp_text = NULL; + iccp_length = 0; + } #endif if (pngcrush_must_exit) exit(0); @@ -7684,4 +7797,4 @@ void print_usage(int retval) exit(retval); } -#endif /* PNGCRUSH_LIBPNG_VER < 10700 || defined(PNGCRUSH_H) */ +#endif /* PNGCRUSH_LIBPNG_VER < 10800 || defined(PNGCRUSH_H) */ diff --git a/pngcrush.h b/pngcrush.h index af16eb20f..47b16a133 100644 --- a/pngcrush.h +++ b/pngcrush.h @@ -5,7 +5,7 @@ * license (see LICENSE, in pngcrush.c). */ -/* Special defines for pngcrush version 1.7.55 */ +/* Special defines for pngcrush version 1.7.56 */ #ifndef PNGCRUSH_H #define PNGCRUSH_H |