mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 06:08:21 +01:00
Enc: add a qmin / qmax range for quality factor
This is particularly useful for multi-pass search (but not only), to prevent the search from going over or below a reasonable threshold. E.g.: 'cwebp -qrange 50 80 ...' will prevent any unreasonable degradation. new cwebp option: -qrange min max Change-Id: I59f394533535fc20b6996bc0895f4301476d5eff
This commit is contained in:
parent
0fa56f307f
commit
6a0ff35872
3
README
3
README
@ -254,6 +254,8 @@ Options:
|
|||||||
-partition_limit <int> . limit quality to fit the 512k limit on
|
-partition_limit <int> . limit quality to fit the 512k limit on
|
||||||
the first partition (0=no degradation ... 100=full)
|
the first partition (0=no degradation ... 100=full)
|
||||||
-pass <int> ............ analysis pass number (1..10)
|
-pass <int> ............ analysis pass number (1..10)
|
||||||
|
-qrange <min> <max> .... specifies the permissible quality range
|
||||||
|
(default: 0 100)
|
||||||
-crop <x> <y> <w> <h> .. crop picture with the given rectangle
|
-crop <x> <y> <w> <h> .. crop picture with the given rectangle
|
||||||
-resize <w> <h> ........ resize picture (after any cropping)
|
-resize <w> <h> ........ resize picture (after any cropping)
|
||||||
-mt .................... use multi-threading if available
|
-mt .................... use multi-threading if available
|
||||||
@ -294,6 +296,7 @@ Experimental Options:
|
|||||||
-af .................... auto-adjust filter strength
|
-af .................... auto-adjust filter strength
|
||||||
-pre <int> ............. pre-processing filter
|
-pre <int> ............. pre-processing filter
|
||||||
|
|
||||||
|
|
||||||
The main options you might want to try in order to further tune the
|
The main options you might want to try in order to further tune the
|
||||||
visual quality are:
|
visual quality are:
|
||||||
-preset
|
-preset
|
||||||
|
@ -565,6 +565,8 @@ static void HelpLong(void) {
|
|||||||
printf(" "
|
printf(" "
|
||||||
"the first partition (0=no degradation ... 100=full)\n");
|
"the first partition (0=no degradation ... 100=full)\n");
|
||||||
printf(" -pass <int> ............ analysis pass number (1..10)\n");
|
printf(" -pass <int> ............ analysis pass number (1..10)\n");
|
||||||
|
printf(" -qrange <min> <max> .... specifies the permissible quality range\n"
|
||||||
|
" (default: 0 100)\n");
|
||||||
printf(" -crop <x> <y> <w> <h> .. crop picture with the given rectangle\n");
|
printf(" -crop <x> <y> <w> <h> .. crop picture with the given rectangle\n");
|
||||||
printf(" -resize <w> <h> ........ resize picture (after any cropping)\n");
|
printf(" -resize <w> <h> ........ resize picture (after any cropping)\n");
|
||||||
printf(" -mt .................... use multi-threading if available\n");
|
printf(" -mt .................... use multi-threading if available\n");
|
||||||
@ -691,9 +693,9 @@ int main(int argc, const char* argv[]) {
|
|||||||
} else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
|
} else if (!strcmp(argv[c], "-H") || !strcmp(argv[c], "-longhelp")) {
|
||||||
HelpLong();
|
HelpLong();
|
||||||
FREE_WARGV_AND_RETURN(0);
|
FREE_WARGV_AND_RETURN(0);
|
||||||
} else if (!strcmp(argv[c], "-o") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-o") && c + 1 < argc) {
|
||||||
out_file = (const char*)GET_WARGV(argv, ++c);
|
out_file = (const char*)GET_WARGV(argv, ++c);
|
||||||
} else if (!strcmp(argv[c], "-d") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-d") && c + 1 < argc) {
|
||||||
dump_file = (const char*)GET_WARGV(argv, ++c);
|
dump_file = (const char*)GET_WARGV(argv, ++c);
|
||||||
config.show_compressed = 1;
|
config.show_compressed = 1;
|
||||||
} else if (!strcmp(argv[c], "-print_psnr")) {
|
} else if (!strcmp(argv[c], "-print_psnr")) {
|
||||||
@ -707,7 +709,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
print_distortion = 2;
|
print_distortion = 2;
|
||||||
} else if (!strcmp(argv[c], "-short")) {
|
} else if (!strcmp(argv[c], "-short")) {
|
||||||
++short_output;
|
++short_output;
|
||||||
} else if (!strcmp(argv[c], "-s") && c < argc - 2) {
|
} else if (!strcmp(argv[c], "-s") && c + 2 < argc) {
|
||||||
picture.width = ExUtilGetInt(argv[++c], 0, &parse_error);
|
picture.width = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
picture.height = ExUtilGetInt(argv[++c], 0, &parse_error);
|
picture.height = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 ||
|
if (picture.width > WEBP_MAX_DIMENSION || picture.width < 0 ||
|
||||||
@ -717,30 +719,30 @@ int main(int argc, const char* argv[]) {
|
|||||||
picture.width, picture.height);
|
picture.width, picture.height);
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[c], "-m") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-m") && c + 1 < argc) {
|
||||||
config.method = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.method = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
use_lossless_preset = 0; // disable -z option
|
use_lossless_preset = 0; // disable -z option
|
||||||
} else if (!strcmp(argv[c], "-q") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-q") && c + 1 < argc) {
|
||||||
config.quality = ExUtilGetFloat(argv[++c], &parse_error);
|
config.quality = ExUtilGetFloat(argv[++c], &parse_error);
|
||||||
use_lossless_preset = 0; // disable -z option
|
use_lossless_preset = 0; // disable -z option
|
||||||
} else if (!strcmp(argv[c], "-z") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-z") && c + 1 < argc) {
|
||||||
lossless_preset = ExUtilGetInt(argv[++c], 0, &parse_error);
|
lossless_preset = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
if (use_lossless_preset != 0) use_lossless_preset = 1;
|
if (use_lossless_preset != 0) use_lossless_preset = 1;
|
||||||
} else if (!strcmp(argv[c], "-alpha_q") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-alpha_q") && c + 1 < argc) {
|
||||||
config.alpha_quality = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.alpha_quality = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-alpha_method") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-alpha_method") && c + 1 < argc) {
|
||||||
config.alpha_compression = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.alpha_compression = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-alpha_cleanup")) {
|
} else if (!strcmp(argv[c], "-alpha_cleanup")) {
|
||||||
// This flag is obsolete, does opposite of -exact.
|
// This flag is obsolete, does opposite of -exact.
|
||||||
config.exact = 0;
|
config.exact = 0;
|
||||||
} else if (!strcmp(argv[c], "-exact")) {
|
} else if (!strcmp(argv[c], "-exact")) {
|
||||||
config.exact = 1;
|
config.exact = 1;
|
||||||
} else if (!strcmp(argv[c], "-blend_alpha") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-blend_alpha") && c + 1 < argc) {
|
||||||
blend_alpha = 1;
|
blend_alpha = 1;
|
||||||
// background color is given in hex with an optional '0x' prefix
|
// background color is given in hex with an optional '0x' prefix
|
||||||
background_color = ExUtilGetInt(argv[++c], 16, &parse_error);
|
background_color = ExUtilGetInt(argv[++c], 16, &parse_error);
|
||||||
background_color = background_color & 0x00ffffffu;
|
background_color = background_color & 0x00ffffffu;
|
||||||
} else if (!strcmp(argv[c], "-alpha_filter") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-alpha_filter") && c + 1 < argc) {
|
||||||
++c;
|
++c;
|
||||||
if (!strcmp(argv[c], "none")) {
|
if (!strcmp(argv[c], "none")) {
|
||||||
config.alpha_filtering = 0;
|
config.alpha_filtering = 0;
|
||||||
@ -756,10 +758,10 @@ int main(int argc, const char* argv[]) {
|
|||||||
keep_alpha = 0;
|
keep_alpha = 0;
|
||||||
} else if (!strcmp(argv[c], "-lossless")) {
|
} else if (!strcmp(argv[c], "-lossless")) {
|
||||||
config.lossless = 1;
|
config.lossless = 1;
|
||||||
} else if (!strcmp(argv[c], "-near_lossless") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-near_lossless") && c + 1 < argc) {
|
||||||
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.near_lossless = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
config.lossless = 1; // use near-lossless only with lossless
|
config.lossless = 1; // use near-lossless only with lossless
|
||||||
} else if (!strcmp(argv[c], "-hint") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-hint") && c + 1 < argc) {
|
||||||
++c;
|
++c;
|
||||||
if (!strcmp(argv[c], "photo")) {
|
if (!strcmp(argv[c], "photo")) {
|
||||||
config.image_hint = WEBP_HINT_PHOTO;
|
config.image_hint = WEBP_HINT_PHOTO;
|
||||||
@ -771,13 +773,13 @@ int main(int argc, const char* argv[]) {
|
|||||||
fprintf(stderr, "Error! Unrecognized image hint: %s\n", argv[c]);
|
fprintf(stderr, "Error! Unrecognized image hint: %s\n", argv[c]);
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[c], "-size") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-size") && c + 1 < argc) {
|
||||||
config.target_size = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.target_size = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-psnr") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-psnr") && c + 1 < argc) {
|
||||||
config.target_PSNR = ExUtilGetFloat(argv[++c], &parse_error);
|
config.target_PSNR = ExUtilGetFloat(argv[++c], &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-sns") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-sns") && c + 1 < argc) {
|
||||||
config.sns_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.sns_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-f") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-f") && c + 1 < argc) {
|
||||||
config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.filter_strength = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-af")) {
|
} else if (!strcmp(argv[c], "-af")) {
|
||||||
config.autofilter = 1;
|
config.autofilter = 1;
|
||||||
@ -791,27 +793,32 @@ int main(int argc, const char* argv[]) {
|
|||||||
config.filter_type = 1;
|
config.filter_type = 1;
|
||||||
} else if (!strcmp(argv[c], "-nostrong")) {
|
} else if (!strcmp(argv[c], "-nostrong")) {
|
||||||
config.filter_type = 0;
|
config.filter_type = 0;
|
||||||
} else if (!strcmp(argv[c], "-sharpness") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-sharpness") && c + 1 < argc) {
|
||||||
config.filter_sharpness = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.filter_sharpness = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-sharp_yuv")) {
|
} else if (!strcmp(argv[c], "-sharp_yuv")) {
|
||||||
config.use_sharp_yuv = 1;
|
config.use_sharp_yuv = 1;
|
||||||
} else if (!strcmp(argv[c], "-pass") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-pass") && c + 1 < argc) {
|
||||||
config.pass = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.pass = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-pre") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-qrange") && c + 2 < argc) {
|
||||||
|
config.qmin = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
|
config.qmax = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
|
if (config.qmin < 0) config.qmin = 0;
|
||||||
|
if (config.qmax > 100) config.qmax = 100;
|
||||||
|
} else if (!strcmp(argv[c], "-pre") && c + 1 < argc) {
|
||||||
config.preprocessing = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.preprocessing = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-segments") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-segments") && c + 1 < argc) {
|
||||||
config.segments = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.segments = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-partition_limit") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-partition_limit") && c + 1 < argc) {
|
||||||
config.partition_limit = ExUtilGetInt(argv[++c], 0, &parse_error);
|
config.partition_limit = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-map") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-map") && c + 1 < argc) {
|
||||||
picture.extra_info_type = ExUtilGetInt(argv[++c], 0, &parse_error);
|
picture.extra_info_type = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-crop") && c < argc - 4) {
|
} else if (!strcmp(argv[c], "-crop") && c + 4 < argc) {
|
||||||
crop = 1;
|
crop = 1;
|
||||||
crop_x = ExUtilGetInt(argv[++c], 0, &parse_error);
|
crop_x = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
crop_y = ExUtilGetInt(argv[++c], 0, &parse_error);
|
crop_y = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
crop_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
crop_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
crop_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
crop_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
} else if (!strcmp(argv[c], "-resize") && c < argc - 2) {
|
} else if (!strcmp(argv[c], "-resize") && c + 2 < argc) {
|
||||||
resize_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
resize_w = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
resize_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
resize_h = ExUtilGetInt(argv[++c], 0, &parse_error);
|
||||||
#ifndef WEBP_DLL
|
#ifndef WEBP_DLL
|
||||||
@ -827,7 +834,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
show_progress = 1;
|
show_progress = 1;
|
||||||
} else if (!strcmp(argv[c], "-quiet")) {
|
} else if (!strcmp(argv[c], "-quiet")) {
|
||||||
quiet = 1;
|
quiet = 1;
|
||||||
} else if (!strcmp(argv[c], "-preset") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-preset") && c + 1 < argc) {
|
||||||
WebPPreset preset;
|
WebPPreset preset;
|
||||||
++c;
|
++c;
|
||||||
if (!strcmp(argv[c], "default")) {
|
if (!strcmp(argv[c], "default")) {
|
||||||
@ -850,7 +857,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
fprintf(stderr, "Error! Could initialize configuration with preset.\n");
|
fprintf(stderr, "Error! Could initialize configuration with preset.\n");
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
} else if (!strcmp(argv[c], "-metadata") && c < argc - 1) {
|
} else if (!strcmp(argv[c], "-metadata") && c + 1 < argc) {
|
||||||
static const struct {
|
static const struct {
|
||||||
const char* option;
|
const char* option;
|
||||||
int flag;
|
int flag;
|
||||||
@ -898,7 +905,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
} else if (!strcmp(argv[c], "-v")) {
|
} else if (!strcmp(argv[c], "-v")) {
|
||||||
verbose = 1;
|
verbose = 1;
|
||||||
} else if (!strcmp(argv[c], "--")) {
|
} else if (!strcmp(argv[c], "--")) {
|
||||||
if (c < argc - 1) in_file = (const char*)GET_WARGV(argv, ++c);
|
if (c + 1 < argc) in_file = (const char*)GET_WARGV(argv, ++c);
|
||||||
break;
|
break;
|
||||||
} else if (argv[c][0] == '-') {
|
} else if (argv[c][0] == '-') {
|
||||||
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
|
fprintf(stderr, "Error! Unknown option '%s'\n", argv[c]);
|
||||||
|
@ -134,6 +134,13 @@ options \fB\-size\fP or \fB\-psnr\fP. Maximum value is 10, default is 1.
|
|||||||
If options \fB\-size\fP or \fB\-psnr\fP were used, but \fB\-pass\fP wasn't
|
If options \fB\-size\fP or \fB\-psnr\fP were used, but \fB\-pass\fP wasn't
|
||||||
specified, a default value of '6' passes will be used.
|
specified, a default value of '6' passes will be used.
|
||||||
.TP
|
.TP
|
||||||
|
.BI \-qrange " int int
|
||||||
|
Specifies the permissible interval for the quality factor. This is particularly
|
||||||
|
useful when using multi-pass (\fB\-size\fP or \fB\-psnr\fP options).
|
||||||
|
Default is 0 100.
|
||||||
|
If the quality factor is outside this range, it will be clamped.
|
||||||
|
If the minimum value must be less or equal to the maximum one.
|
||||||
|
.TP
|
||||||
.B \-af
|
.B \-af
|
||||||
Turns auto\-filter on. This algorithm will spend additional time optimizing
|
Turns auto\-filter on. This algorithm will spend additional time optimizing
|
||||||
the filtering strength to reach a well\-balanced quality.
|
the filtering strength to reach a well\-balanced quality.
|
||||||
|
@ -39,6 +39,8 @@ int WebPConfigInitInternal(WebPConfig* config,
|
|||||||
config->partitions = 0;
|
config->partitions = 0;
|
||||||
config->segments = 4;
|
config->segments = 4;
|
||||||
config->pass = 1;
|
config->pass = 1;
|
||||||
|
config->qmin = 0;
|
||||||
|
config->qmax = 100;
|
||||||
config->show_compressed = 0;
|
config->show_compressed = 0;
|
||||||
config->preprocessing = 0;
|
config->preprocessing = 0;
|
||||||
config->autofilter = 0;
|
config->autofilter = 0;
|
||||||
@ -106,6 +108,9 @@ int WebPValidateConfig(const WebPConfig* config) {
|
|||||||
if (config->filter_type < 0 || config->filter_type > 1) return 0;
|
if (config->filter_type < 0 || config->filter_type > 1) return 0;
|
||||||
if (config->autofilter < 0 || config->autofilter > 1) return 0;
|
if (config->autofilter < 0 || config->autofilter > 1) return 0;
|
||||||
if (config->pass < 1 || config->pass > 10) return 0;
|
if (config->pass < 1 || config->pass > 10) return 0;
|
||||||
|
if (config->qmin < 0 || config->qmax > 100 || config->qmin > config->qmax) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (config->show_compressed < 0 || config->show_compressed > 1) return 0;
|
if (config->show_compressed < 0 || config->show_compressed > 1) return 0;
|
||||||
if (config->preprocessing < 0 || config->preprocessing > 7) return 0;
|
if (config->preprocessing < 0 || config->preprocessing > 7) return 0;
|
||||||
if (config->partitions < 0 || config->partitions > 3) return 0;
|
if (config->partitions < 0 || config->partitions > 3) return 0;
|
||||||
|
@ -31,10 +31,15 @@
|
|||||||
// we allow 2k of extra head-room in PARTITION0 limit.
|
// we allow 2k of extra head-room in PARTITION0 limit.
|
||||||
#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11)
|
#define PARTITION0_SIZE_LIMIT ((VP8_MAX_PARTITION0_SIZE - 2048ULL) << 11)
|
||||||
|
|
||||||
|
static float Clamp(float v, float min, float max) {
|
||||||
|
return (v < min) ? min : (v > max) ? max : v;
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct { // struct for organizing convergence in either size or PSNR
|
typedef struct { // struct for organizing convergence in either size or PSNR
|
||||||
int is_first;
|
int is_first;
|
||||||
float dq;
|
float dq;
|
||||||
float q, last_q;
|
float q, last_q;
|
||||||
|
float qmin, qmax;
|
||||||
double value, last_value; // PSNR or size
|
double value, last_value; // PSNR or size
|
||||||
double target;
|
double target;
|
||||||
int do_size_search;
|
int do_size_search;
|
||||||
@ -47,7 +52,9 @@ static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) {
|
|||||||
|
|
||||||
s->is_first = 1;
|
s->is_first = 1;
|
||||||
s->dq = 10.f;
|
s->dq = 10.f;
|
||||||
s->q = s->last_q = enc->config_->quality;
|
s->qmin = enc->config_->qmin;
|
||||||
|
s->qmax = enc->config_->qmax;
|
||||||
|
s->q = s->last_q = Clamp(enc->config_->quality, s->qmin, s->qmax);
|
||||||
s->target = do_size_search ? (double)target_size
|
s->target = do_size_search ? (double)target_size
|
||||||
: (target_PSNR > 0.) ? target_PSNR
|
: (target_PSNR > 0.) ? target_PSNR
|
||||||
: 40.; // default, just in case
|
: 40.; // default, just in case
|
||||||
@ -56,10 +63,6 @@ static int InitPassStats(const VP8Encoder* const enc, PassStats* const s) {
|
|||||||
return do_size_search;
|
return do_size_search;
|
||||||
}
|
}
|
||||||
|
|
||||||
static float Clamp(float v, float min, float max) {
|
|
||||||
return (v < min) ? min : (v > max) ? max : v;
|
|
||||||
}
|
|
||||||
|
|
||||||
static float ComputeNextQ(PassStats* const s) {
|
static float ComputeNextQ(PassStats* const s) {
|
||||||
float dq;
|
float dq;
|
||||||
if (s->is_first) {
|
if (s->is_first) {
|
||||||
@ -75,7 +78,7 @@ static float ComputeNextQ(PassStats* const s) {
|
|||||||
s->dq = Clamp(dq, -30.f, 30.f);
|
s->dq = Clamp(dq, -30.f, 30.f);
|
||||||
s->last_q = s->q;
|
s->last_q = s->q;
|
||||||
s->last_value = s->value;
|
s->last_value = s->value;
|
||||||
s->q = Clamp(s->q + s->dq, 0.f, 100.f);
|
s->q = Clamp(s->q + s->dq, s->qmin, s->qmax);
|
||||||
return s->q;
|
return s->q;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -848,9 +851,10 @@ int VP8EncTokenLoop(VP8Encoder* const enc) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if (DEBUG_SEARCH > 0)
|
#if (DEBUG_SEARCH > 0)
|
||||||
printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf\n",
|
printf("#%2d metric:%.1lf -> %.1lf last_q=%.2lf q=%.2lf dq=%.2lf "
|
||||||
|
" range:[%.1f, %.1f]\n",
|
||||||
num_pass_left, stats.last_value, stats.value,
|
num_pass_left, stats.last_value, stats.value,
|
||||||
stats.last_q, stats.q, stats.dq);
|
stats.last_q, stats.q, stats.dq, stats.qmin, stats.qmax);
|
||||||
#endif
|
#endif
|
||||||
if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) {
|
if (enc->max_i4_header_bits_ > 0 && size_p0 > PARTITION0_SIZE_LIMIT) {
|
||||||
++num_pass_left;
|
++num_pass_left;
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WEBP_ENCODER_ABI_VERSION 0x020f // MAJOR(8b) + MINOR(8b)
|
#define WEBP_ENCODER_ABI_VERSION 0x0210 // MAJOR(8b) + MINOR(8b)
|
||||||
|
|
||||||
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
|
// Note: forward declaring enumerations is not allowed in (strict) C and C++,
|
||||||
// the types are left here for reference.
|
// the types are left here for reference.
|
||||||
@ -121,6 +121,8 @@ struct WebPConfig {
|
|||||||
int alpha_quality; // Between 0 (smallest size) and 100 (lossless).
|
int alpha_quality; // Between 0 (smallest size) and 100 (lossless).
|
||||||
// Default is 100.
|
// Default is 100.
|
||||||
int pass; // number of entropy-analysis passes (in [1..10]).
|
int pass; // number of entropy-analysis passes (in [1..10]).
|
||||||
|
int qmin; // minimum permissible quality factor
|
||||||
|
int qmax; // maximum permissible quality factor
|
||||||
|
|
||||||
int show_compressed; // if true, export the compressed picture back.
|
int show_compressed; // if true, export the compressed picture back.
|
||||||
// In-loop filtering is not applied.
|
// In-loop filtering is not applied.
|
||||||
|
Loading…
Reference in New Issue
Block a user