From 65b99f1c924cf7bf225f420b3cc115b66cdfbf42 Mon Sep 17 00:00:00 2001 From: skal Date: Tue, 11 Mar 2014 23:25:35 +0100 Subject: [PATCH] add a -z option to cwebp, and WebPConfigLosslessPreset() function These are presets for lossless coding, similar to zlib. The shortcut for lossless coding is now, e.g.: cwebp -z 5 in.png -o out_lossless.webp There are 10 possible values for -z parameter: 0 (fastest, lowest compression) to 9 (slowest, best compression) A reasonable tradeoff is -z 6, e.g. -z 9 can be quite slow, so use with care. This -z option is just a shortcut for some pre-defined '-lossless -m xx -q yy' combinations. Change-Id: I6ae716456456aea065469c916c2d5ca4d6c6cf04 --- examples/cwebp.c | 16 ++++++++++++++++ man/cwebp.1 | 10 +++++++++- src/enc/config.c | 20 ++++++++++++++++++++ src/webp/encode.h | 10 +++++++++- 4 files changed, 54 insertions(+), 2 deletions(-) diff --git a/examples/cwebp.c b/examples/cwebp.c index 95750c95..93d051e7 100644 --- a/examples/cwebp.c +++ b/examples/cwebp.c @@ -568,6 +568,8 @@ static void HelpLong(void) { printf(" default, photo, picture,\n"); printf(" drawing, icon, text\n"); printf(" -preset must come first, as it overwrites other parameters."); + printf(" -z ............... Activates lossless preset with given " + " level in [0:fast, ..., 9:slowest]\n"); printf("\n"); printf(" -m ............... compression method (0=fast, 6=slowest)\n"); printf(" -segments ........ number of segments to use (1..4)\n"); @@ -672,6 +674,8 @@ int main(int argc, const char *argv[]) { uint32_t background_color = 0xffffffu; int crop = 0, crop_x = 0, crop_y = 0, crop_w = 0, crop_h = 0; int resize_w = 0, resize_h = 0; + int lossless_preset = 6; + int use_lossless_preset = -1; // -1=unset, 0=don't use, 1=use it int show_progress = 0; int keep_metadata = 0; int metadata_written = 0; @@ -726,8 +730,13 @@ int main(int argc, const char *argv[]) { picture.height = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-m") && c < argc - 1) { config.method = strtol(argv[++c], NULL, 0); + use_lossless_preset = 0; // disable -z option } else if (!strcmp(argv[c], "-q") && c < argc - 1) { config.quality = (float)strtod(argv[++c], NULL); + use_lossless_preset = 0; // disable -z option + } else if (!strcmp(argv[c], "-z") && c < argc - 1) { + lossless_preset = strtol(argv[++c], NULL, 0); + if (use_lossless_preset != 0) use_lossless_preset = 1; } else if (!strcmp(argv[c], "-alpha_q") && c < argc - 1) { config.alpha_quality = strtol(argv[++c], NULL, 0); } else if (!strcmp(argv[c], "-alpha_method") && c < argc - 1) { @@ -916,6 +925,13 @@ int main(int argc, const char *argv[]) { goto Error; } + if (use_lossless_preset == 1) { + if (!WebPConfigLosslessPreset(&config, lossless_preset)) { + fprintf(stderr, "Invalid lossless preset (-z %d)\n", lossless_preset); + goto Error; + } + } + // Check for unsupported command line options for lossless mode and log // warning for such options. if (!quiet && config.lossless == 1) { diff --git a/man/cwebp.1 b/man/cwebp.1 index 9a51272a..dfa02333 100644 --- a/man/cwebp.1 +++ b/man/cwebp.1 @@ -1,5 +1,5 @@ .\" Hey, EMACS: -*- nroff -*- -.TH CWEBP 1 "December 12, 2013" +.TH CWEBP 1 "March 11, 2014" .SH NAME cwebp \- compress an image file to a WebP file .SH SYNOPSIS @@ -32,6 +32,14 @@ Print the version number (as major.minor.revision) and exit. .BI \-q " float Specify the compression factor for RGB channels between 0 and 100. The default is 75. +.TP +.BI \-z " int +Switch on \fBlossless\fP compression mode with the specified level between 0 +and 9, with level 0 being the fastest, 9 being the slowest. Fast mode +produce larger file size than fast ones. A good default is \-z 6. +This option is actually a shortcut for some predefined setting for quality +and method. If options \-q or \-m are subsequently used, they will invalidate +the effect of this \-z option. .br In case of lossy compression (default), a small factor produces a smaller file with lower quality. Best quality is achieved by using a value of 100. diff --git a/src/enc/config.c b/src/enc/config.c index af7f0b09..6531438f 100644 --- a/src/enc/config.c +++ b/src/enc/config.c @@ -138,3 +138,23 @@ int WebPValidateConfig(const WebPConfig* config) { //------------------------------------------------------------------------------ +#define MAX_LEVEL 9 + +// Mapping between -z level and -m / -q parameter settings. +static const struct { + uint8_t method_; + uint8_t quality_; +} kLosslessPresets[MAX_LEVEL + 1] = { + { 0, 0 }, { 1, 20 }, { 2, 25 }, { 3, 30 }, { 3, 50 }, + { 4, 50 }, { 4, 75 }, { 4, 90 }, { 5, 90 }, { 6, 100 } +}; + +int WebPConfigLosslessPreset(WebPConfig* config, int level) { + if (config == NULL || level < 0 || level > MAX_LEVEL) return 0; + config->lossless = 1; + config->method = kLosslessPresets[level].method_; + config->quality = kLosslessPresets[level].quality_; + return 1; +} + +//------------------------------------------------------------------------------ diff --git a/src/webp/encode.h b/src/webp/encode.h index e3c03969..0d9b5231 100644 --- a/src/webp/encode.h +++ b/src/webp/encode.h @@ -20,7 +20,7 @@ extern "C" { #endif -#define WEBP_ENCODER_ABI_VERSION 0x0202 // MAJOR(8b) + MINOR(8b) +#define WEBP_ENCODER_ABI_VERSION 0x0203 // MAJOR(8b) + MINOR(8b) // Note: forward declaring enumerations is not allowed in (strict) C and C++, // the types are left here for reference. @@ -167,6 +167,14 @@ static WEBP_INLINE int WebPConfigPreset(WebPConfig* config, WEBP_ENCODER_ABI_VERSION); } +// Activate the lossless compression mode with the desired efficiency level +// between 0 (fastest, lowest compression) and 9 (slower, best compression). +// A good default level is '6', providing a fair tradeoff between compression +// speed and final compressed size. +// This function will overwrite several fields from config: 'method', 'quality' +// and 'lossless'. Returns false in case of parameter error. +WEBP_EXTERN(int) WebPConfigLosslessPreset(WebPConfig* config, int level); + // Returns true if 'config' is non-NULL and all configuration parameters are // within their valid ranges. WEBP_EXTERN(int) WebPValidateConfig(const WebPConfig* config);