mirror of
https://github.com/webmproject/libwebp.git
synced 2024-11-20 04:18:26 +01:00
Move GetHistImageSymbols to histogram.c
Planning to revisit memory allocation scheme at several instanaces (next CL). Change-Id: Id7b9f4854e9577e10b53d5b1d8595b7d862e6e01
This commit is contained in:
parent
889a578681
commit
bfc73db4a8
@ -100,6 +100,11 @@ typedef struct {
|
|||||||
uint32_t argb_or_distance;
|
uint32_t argb_or_distance;
|
||||||
} PixOrCopy;
|
} PixOrCopy;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PixOrCopy* refs;
|
||||||
|
int size;
|
||||||
|
} VP8LBackwardRefs;
|
||||||
|
|
||||||
static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance,
|
static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance,
|
||||||
uint16_t len) {
|
uint16_t len) {
|
||||||
PixOrCopy retval;
|
PixOrCopy retval;
|
||||||
|
@ -68,12 +68,11 @@ void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const p,
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VP8LHistogramCreate(VP8LHistogram* const p,
|
void VP8LHistogramCreate(VP8LHistogram* const p,
|
||||||
const PixOrCopy* const literal_and_length,
|
const VP8LBackwardRefs* const refs) {
|
||||||
int n_literal_and_length) {
|
|
||||||
int i;
|
int i;
|
||||||
VP8LHistogramClear(p);
|
VP8LHistogramClear(p);
|
||||||
for (i = 0; i < n_literal_and_length; ++i) {
|
for (i = 0; i < refs->size; ++i) {
|
||||||
VP8LHistogramAddSinglePixOrCopy(p, literal_and_length[i]);
|
VP8LHistogramAddSinglePixOrCopy(p, refs->refs[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,11 +195,12 @@ double VP8LHistogramEstimateBitsHeader(const VP8LHistogram* const p) {
|
|||||||
HuffmanCost(&p->distance_[0], DISTANCE_CODES_MAX);
|
HuffmanCost(&p->distance_[0], DISTANCE_CODES_MAX);
|
||||||
}
|
}
|
||||||
|
|
||||||
int VP8LHistogramBuildImage(int xsize, int ysize,
|
static int HistogramBuildImage(int xsize, int ysize,
|
||||||
int histobits, int palettebits,
|
int histobits, int palettebits,
|
||||||
const PixOrCopy* backward_refs,
|
const PixOrCopy* const backward_refs,
|
||||||
int backward_refs_size,
|
int backward_refs_size,
|
||||||
VP8LHistogram*** image_arg, int* image_size) {
|
VP8LHistogram*** const image_arg,
|
||||||
|
int* const image_size) {
|
||||||
int histo_xsize = histobits ? (xsize + (1 << histobits) - 1) >> histobits : 1;
|
int histo_xsize = histobits ? (xsize + (1 << histobits) - 1) >> histobits : 1;
|
||||||
int histo_ysize = histobits ? (ysize + (1 << histobits) - 1) >> histobits : 1;
|
int histo_ysize = histobits ? (ysize + (1 << histobits) - 1) >> histobits : 1;
|
||||||
int i;
|
int i;
|
||||||
@ -241,8 +241,9 @@ int VP8LHistogramBuildImage(int xsize, int ysize,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VP8LHistogramCombine(VP8LHistogram** in, int in_size, int quality,
|
static int HistogramCombine(VP8LHistogram** const in, int in_size, int quality,
|
||||||
VP8LHistogram*** out_arg, int* out_size) {
|
VP8LHistogram*** const out_arg,
|
||||||
|
int* const out_size) {
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
int i;
|
int i;
|
||||||
unsigned int seed = 0;
|
unsigned int seed = 0;
|
||||||
@ -339,7 +340,7 @@ Error:
|
|||||||
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,
|
||||||
VP8LHistogram** 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;
|
||||||
@ -367,8 +368,9 @@ static double HistogramDistance(const VP8LHistogram* const square_histogram,
|
|||||||
return new_bit_cost - previous_bit_cost;
|
return new_bit_cost - previous_bit_cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VP8LHistogramRefine(VP8LHistogram** raw, int raw_size,
|
static void HistogramRefine(VP8LHistogram** const raw, int raw_size,
|
||||||
uint32_t* symbols, int out_size, VP8LHistogram** out) {
|
uint32_t* const symbols, int out_size,
|
||||||
|
VP8LHistogram** const out) {
|
||||||
int i;
|
int 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) {
|
||||||
@ -394,4 +396,45 @@ void VP8LHistogramRefine(VP8LHistogram** raw, int raw_size,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int VP8LGetHistImageSymbols(int xsize, int ysize,
|
||||||
|
const VP8LBackwardRefs* const refs,
|
||||||
|
int quality, int histogram_bits,
|
||||||
|
int cache_bits,
|
||||||
|
VP8LHistogram*** const histogram_image,
|
||||||
|
int* const histogram_image_size,
|
||||||
|
uint32_t* const histogram_symbols) {
|
||||||
|
// Build histogram image.
|
||||||
|
int ok = 0;
|
||||||
|
int i;
|
||||||
|
int histogram_image_raw_size;
|
||||||
|
VP8LHistogram** histogram_image_raw = NULL;
|
||||||
|
|
||||||
|
*histogram_image = NULL;
|
||||||
|
if (!HistogramBuildImage(xsize, ysize, histogram_bits, cache_bits,
|
||||||
|
refs->refs, refs->size,
|
||||||
|
&histogram_image_raw,
|
||||||
|
&histogram_image_raw_size)) {
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
// Collapse similar histograms.
|
||||||
|
if (!HistogramCombine(histogram_image_raw, histogram_image_raw_size,
|
||||||
|
quality, histogram_image, histogram_image_size)) {
|
||||||
|
goto Error;
|
||||||
|
}
|
||||||
|
// Refine histogram image.
|
||||||
|
for (i = 0; i < histogram_image_raw_size; ++i) {
|
||||||
|
histogram_symbols[i] = -1;
|
||||||
|
}
|
||||||
|
HistogramRefine(histogram_image_raw, histogram_image_raw_size,
|
||||||
|
histogram_symbols, *histogram_image_size, *histogram_image);
|
||||||
|
ok = 1;
|
||||||
|
|
||||||
|
Error:
|
||||||
|
if (!ok) {
|
||||||
|
VP8LDeleteHistograms(*histogram_image, *histogram_image_size);
|
||||||
|
}
|
||||||
|
VP8LDeleteHistograms(histogram_image_raw, histogram_image_raw_size);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -59,8 +59,7 @@ static WEBP_INLINE void VP8LHistogramInit(VP8LHistogram* const p,
|
|||||||
// The input data is the PixOrCopy data, which models the
|
// The input data is the PixOrCopy data, which models the
|
||||||
// literals, stop codes and backward references (both distances and lengths)
|
// literals, stop codes and backward references (both distances and lengths)
|
||||||
void VP8LHistogramCreate(VP8LHistogram* const p,
|
void VP8LHistogramCreate(VP8LHistogram* const p,
|
||||||
const PixOrCopy* const literal_and_length,
|
const VP8LBackwardRefs* const refs);
|
||||||
int n_literal_and_length);
|
|
||||||
|
|
||||||
void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const p, const PixOrCopy v);
|
void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const p, const PixOrCopy v);
|
||||||
|
|
||||||
@ -117,32 +116,28 @@ static WEBP_INLINE int VP8LHistogramNumCodes(const VP8LHistogram* const p) {
|
|||||||
return 256 + kLengthCodes + (1 << p->palette_code_bits_);
|
return 256 + kLengthCodes + (1 << p->palette_code_bits_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static WEBP_INLINE void VP8LDeleteHistograms(VP8LHistogram** histograms,
|
||||||
|
int size) {
|
||||||
|
if (histograms != NULL) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i < size; ++i) {
|
||||||
|
free(histograms[i]);
|
||||||
|
}
|
||||||
|
free(histograms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void VP8LConvertPopulationCountTableToBitEstimates(
|
void VP8LConvertPopulationCountTableToBitEstimates(
|
||||||
int n, const int* const population_counts, double* const output);
|
int n, const int* const population_counts, double* const output);
|
||||||
|
|
||||||
// Build a 2d image of histograms, subresolutioned by (1 << histobits) to
|
// Builds the histogram image.
|
||||||
// the original image.
|
int VP8LGetHistImageSymbols(int xsize, int ysize,
|
||||||
int VP8LHistogramBuildImage(int xsize, int ysize,
|
const VP8LBackwardRefs* const refs,
|
||||||
int histobits, int palette_bits,
|
int quality, int histogram_bits,
|
||||||
const PixOrCopy* backward_refs,
|
int cache_bits,
|
||||||
int backward_refs_size,
|
VP8LHistogram*** histogram_image,
|
||||||
VP8LHistogram*** image,
|
int* const histogram_image_size,
|
||||||
int* histogram_size);
|
uint32_t* const histogram_symbols);
|
||||||
|
|
||||||
// Combines several histograms into fewer histograms.
|
|
||||||
int VP8LHistogramCombine(VP8LHistogram** in,
|
|
||||||
int in_size,
|
|
||||||
int quality,
|
|
||||||
VP8LHistogram*** out,
|
|
||||||
int* out_size);
|
|
||||||
|
|
||||||
// Moves histograms from one cluster to another if smaller entropy can
|
|
||||||
// be achieved by doing that.
|
|
||||||
void VP8LHistogramRefine(VP8LHistogram** raw,
|
|
||||||
int raw_size,
|
|
||||||
uint32_t* symbols,
|
|
||||||
int out_size,
|
|
||||||
VP8LHistogram** out);
|
|
||||||
|
|
||||||
#if defined(__cplusplus) || defined(c_plusplus)
|
#if defined(__cplusplus) || defined(c_plusplus)
|
||||||
}
|
}
|
||||||
|
@ -154,13 +154,6 @@ static int VP8LEncAnalyze(VP8LEncoder* const enc) {
|
|||||||
|
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
// TODO(urvang): should be moved to backward_reference.h and used more
|
|
||||||
// as function parameters.
|
|
||||||
typedef struct {
|
|
||||||
PixOrCopy* refs;
|
|
||||||
int size;
|
|
||||||
} VP8LBackwardRefs;
|
|
||||||
|
|
||||||
static void VP8LInitBackwardRefs(VP8LBackwardRefs* const refs) {
|
static void VP8LInitBackwardRefs(VP8LBackwardRefs* const refs) {
|
||||||
if (refs != NULL) {
|
if (refs != NULL) {
|
||||||
refs->refs = NULL;
|
refs->refs = NULL;
|
||||||
@ -209,11 +202,11 @@ static int GetBackwardReferences(int width, int height,
|
|||||||
if (histo == NULL) goto Error1;
|
if (histo == NULL) goto Error1;
|
||||||
// Evaluate lz77 coding
|
// Evaluate lz77 coding
|
||||||
VP8LHistogramInit(histo, cache_bits);
|
VP8LHistogramInit(histo, cache_bits);
|
||||||
VP8LHistogramCreate(histo, refs_lz77.refs, refs_lz77.size);
|
VP8LHistogramCreate(histo, &refs_lz77);
|
||||||
bit_cost_lz77 = (int)VP8LHistogramEstimateBits(histo);
|
bit_cost_lz77 = (int)VP8LHistogramEstimateBits(histo);
|
||||||
// Evaluate RLE coding
|
// Evaluate RLE coding
|
||||||
VP8LHistogramInit(histo, cache_bits);
|
VP8LHistogramInit(histo, cache_bits);
|
||||||
VP8LHistogramCreate(histo, refs_rle.refs, refs_rle.size);
|
VP8LHistogramCreate(histo, &refs_rle);
|
||||||
bit_cost_rle = (int)VP8LHistogramEstimateBits(histo);
|
bit_cost_rle = (int)VP8LHistogramEstimateBits(histo);
|
||||||
// Decide if LZ77 is useful.
|
// Decide if LZ77 is useful.
|
||||||
lz77_is_useful = (bit_cost_lz77 < bit_cost_rle);
|
lz77_is_useful = (bit_cost_lz77 < bit_cost_rle);
|
||||||
@ -259,58 +252,6 @@ End:
|
|||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void DeleteHistograms(VP8LHistogram** histograms, int size) {
|
|
||||||
if (histograms != NULL) {
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < size; ++i) {
|
|
||||||
free(histograms[i]);
|
|
||||||
}
|
|
||||||
free(histograms);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int GetHistImageSymbols(int xsize, int ysize,
|
|
||||||
const VP8LBackwardRefs* const refs,
|
|
||||||
int quality, int histogram_bits,
|
|
||||||
int cache_bits,
|
|
||||||
VP8LHistogram*** histogram_image,
|
|
||||||
int* histogram_image_size,
|
|
||||||
uint32_t* histogram_symbols) {
|
|
||||||
// Build histogram image.
|
|
||||||
int ok = 0;
|
|
||||||
int i;
|
|
||||||
int histogram_image_raw_size;
|
|
||||||
VP8LHistogram** histogram_image_raw = NULL;
|
|
||||||
|
|
||||||
*histogram_image = NULL;
|
|
||||||
if (!VP8LHistogramBuildImage(xsize, ysize, histogram_bits, cache_bits,
|
|
||||||
refs->refs, refs->size,
|
|
||||||
&histogram_image_raw,
|
|
||||||
&histogram_image_raw_size)) {
|
|
||||||
goto Error;
|
|
||||||
}
|
|
||||||
// Collapse similar histograms.
|
|
||||||
if (!VP8LHistogramCombine(histogram_image_raw, histogram_image_raw_size,
|
|
||||||
quality, histogram_image, histogram_image_size)) {
|
|
||||||
goto Error;
|
|
||||||
}
|
|
||||||
// Refine histogram image.
|
|
||||||
for (i = 0; i < histogram_image_raw_size; ++i) {
|
|
||||||
histogram_symbols[i] = -1;
|
|
||||||
}
|
|
||||||
VP8LHistogramRefine(histogram_image_raw, histogram_image_raw_size,
|
|
||||||
histogram_symbols, *histogram_image_size,
|
|
||||||
*histogram_image);
|
|
||||||
ok = 1;
|
|
||||||
|
|
||||||
Error:
|
|
||||||
if (!ok) {
|
|
||||||
DeleteHistograms(*histogram_image, *histogram_image_size);
|
|
||||||
}
|
|
||||||
DeleteHistograms(histogram_image_raw, histogram_image_raw_size);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Heuristics for selecting the stride ranges to collapse.
|
// Heuristics for selecting the stride ranges to collapse.
|
||||||
static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) {
|
static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) {
|
||||||
return abs(a - b) < 4;
|
return abs(a - b) < 4;
|
||||||
@ -750,10 +691,10 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
|||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
// Build histogram image & symbols from backward references.
|
// Build histogram image & symbols from backward references.
|
||||||
if (!GetHistImageSymbols(width, height, &refs,
|
if (!VP8LGetHistImageSymbols(width, height, &refs,
|
||||||
quality, histogram_bits, cache_bits,
|
quality, histogram_bits, cache_bits,
|
||||||
&histogram_image, &histogram_image_size,
|
&histogram_image, &histogram_image_size,
|
||||||
histogram_symbols)) {
|
histogram_symbols)) {
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
// Create Huffman bit lengths & codes for each histogram image.
|
// Create Huffman bit lengths & codes for each histogram image.
|
||||||
@ -816,7 +757,7 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Free combined histograms.
|
// Free combined histograms.
|
||||||
DeleteHistograms(histogram_image, histogram_image_size);
|
VP8LDeleteHistograms(histogram_image, histogram_image_size);
|
||||||
histogram_image = NULL;
|
histogram_image = NULL;
|
||||||
|
|
||||||
// Emit no bits if there is only one symbol in the histogram.
|
// Emit no bits if there is only one symbol in the histogram.
|
||||||
@ -832,7 +773,7 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
|||||||
|
|
||||||
Error:
|
Error:
|
||||||
if (!ok) {
|
if (!ok) {
|
||||||
DeleteHistograms(histogram_image, histogram_image_size);
|
VP8LDeleteHistograms(histogram_image, histogram_image_size);
|
||||||
}
|
}
|
||||||
VP8LClearBackwardRefs(&refs);
|
VP8LClearBackwardRefs(&refs);
|
||||||
for (i = 0; i < 5 * histogram_image_size; ++i) {
|
for (i = 0; i < 5 * histogram_image_size; ++i) {
|
||||||
|
Loading…
Reference in New Issue
Block a user