mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-25 13:18:22 +01:00
add a -partition_limit option to limit the number of bits used by intra4x4
Although it degrades quality, this option is useful to avoid the 512k limit for partition #0. If not enough to reach the lower bound of 4bits per macroblock header, one should also limit the number of segments used (down to -segments 1) See the man file for extra details. Change-Id: Ia59ffac13176c85b809ddd6340d37b54ee9487ea
This commit is contained in:
parent
cd12b4b0ac
commit
900286e091
2
README
2
README
@ -140,6 +140,8 @@ options:
|
||||
-f <int> ............... filter strength (0=off..100)
|
||||
-sharpness <int> ....... filter sharpness (0:most .. 7:least sharp)
|
||||
-strong ................ use strong filter instead of simple.
|
||||
-partition_limit <int> . limit quality to fit the 512k limit on
|
||||
the first partition (0=no degradation ... 100=full)
|
||||
-alpha_comp <int> ...... set the transparency-compression
|
||||
-noalpha ............... discard any transparency information.
|
||||
-pass <int> ............ analysis pass number (1..10)
|
||||
|
@ -676,6 +676,9 @@ static void HelpLong(void) {
|
||||
printf(" -sharpness <int> ....... "
|
||||
"filter sharpness (0:most .. 7:least sharp)\n");
|
||||
printf(" -strong ................ use strong filter instead of simple.\n");
|
||||
printf(" -partition_limit <int> . limit quality to fit the 512k limit on\n");
|
||||
printf(" "
|
||||
"the first partition (0=no degradation ... 100=full)\n");
|
||||
printf(" -alpha_comp <int> ...... set the transparency-compression\n");
|
||||
printf(" -noalpha ............... discard any transparency information.\n");
|
||||
printf(" -pass <int> ............ analysis pass number (1..10)\n");
|
||||
@ -712,10 +715,15 @@ static const char* const kErrorMessages[] = {
|
||||
"BITSTREAM_OUT_OF_MEMORY: Out of memory re-allocating byte buffer",
|
||||
"NULL_PARAMETER: NULL parameter passed to function",
|
||||
"INVALID_CONFIGURATION: configuration is invalid",
|
||||
"BAD_DIMENSION: Bad picture dimension",
|
||||
"PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k",
|
||||
"PARTITION_OVERFLOW: Partition is too big to fir 16M",
|
||||
"BAD_WRITE: Picture writer returned an error"
|
||||
"BAD_DIMENSION: Bad picture dimension. Maximum width and height "
|
||||
"allowed is 16383 pixels.",
|
||||
"PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k.\n"
|
||||
"To reduce the size of this partition, try using less segments "
|
||||
"with the -segments option, and eventually reduce the number of "
|
||||
"header bits using -partition_limit. More details are available "
|
||||
"in the manual (`man cwebp`)",
|
||||
"PARTITION_OVERFLOW: Partition is too big to fit 16M",
|
||||
"BAD_WRITE: Picture writer returned an I/O error"
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -789,6 +797,8 @@ int main(int argc, const char *argv[]) {
|
||||
config.preprocessing = strtol(argv[++c], NULL, 0);
|
||||
} else if (!strcmp(argv[c], "-segments") && c < argc - 1) {
|
||||
config.segments = strtol(argv[++c], NULL, 0);
|
||||
} else if (!strcmp(argv[c], "-partition_limit") && c < argc - 1) {
|
||||
config.partition_limit = strtol(argv[++c], NULL, 0);
|
||||
} else if (!strcmp(argv[c], "-alpha_comp") && c < argc - 1) {
|
||||
config.alpha_compression = strtol(argv[++c], NULL, 0);
|
||||
} else if (!strcmp(argv[c], "-noalpha")) {
|
||||
|
21
man/cwebp.1
21
man/cwebp.1
@ -1,5 +1,5 @@
|
||||
.\" Hey, EMACS: -*- nroff -*-
|
||||
.TH CWEBP 1 "June 20, 2011"
|
||||
.TH CWEBP 1 "August 23, 2011"
|
||||
.SH NAME
|
||||
cwebp \- compress an image file to a WebP file
|
||||
.SH SYNOPSIS
|
||||
@ -86,6 +86,25 @@ used thanks to the \fB\-f\fP option). Strong filtering is off by default.
|
||||
Change the number of partitions to use during the segmentation of the
|
||||
sns algorithm. Segments should be in range 1 to 4. Default value is 4.
|
||||
.TP
|
||||
.B \-partition_limit int
|
||||
Degrade quality by limiting the number of bits used by some macroblocks.
|
||||
Range is 0 (no degradation, the default) to 100 (full degradation).
|
||||
Useful values are usually around 30-70 for moderately large images.
|
||||
In the VP8 format, the so-called control partition has a limit of 512k and
|
||||
is used to store the following information: whether the macroblock is skipped,
|
||||
which segment it belongs to, whether it is coded as intra 4x4 or intra 16x16
|
||||
mode, and finally the prediction modes to use for each of the sub-blocks.
|
||||
For a very large image, 512k only leaves room to few bits per 16x16 macroblock.
|
||||
The absolute minimum is 4 bits per macroblock. Skip, segment, and mode
|
||||
information can use up almost all these 4 bits (although the case is unlikely),
|
||||
which is problematic for very large images. The partition_limit factor controls
|
||||
how frequently the most bit-costly mode (intra 4x4) will be used. This is
|
||||
useful in case the 512k limit is reached and the following message is displayed:
|
||||
\fIError code: 6 (PARTITION0_OVERFLOW: Partition #0 is too big to fit 512k)\fP.
|
||||
If using \fB-partition_limit\fP is not enough to meet the 512k constraint, one
|
||||
should use less segments in order to save more header bits per macroblock.
|
||||
See the \fB-segments\fP option.
|
||||
.TP
|
||||
.B \-size int
|
||||
Specify a target size (in bytes) to try and reach for the compressed output.
|
||||
Compressor will make several pass of partial encoding in order to get as
|
||||
|
@ -42,6 +42,7 @@ int WebPConfigInitInternal(WebPConfig* const config,
|
||||
config->preprocessing = 0;
|
||||
config->autofilter = 0;
|
||||
config->alpha_compression = 0;
|
||||
config->partition_limit = 0;
|
||||
|
||||
// TODO(skal): tune.
|
||||
switch (preset) {
|
||||
@ -106,6 +107,8 @@ int WebPValidateConfig(const WebPConfig* const config) {
|
||||
return 0;
|
||||
if (config->partitions < 0 || config->partitions > 3)
|
||||
return 0;
|
||||
if (config->partition_limit < 0 || config->partition_limit > 100)
|
||||
return 0;
|
||||
if (config->alpha_compression < 0)
|
||||
return 0;
|
||||
return 1;
|
||||
|
@ -757,8 +757,13 @@ static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
|
||||
const int tlambda = dqm->tlambda_;
|
||||
const uint8_t* const src0 = it->yuv_in_ + Y_OFF;
|
||||
uint8_t* const best_blocks = it->yuv_out2_ + Y_OFF;
|
||||
int total_header_bits = 0;
|
||||
VP8ModeScore rd_best;
|
||||
|
||||
if (enc->max_i4_header_bits_ == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
InitScore(&rd_best);
|
||||
rd_best.score = 211; // '211' is the value of VP8BitCost(0, 145)
|
||||
VP8IteratorStartI4(it);
|
||||
@ -799,7 +804,9 @@ static int PickBestIntra4(VP8EncIterator* const it, VP8ModeScore* const rd) {
|
||||
}
|
||||
SetRDScore(dqm->lambda_mode_, &rd_i4);
|
||||
AddScore(&rd_best, &rd_i4);
|
||||
if (rd_best.score >= rd->score) {
|
||||
total_header_bits += mode_costs[best_mode];
|
||||
if (rd_best.score >= rd->score ||
|
||||
total_header_bits > enc->max_i4_header_bits_) {
|
||||
return 0;
|
||||
}
|
||||
// Copy selected samples if not in the right place already.
|
||||
|
@ -359,8 +359,9 @@ struct VP8Encoder {
|
||||
int block_count_[3];
|
||||
|
||||
// quality/speed settings
|
||||
int method_; // 0=fastest, 6=best/slowest.
|
||||
int rd_opt_level_; // Deduced from method_.
|
||||
int method_; // 0=fastest, 6=best/slowest.
|
||||
int rd_opt_level_; // Deduced from method_.
|
||||
int max_i4_header_bits_; // partition #0 safeness factor
|
||||
|
||||
// Memory
|
||||
VP8MBInfo* mb_info_; // contextual macroblock infos (mb_w_ + 1)
|
||||
|
@ -112,11 +112,15 @@ static void ResetBoundaryPredictions(VP8Encoder* const enc) {
|
||||
|
||||
static void MapConfigToTools(VP8Encoder* const enc) {
|
||||
const int method = enc->config_->method;
|
||||
const int limit = 100 - enc->config_->partition_limit;
|
||||
enc->method_ = method;
|
||||
enc->rd_opt_level_ = (method >= 6) ? 3
|
||||
: (method >= 5) ? 2
|
||||
: (method >= 3) ? 1
|
||||
: 0;
|
||||
enc->max_i4_header_bits_ =
|
||||
256 * 16 * 16 * // upper bound: up to 16bit per 4x4 block
|
||||
(limit * limit) / (100 * 100); // ... modulated with a quadratic curve.
|
||||
}
|
||||
|
||||
// Memory scaling with dimensions:
|
||||
|
@ -69,6 +69,8 @@ typedef struct {
|
||||
int preprocessing; // preprocessing filter (0=none, 1=segment-smooth)
|
||||
int partitions; // log2(number of token partitions) in [0..3]
|
||||
// Default is set to 0 for easier progressive decoding.
|
||||
int partition_limit; // quality degradation allowed to fit the 512k limit on
|
||||
// prediction modes coding (0=no degradation, 100=full)
|
||||
int alpha_compression; // Algorithm for optimizing the alpha plane (0 = none)
|
||||
} WebPConfig;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user