From d52c8eba998d7e7ecd9f8cf653f3181b02ed9b94 Mon Sep 17 00:00:00 2001 From: John Bowler Date: Wed, 8 Jun 2016 08:37:20 -0700 Subject: [PATCH] Compression changes/fixes Simplified API: change handling of PNG_IMAGE_FLAG_FAST to use PNG_COMPRESSION_HIGH_SPEED, and PNG_COMPRESSION_HIGH otherwise. Compression: add missing break statements that caused some compression settings to fall through to the 'HIGH' setting. Internal: remove png_struct::flags, it only stored the 'library mismatch' flag and that could never be accessed (because immediately after it was set the png_struct, which was on the stack, was eliminated.) Signed-off-by: John Bowler --- png.c | 37 +++++++++++++++++++------------------ pngpriv.h | 22 ---------------------- pngstruct.h | 1 - pngwrite.c | 21 ++++++--------------- pngwutil.c | 4 ++++ 5 files changed, 29 insertions(+), 56 deletions(-) diff --git a/png.c b/png.c index eb96a9913..75cb29eeb 100644 --- a/png.c +++ b/png.c @@ -175,16 +175,16 @@ png_calculate_crc(png_structrp png_ptr, png_const_voidp ptr, png_size_t length) /* Check a user supplied version number, called from both read and write * functions that create a png_struct. */ -int +static int png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) { - /* Libpng versions 1.0.0 and later are binary compatible if the version - * string matches through the second '.'; we must recompile any - * applications that use any older library version. - */ - + /* Libpng versions 1.0.0 and later are binary compatible if the version + * string matches through the second '.'; we must recompile any applications + * that use any older library version. + */ if (user_png_ver != NULL) { + int library_match = 1; int i = -1; int found_dots = 0; @@ -192,36 +192,36 @@ png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver) { i++; if (user_png_ver[i] != PNG_LIBPNG_VER_STRING[i]) - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; + library_match = 0; if (user_png_ver[i] == '.') found_dots++; - } while (found_dots < 2 && user_png_ver[i] != 0 && + } while (library_match && found_dots < 2 && user_png_ver[i] != 0 && PNG_LIBPNG_VER_STRING[i] != 0); + + if (library_match) + return 1; /* Library matches ok */ } - else - png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH; - - if ((png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) != 0) - { + /* Failure: mismatched library major version number */ #ifdef PNG_WARNINGS_SUPPORTED + { size_t pos = 0; char m[128]; pos = png_safecat(m, (sizeof m), pos, "Application built with libpng-"); + /* This is ok if user_png_ver is NULL, it appends nothing: */ pos = png_safecat(m, (sizeof m), pos, user_png_ver); pos = png_safecat(m, (sizeof m), pos, " but running with "); pos = png_safecat(m, (sizeof m), pos, PNG_LIBPNG_VER_STRING); PNG_UNUSED(pos) - png_warning(png_ptr, m); -#endif - return 0; + png_app_warning(png_ptr, m); } +#endif - /* Success return. */ - return 1; + return 0; /* Failure */ + PNG_UNUSED(png_ptr) /* if no warning */ } /* Generic function to create a png_struct for either read or write - this @@ -3431,6 +3431,7 @@ png_setting(png_structrp png_ptr, png_uint_32 setting, png_uint_32 parameter, /* No write options at present */ result = PNG_OPTION_UNSET; /* i.e. ignore it */ + break; # endif /* SET_OPTION */ default: diff --git a/pngpriv.h b/pngpriv.h index 247e43c36..a5245f790 100644 --- a/pngpriv.h +++ b/pngpriv.h @@ -618,22 +618,6 @@ #define PNG_HAVE_IEND 0x10U #define PNG_HAVE_PNG_SIGNATURE 0x20U -/* Flags for the png_ptr->flags. - * TODO: change to bit fields. - */ -#define PNG_FLAG_LIBRARY_MISMATCH 0x001U -/*#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x002U NO LONGER USED */ -/*#define PNG_FLAG_CRC_ANCILLARY_USE 0x004U NO LONGER USED */ -/*#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x008U NO LONGER USED */ -/*#define PNG_FLAG_CRC_CRITICAL_USE 0x010U NO LONGER USED */ -/*#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x020U NO LONGER USED */ -/*#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x040U NEVER USED */ -/*#define PNG_FLAG_STRIP_ERROR_TEXT 0x080U NEVER USED */ -/*#define PNG_FLAG_IDAT_ERRORS_WARN 0x100U NEVER SET */ -/*#define PNG_FLAG_BENIGN_ERRORS_WARN 0x200U NO LONGER USED */ -/*#define PNG_FLAG_APP_WARNINGS_WARN 0x400U NO LONGER USED */ -/*#define PNG_FLAG_APP_ERRORS_WARN 0x800U NO LONGER USED */ - #if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) /* See below for the definitions of the tables used in these macros */ @@ -968,12 +952,6 @@ PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr, double fp, png_const_charp text),PNG_EMPTY); #endif -/* Check the user version string for compatibility, returns false if the version - * numbers aren't compatible. - */ -PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr, - png_const_charp user_png_ver),PNG_EMPTY); - /* Internal base allocator - no messages, NULL on failure to allocate. This * does, however, call the application provided allocator and that could call * png_error (although that would be a bug in the application implementation.) diff --git a/pngstruct.h b/pngstruct.h index a66df6772..2267e7561 100644 --- a/pngstruct.h +++ b/pngstruct.h @@ -394,7 +394,6 @@ struct png_struct_def png_uint_32 chunk_length; /* Length (possibly remaining) in said chunk. */ png_uint_32 crc; /* current chunk CRC value */ - unsigned int flags; /* flags (should be bit fields) */ unsigned int mode :6; /* where we are in the PNG file */ unsigned int read_struct :1; /* this is a read (not write) struct */ unsigned int num_palette :9; /* number of color entries in palette */ diff --git a/pngwrite.c b/pngwrite.c index 0807791ff..b3ee9c89d 100644 --- a/pngwrite.c +++ b/pngwrite.c @@ -1910,21 +1910,12 @@ png_image_write_main(png_voidp argument) display->row_bytes = row_bytes; } - /* Apply 'fast' options if the flag is set. */ - if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0) - { -# ifdef PNG_WRITE_FILTER_SUPPORTED - png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS); -# endif /* WRITE_FILTER */ - /* NOTE: determined by experiment using pngstest, this reflects some - * balance between the time to write the image once and the time to read - * it about 50 times. The speed-up in pngstest was about 10-20% of the - * total (user) time on a heavily loaded system. - */ -# ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED - png_set_compression_level(png_ptr, 3); -# endif /* WRITE_CUSTOMIZE_COMPRESSION */ - } + /* Select the right compression mode based on the presence or absence of the + * 'fast' flag, this will use whatever options are available in the libpng + * build. It is always supported. + */ + png_set_compression(png_ptr, (image->flags & PNG_IMAGE_FLAG_FAST) != 0 ? + PNG_COMPRESSION_HIGH_SPEED : PNG_COMPRESSION_HIGH); /* Check for the cases that currently require a pre-transform on the row * before it is written. This only applies when the input is 16-bit and diff --git a/pngwutil.c b/pngwutil.c index 31812b66e..d01a4bf7b 100644 --- a/pngwutil.c +++ b/pngwutil.c @@ -3076,6 +3076,7 @@ png_write_IDAT(png_structrp png_ptr, int flush) default: case PNG_COMPRESSION_MEDIUM: IDAT_size = PNG_ZBUF_SIZE; + break; case PNG_COMPRESSION_HIGH_READ_SPEED: /* Assume the reader reads partial IDAT chunks (pretty much a @@ -3817,12 +3818,15 @@ png_write_start_IDAT(png_structrp png_ptr) default: /* For GCC */ case PNG_COMPRESSION_LOW: ps->filter_mask = PNG_FILTER_NONE+PNG_FILTER_SUB; + break; case PNG_COMPRESSION_MEDIUM: ps->filter_mask = PNG_FAST_FILTERS; + break; case PNG_COMPRESSION_HIGH: ps->filter_mask = PNG_ALL_FILTERS; + break; } # else /* !SELECT_FILTER */ ps->filter_mask = PNG_FILTER_NONE;