mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 06:08:21 +01:00
lossless: Less code for the entropy selection
Tested: 1000 png corpus gives same results Change-Id: Ief5ea7727290743b9bd893b08af7aa7951f556cb
This commit is contained in:
parent
16ab951abf
commit
84326e4ab0
105
src/enc/vp8l.c
105
src/enc/vp8l.c
@ -198,27 +198,26 @@ static void AddSinglePixSubtractGreen(VP8LHistogram* const histo,
|
||||
++histo->blue_[(PixOrCopyLiteral(v, 0) - green) & 0xff];
|
||||
}
|
||||
|
||||
// These five modes are evaluated and their respective entropy is computed.
|
||||
typedef enum {
|
||||
kDirect = 0,
|
||||
kSpatial = 1,
|
||||
kSubGreen = 2,
|
||||
kSpatialSubGreen = 3,
|
||||
kPalette = 4,
|
||||
kNumEntropyIx = 5,
|
||||
} EntropyIx;
|
||||
|
||||
static int AnalyzeEntropy(const uint32_t* argb,
|
||||
int width, int height, int argb_stride,
|
||||
double* const nonpredicted_bits,
|
||||
double* const predicted_bits,
|
||||
double* const predicted_sub_green_bits,
|
||||
double* const nonpredicted_sub_green_bits,
|
||||
double* const palette_bits) {
|
||||
double entropy[kNumEntropyIx]) {
|
||||
// Allocate histogram set with cache_bits = 0.
|
||||
VP8LHistogramSet* const histo_set = VP8LAllocateHistogramSet(5, 0);
|
||||
assert(nonpredicted_bits != NULL);
|
||||
assert(predicted_bits != NULL);
|
||||
|
||||
if (histo_set != NULL) {
|
||||
int x, y;
|
||||
int i, x, y;
|
||||
const uint32_t* prev_row = argb;
|
||||
const uint32_t* curr_row = argb + argb_stride;
|
||||
VP8LHistogram* const histo_non_pred = histo_set->histograms[0];
|
||||
VP8LHistogram* const histo_pred = histo_set->histograms[1];
|
||||
VP8LHistogram* const histo_pred_subgreen = histo_set->histograms[2];
|
||||
VP8LHistogram* const histo_subgreen = histo_set->histograms[3];
|
||||
VP8LHistogram* const histo_palette = histo_set->histograms[4];
|
||||
VP8LHistogram* const * const histo = &histo_set->histograms[0];
|
||||
for (y = 1; y < height; ++y) {
|
||||
uint32_t prev_pix = curr_row[0];
|
||||
for (x = 1; x < width; ++x) {
|
||||
@ -229,27 +228,23 @@ static int AnalyzeEntropy(const uint32_t* argb,
|
||||
{
|
||||
const PixOrCopy pix_token = PixOrCopyCreateLiteral(pix);
|
||||
const PixOrCopy pix_diff_token = PixOrCopyCreateLiteral(pix_diff);
|
||||
VP8LHistogramAddSinglePixOrCopy(histo_non_pred, &pix_token);
|
||||
VP8LHistogramAddSinglePixOrCopy(histo_pred, &pix_diff_token);
|
||||
AddSinglePixSubtractGreen(histo_subgreen, &pix_token);
|
||||
AddSinglePixSubtractGreen(histo_pred_subgreen, &pix_diff_token);
|
||||
VP8LHistogramAddSinglePixOrCopy(histo[kDirect], &pix_token);
|
||||
VP8LHistogramAddSinglePixOrCopy(histo[kSpatial], &pix_diff_token);
|
||||
AddSinglePixSubtractGreen(histo[kSubGreen], &pix_token);
|
||||
AddSinglePixSubtractGreen(histo[kSpatialSubGreen], &pix_diff_token);
|
||||
}
|
||||
{
|
||||
// Approximate the palette by the entropy of the multiplicative hash.
|
||||
const int hash = ((pix + (pix >> 19)) * 0x39c5fba7) >> 24;
|
||||
++histo_palette->red_[hash & 0xff];
|
||||
++histo[kPalette]->red_[hash & 0xff];
|
||||
}
|
||||
}
|
||||
prev_row = curr_row;
|
||||
curr_row += argb_stride;
|
||||
}
|
||||
*nonpredicted_bits = VP8LHistogramEstimateBitsBulk(histo_non_pred);
|
||||
*predicted_bits = VP8LHistogramEstimateBitsBulk(histo_pred);
|
||||
*predicted_sub_green_bits =
|
||||
VP8LHistogramEstimateBitsBulk(histo_pred_subgreen);
|
||||
*nonpredicted_sub_green_bits =
|
||||
VP8LHistogramEstimateBitsBulk(histo_subgreen);
|
||||
*palette_bits = VP8LHistogramEstimateBitsBulk(histo_palette);
|
||||
for (i = 0; i < kNumEntropyIx; ++i) {
|
||||
entropy[i] = VP8LHistogramEstimateBitsBulk(histo[i]);
|
||||
}
|
||||
VP8LFreeHistogramSet(histo_set);
|
||||
return 1;
|
||||
} else {
|
||||
@ -286,11 +281,6 @@ static int AnalyzeAndInit(VP8LEncoder* const enc) {
|
||||
// we round the block size up, so we're guaranteed to have
|
||||
// at max MAX_REFS_BLOCK_PER_IMAGE blocks used:
|
||||
int refs_block_size = (pix_cnt - 1) / MAX_REFS_BLOCK_PER_IMAGE + 1;
|
||||
double non_pred_entropy = 0.;
|
||||
double non_pred_subtract_green_entropy = 0.;
|
||||
double pred_entropy = 0.;
|
||||
double pred_subtract_green_entropy = 0.;
|
||||
double palette_entropy = 0.;
|
||||
assert(pic != NULL && pic->argb != NULL);
|
||||
|
||||
enc->use_cross_color_ = 0;
|
||||
@ -305,49 +295,26 @@ static int AnalyzeAndInit(VP8LEncoder* const enc) {
|
||||
enc->use_subtract_green_ = !enc->use_palette_;
|
||||
enc->use_cross_color_ = 0;
|
||||
} else {
|
||||
double entropy[kNumEntropyIx];
|
||||
EntropyIx min_entropy_ix = kDirect;
|
||||
EntropyIx i = kDirect;
|
||||
EntropyIx last_mode_to_analyze;
|
||||
if (!AnalyzeEntropy(pic->argb, width, height, pic->argb_stride,
|
||||
&non_pred_entropy, &pred_entropy,
|
||||
&pred_subtract_green_entropy,
|
||||
&non_pred_subtract_green_entropy,
|
||||
&palette_entropy)) {
|
||||
&entropy[0])) {
|
||||
return 0;
|
||||
}
|
||||
palette_entropy -= 10.; // Small bias in favor of using the palette.
|
||||
|
||||
if (enc->use_palette_) {
|
||||
// Check if avoiding the palette coding likely improves compression.
|
||||
if (palette_entropy >= non_pred_entropy ||
|
||||
palette_entropy >= non_pred_subtract_green_entropy ||
|
||||
palette_entropy >= pred_entropy ||
|
||||
palette_entropy >= pred_subtract_green_entropy) {
|
||||
enc->use_palette_ = 0;
|
||||
}
|
||||
}
|
||||
// TODO(jyrki): make this more clear.
|
||||
if (!enc->use_palette_) {
|
||||
// Choose the smallest of four options.
|
||||
if (non_pred_entropy < non_pred_subtract_green_entropy &&
|
||||
non_pred_entropy < pred_entropy &&
|
||||
non_pred_entropy < pred_subtract_green_entropy) {
|
||||
enc->use_subtract_green_ = 0;
|
||||
enc->use_predict_ = 0;
|
||||
enc->use_cross_color_ = 0;
|
||||
} else if (pred_entropy < non_pred_subtract_green_entropy &&
|
||||
pred_entropy < pred_subtract_green_entropy) {
|
||||
enc->use_subtract_green_ = 0;
|
||||
enc->use_predict_ = 1;
|
||||
enc->use_cross_color_ = 1;
|
||||
} else if (non_pred_subtract_green_entropy <
|
||||
pred_subtract_green_entropy) {
|
||||
enc->use_subtract_green_ = 1;
|
||||
enc->use_predict_ = 0;
|
||||
enc->use_cross_color_ = 0;
|
||||
} else {
|
||||
enc->use_subtract_green_ = 1;
|
||||
enc->use_predict_ = 1;
|
||||
enc->use_cross_color_ = 1;
|
||||
entropy[kPalette] -= 10.; // Small bias in favor of using the palette.
|
||||
last_mode_to_analyze = enc->use_palette_ ? kPalette : kSpatialSubGreen;
|
||||
for (i = 1; i <= last_mode_to_analyze; ++i) {
|
||||
if (entropy[min_entropy_ix] > entropy[i]) {
|
||||
min_entropy_ix = i;
|
||||
}
|
||||
}
|
||||
enc->use_palette_ = (min_entropy_ix == kPalette);
|
||||
enc->use_subtract_green_ =
|
||||
(min_entropy_ix == kSubGreen) || (min_entropy_ix == kSpatialSubGreen);
|
||||
enc->use_cross_color_ = enc->use_predict_ =
|
||||
(min_entropy_ix == kSpatial) || (min_entropy_ix == kSpatialSubGreen);
|
||||
}
|
||||
// Evaluate histogram bits based on the original value of use_palette flag.
|
||||
enc->histo_bits_ = GetHistoBits(method, enc->use_palette_, pic->width,
|
||||
|
Loading…
Reference in New Issue
Block a user