Allow transform_bits to be different during encoding.

The spec allows it but it is currently forced to the same value for simplicity.

Change-Id: I26197dbf3342f7a72115cc7f7805c154313a2afb
This commit is contained in:
Vincent Rabaud 2024-05-07 10:44:59 +02:00
parent 1e462ca80e
commit 1bf198a22b
5 changed files with 37 additions and 18 deletions

View File

@ -178,8 +178,14 @@ static void PrintFullLosslessInfo(const WebPAuxStats* const stats,
if (stats->lossless_features & 8) fprintf(stderr, " PALETTE");
fprintf(stderr, "\n");
}
fprintf(stderr, " * Precision Bits: histogram=%d transform=%d cache=%d\n",
stats->histogram_bits, stats->transform_bits, stats->cache_bits);
fprintf(stderr, " * Precision Bits: histogram=%d", stats->histogram_bits);
if (stats->lossless_features & 1) {
fprintf(stderr, " prediction=%d", stats->transform_bits);
}
if (stats->lossless_features & 2) {
fprintf(stderr, " cross-color=%d", stats->cross_color_transform_bits);
}
fprintf(stderr, " cache=%d\n", stats->cache_bits);
if (stats->palette_size > 0) {
fprintf(stderr, " * Palette size: %d\n", stats->palette_size);
}

View File

