Skip to content

Commit

Permalink
Allow transform_bits to be different during encoding.
Browse files Browse the repository at this point in the history
The spec allows it but it is currently forced to the same value for simplicity.

Change-Id: I26197dbf3342f7a72115cc7f7805c154313a2afb
  • Loading branch information
vrabaud committed May 13, 2024
1 parent 1e462ca commit 1bf198a
Show file tree
Hide file tree
Showing 5 changed files with 37 additions and 18 deletions.
10 changes: 8 additions & 2 deletions examples/cwebp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
1 change: 1 addition & 0 deletions src/enc/alpha_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
34 changes: 22 additions & 12 deletions src/enc/vp8l_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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) {
Expand Down Expand Up @@ -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.
Expand All @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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_));
Expand Down
3 changes: 2 additions & 1 deletion src/enc/vp8li_enc.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
7 changes: 4 additions & 3 deletions src/webp/encode.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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.
Expand Down

0 comments on commit 1bf198a

Please sign in to comment.