Evaluate output cluster's bit_costs once in HistogramRefine.

Avoid bit_costs evaluated every time in function HistogramDistance. Also moved
VP8LInitBackwardRefs and VP8LClearBackwardRefs to backward_references.h

Change-Id: Id507f164d0fc64480aebc4a3ea3e6950ed377a60
This commit is contained in:
Vikas Arora 2012-04-27 08:04:57 +00:00 committed by James Zern
parent 781c01f421
commit cf33ccd160
3 changed files with 52 additions and 40 deletions

View File

@ -15,6 +15,7 @@
#include <assert.h> #include <assert.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include "../webp/types.h" #include "../webp/types.h"
#if defined(__cplusplus) || defined(c_plusplus) #if defined(__cplusplus) || defined(c_plusplus)
@ -172,6 +173,20 @@ static WEBP_INLINE uint32_t PixOrCopyDistance(const PixOrCopy* const p) {
return p->argb_or_distance; return p->argb_or_distance;
} }
static WEBP_INLINE void VP8LInitBackwardRefs(VP8LBackwardRefs* const refs) {
if (refs != NULL) {
refs->refs = NULL;
refs->size = 0;
}
}
static WEBP_INLINE void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs) {
if (refs != NULL) {
free(refs->refs);
VP8LInitBackwardRefs(refs);
}
}
// Ridiculously simple backward references for images where it is unlikely // Ridiculously simple backward references for images where it is unlikely
// that there are large backward references (photos). // that there are large backward references (photos).
void VP8LBackwardReferencesRle( void VP8LBackwardReferencesRle(

View File

@ -197,8 +197,7 @@ double VP8LHistogramEstimateBitsHeader(const VP8LHistogram* const p) {
static int HistogramBuildImage(int xsize, int ysize, static int HistogramBuildImage(int xsize, int ysize,
int histobits, int palettebits, int histobits, int palettebits,
const PixOrCopy* const backward_refs, const VP8LBackwardRefs* const backward_refs,
int backward_refs_size,
VP8LHistogram*** const image_arg, VP8LHistogram*** const image_arg,
int* const image_size) { int* const image_size) {
int histo_xsize = histobits ? (xsize + (1 << histobits) - 1) >> histobits : 1; int histo_xsize = histobits ? (xsize + (1 << histobits) - 1) >> histobits : 1;
@ -226,8 +225,8 @@ static int HistogramBuildImage(int xsize, int ysize,
VP8LHistogramInit(image[i], palettebits); VP8LHistogramInit(image[i], palettebits);
} }
// x and y trace the position in the image. // x and y trace the position in the image.
for (i = 0; i < backward_refs_size; ++i) { for (i = 0; i < backward_refs->size; ++i) {
const PixOrCopy v = backward_refs[i]; const PixOrCopy v = backward_refs->refs[i];
const int ix = const int ix =
histobits ? (y >> histobits) * histo_xsize + (x >> histobits) : 0; histobits ? (y >> histobits) * histo_xsize + (x >> histobits) : 0;
VP8LHistogramAddSinglePixOrCopy(image[ix], v); VP8LHistogramAddSinglePixOrCopy(image[ix], v);
@ -338,47 +337,54 @@ Error:
// What is the bit cost of moving square_histogram from // What is the bit cost of moving square_histogram from
// cur_symbol to candidate_symbol. // cur_symbol to candidate_symbol.
static double HistogramDistance(const VP8LHistogram* const square_histogram, static double HistogramDistance(const VP8LHistogram* const square_histogram,
int cur_symbol, int cur_symbol, int candidate_symbol,
int candidate_symbol, const double* const symbol_bit_costs,
VP8LHistogram** const candidate_histograms) { VP8LHistogram** const candidate_histograms) {
double new_bit_cost; double new_bit_cost;
double previous_bit_cost; double previous_bit_cost;
VP8LHistogram modified; VP8LHistogram modified_histo;
if (cur_symbol == candidate_symbol) { if (cur_symbol == candidate_symbol) {
return 0; // Going nowhere. No savings. return 0; // Going nowhere. No savings.
} }
previous_bit_cost = previous_bit_cost = symbol_bit_costs[candidate_symbol];
VP8LHistogramEstimateBits(candidate_histograms[candidate_symbol]);
if (cur_symbol != -1) { if (cur_symbol != -1) {
previous_bit_cost += previous_bit_cost += symbol_bit_costs[cur_symbol];
VP8LHistogramEstimateBits(candidate_histograms[cur_symbol]);
} }
// Compute the bit cost of the histogram where the data moves to. // Compute the bit cost of the histogram where the data moves to.
modified = *candidate_histograms[candidate_symbol]; modified_histo = *candidate_histograms[candidate_symbol];
VP8LHistogramAdd(&modified, square_histogram); VP8LHistogramAdd(&modified_histo, square_histogram);
new_bit_cost = VP8LHistogramEstimateBits(&modified); new_bit_cost = VP8LHistogramEstimateBits(&modified_histo);
// Compute the bit cost of the histogram where the data moves away. // Compute the bit cost of the histogram where the data moves away.
if (cur_symbol != -1) { if (cur_symbol != -1) {
modified = *candidate_histograms[cur_symbol]; modified_histo = *candidate_histograms[cur_symbol];
VP8LHistogramRemove(&modified, square_histogram); VP8LHistogramRemove(&modified_histo, square_histogram);
new_bit_cost += VP8LHistogramEstimateBits(&modified); new_bit_cost += VP8LHistogramEstimateBits(&modified_histo);
} }
return new_bit_cost - previous_bit_cost; return new_bit_cost - previous_bit_cost;
} }
static void HistogramRefine(VP8LHistogram** const raw, int raw_size, static int HistogramRefine(VP8LHistogram** const raw, int raw_size,
uint32_t* const symbols, int out_size, uint32_t* const symbols,
VP8LHistogram** const out) { VP8LHistogram** const out, int out_size) {
int i; int i;
double* const symbol_bit_costs =
(double*)malloc(out_size * sizeof(*symbol_bit_costs));
if (symbol_bit_costs == NULL) return 0;
for (i = 0; i < out_size; ++i) {
symbol_bit_costs[i] = VP8LHistogramEstimateBits(out[i]);
}
// Find the best 'out' histogram for each of the raw histograms // Find the best 'out' histogram for each of the raw histograms
for (i = 0; i < raw_size; ++i) { for (i = 0; i < raw_size; ++i) {
int best_out = 0; int best_out = 0;
double best_bits = HistogramDistance(raw[i], symbols[i], 0, out); double best_bits = HistogramDistance(raw[i], symbols[i], 0,
symbol_bit_costs, out);
int k; int k;
for (k = 1; k < out_size; ++k) { for (k = 1; k < out_size; ++k) {
double cur_bits = HistogramDistance(raw[i], symbols[i], k, out); double cur_bits = HistogramDistance(raw[i], symbols[i], k,
symbol_bit_costs, out);
if (cur_bits < best_bits) { if (cur_bits < best_bits) {
best_bits = cur_bits; best_bits = cur_bits;
best_out = k; best_out = k;
@ -386,6 +392,7 @@ static void HistogramRefine(VP8LHistogram** const raw, int raw_size,
} }
symbols[i] = best_out; symbols[i] = best_out;
} }
free(out_bit_costs);
// Recompute each out based on raw and symbols. // Recompute each out based on raw and symbols.
for (i = 0; i < out_size; ++i) { for (i = 0; i < out_size; ++i) {
@ -394,6 +401,8 @@ static void HistogramRefine(VP8LHistogram** const raw, int raw_size,
for (i = 0; i < raw_size; ++i) { for (i = 0; i < raw_size; ++i) {
VP8LHistogramAdd(out[symbols[i]], raw[i]); VP8LHistogramAdd(out[symbols[i]], raw[i]);
} }
return 1;
} }
int VP8LGetHistImageSymbols(int xsize, int ysize, int VP8LGetHistImageSymbols(int xsize, int ysize,
@ -410,8 +419,7 @@ int VP8LGetHistImageSymbols(int xsize, int ysize,
VP8LHistogram** histogram_image_raw = NULL; VP8LHistogram** histogram_image_raw = NULL;
*histogram_image = NULL; *histogram_image = NULL;
if (!HistogramBuildImage(xsize, ysize, histogram_bits, cache_bits, if (!HistogramBuildImage(xsize, ysize, histogram_bits, cache_bits, refs,
refs->refs, refs->size,
&histogram_image_raw, &histogram_image_raw,
&histogram_image_raw_size)) { &histogram_image_raw_size)) {
goto Error; goto Error;
@ -425,8 +433,11 @@ int VP8LGetHistImageSymbols(int xsize, int ysize,
for (i = 0; i < histogram_image_raw_size; ++i) { for (i = 0; i < histogram_image_raw_size; ++i) {
histogram_symbols[i] = -1; histogram_symbols[i] = -1;
} }
HistogramRefine(histogram_image_raw, histogram_image_raw_size, if (!HistogramRefine(histogram_image_raw, histogram_image_raw_size,
histogram_symbols, *histogram_image_size, *histogram_image); histogram_symbols,
*histogram_image, *histogram_image_size)) {
goto Error;
}
ok = 1; ok = 1;
Error: Error:

View File

@ -154,20 +154,6 @@ static int VP8LEncAnalyze(VP8LEncoder* const enc) {
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
static void VP8LInitBackwardRefs(VP8LBackwardRefs* const refs) {
if (refs != NULL) {
refs->refs = NULL;
refs->size = 0;
}
}
static void VP8LClearBackwardRefs(VP8LBackwardRefs* const refs) {
if (refs != NULL) {
free(refs->refs);
VP8LInitBackwardRefs(refs);
}
}
static int GetBackwardReferences(int width, int height, static int GetBackwardReferences(int width, int height,
const uint32_t* argb, const uint32_t* argb,
int quality, int use_color_cache, int quality, int use_color_cache,