@ -276,6 +276,7 @@ static int ApplyFiltersAndEncode(const uint8_t* alpha, int width, int height,
stats->lossless_features = best.stats.lossless_features;
stats->histogram_bits = best.stats.histogram_bits;
stats->transform_bits = best.stats.transform_bits;
stats->cross_color_transform_bits = best.stats.cross_color_transform_bits;
stats->cache_bits = best.stats.cache_bits;
stats->palette_size = best.stats.palette_size;
stats->lossless_size = best.stats.lossless_size;

View File

@ -281,7 +281,7 @@ static int EncoderAnalyze(VP8LEncoder* const enc,
const int method = config->method;
const int low_effort = (config->method == 0);
int i;
int use_palette;
int use_palette, transform_bits;
int n_lz77s;
// If set to 0, analyze the cache with the computed cache value. If 1, also
// analyze with no-cache.
@ -298,7 +298,9 @@ static int EncoderAnalyze(VP8LEncoder* const enc,
// Empirical bit sizes.
enc->histo_bits_ = GetHistoBits(method, use_palette,
pic->width, pic->height);
enc->transform_bits_ = GetTransformBits(method, enc->histo_bits_);
transform_bits = GetTransformBits(method, enc->histo_bits_);
enc->predictor_transform_bits_ = transform_bits;
enc->cross_color_transform_bits_ = transform_bits;
if (low_effort) {
// AnalyzeEntropy is somewhat slow.
@ -312,8 +314,8 @@ static int EncoderAnalyze(VP8LEncoder* const enc,
// Try out multiple LZ77 on images with few colors.
n_lz77s = (enc->palette_size_ > 0 && enc->palette_size_ <= 16) ? 2 : 1;
if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride, use_palette,
enc->palette_size_, enc->transform_bits_,
&min_entropy_ix, red_and_blue_always_zero)) {
enc->palette_size_, transform_bits, &min_entropy_ix,
red_and_blue_always_zero)) {
return 0;
}
if (method == 6 && config->quality == 100) {
@ -1069,7 +1071,7 @@ static int ApplyPredictFilter(VP8LEncoder* const enc, int width, int height,
int quality, int low_effort,
int used_subtract_green, VP8LBitWriter* const bw,
int percent_range, int* const percent) {
const int pred_bits = enc->transform_bits_;
const int pred_bits = enc->predictor_transform_bits_;
const int transform_width = VP8LSubSampleSize(width, pred_bits);
const int transform_height = VP8LSubSampleSize(height, pred_bits);
// we disable near-lossless quantization if palette is used.
@ -1093,11 +1095,11 @@ static int ApplyPredictFilter(VP8LEncoder* const enc, int width, int height,
percent);
}
static int ApplyCrossColorFilter(const VP8LEncoder* const enc, int width,
int height, int quality, int low_effort,
static int ApplyCrossColorFilter(VP8LEncoder* const enc, int width, int height,
int quality, int low_effort,
VP8LBitWriter* const bw, int percent_range,
int* const percent) {
const int ccolor_transform_bits = enc->transform_bits_;
const int ccolor_transform_bits = enc->cross_color_transform_bits_;
const int transform_width = VP8LSubSampleSize(width, ccolor_transform_bits);
const int transform_height = VP8LSubSampleSize(height, ccolor_transform_bits);
@ -1200,10 +1202,14 @@ static int AllocateTransformBuffer(VP8LEncoder* const enc, int width,
enc->use_predict_ ? (width + 1) * 2 + (width * 2 + sizeof(uint32_t) - 1) /
sizeof(uint32_t)
: 0;
const int min_transform_bits =
(enc->predictor_transform_bits_ < enc->cross_color_transform_bits_)
? enc->predictor_transform_bits_
: enc->cross_color_transform_bits_;
const uint64_t transform_data_size =
(enc->use_predict_ || enc->use_cross_color_)
? (uint64_t)VP8LSubSampleSize(width, enc->transform_bits_) *
VP8LSubSampleSize(height, enc->transform_bits_)
? (uint64_t)VP8LSubSampleSize(width, min_transform_bits) *
VP8LSubSampleSize(height, min_transform_bits)
: 0;
const uint64_t max_alignment_in_words =
(WEBP_ALIGN_CST + sizeof(uint32_t) - 1) / sizeof(uint32_t);
@ -1628,7 +1634,8 @@ static int EncodeStreamHook(void* input, void* data2) {
if (enc->use_subtract_green_) stats->lossless_features |= 4;
if (enc->use_palette_) stats->lossless_features |= 8;
stats->histogram_bits = enc->histo_bits_;
stats->transform_bits = enc->transform_bits_;
stats->transform_bits = enc->predictor_transform_bits_;
stats->cross_color_transform_bits = enc->cross_color_transform_bits_;
stats->cache_bits = enc->cache_bits_;
stats->palette_size = enc->palette_size_;
stats->lossless_size = (int)(best_size - byte_position);
@ -1738,7 +1745,10 @@ int VP8LEncodeStream(const WebPConfig* const config,
}
// Copy the values that were computed for the main encoder.
enc_side->histo_bits_ = enc_main->histo_bits_;
enc_side->transform_bits_ = enc_main->transform_bits_;
enc_side->predictor_transform_bits_ =
enc_main->predictor_transform_bits_;
enc_side->cross_color_transform_bits_ =
enc_main->cross_color_transform_bits_;
enc_side->palette_size_ = enc_main->palette_size_;
memcpy(enc_side->palette_, enc_main->palette_,
sizeof(enc_main->palette_));

View File

@ -59,7 +59,8 @@ typedef struct {
// Encoding parameters derived from quality parameter.
int histo_bits_;
int transform_bits_; // <= MAX_TRANSFORM_BITS.
int predictor_transform_bits_; // <= MAX_TRANSFORM_BITS
int cross_color_transform_bits_; // <= MAX_TRANSFORM_BITS
int cache_bits_; // If equal to 0, don't use color cache.
// Encoding parameters derived from image characteristics.

View File

@ -20,7 +20,7 @@
extern "C" {
#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++,
// the types are left here for reference.
@ -224,14 +224,15 @@ struct WebPAuxStats {
uint32_t lossless_features; // bit0:predictor bit1:cross-color transform
// bit2:subtract-green bit3:color indexing
int histogram_bits; // number of precision bits of histogram
int transform_bits; // precision bits for transform
int transform_bits; // precision bits for predictor transform
int cache_bits; // number of bits for color cache lookup
int palette_size; // number of color in palette, if used
int lossless_size; // final lossless size
int lossless_hdr_size; // lossless header (transform, huffman etc) size
int lossless_data_size; // lossless image data size
int cross_color_transform_bits; // precision bits for cross-color transform
uint32_t pad[2]; // padding for later use
uint32_t pad[1]; // padding for later use
};
// Signature for output function. Should return true if writing was successful.