diff --git a/src/enc/backward_references.h b/src/enc/backward_references.h index 22e53a4a..7bcc3313 100644 --- a/src/enc/backward_references.h +++ b/src/enc/backward_references.h @@ -100,6 +100,11 @@ typedef struct { uint32_t argb_or_distance; } PixOrCopy; +typedef struct { + PixOrCopy* refs; + int size; +} VP8LBackwardRefs; + static WEBP_INLINE PixOrCopy PixOrCopyCreateCopy(uint32_t distance, uint16_t len) { PixOrCopy retval; diff --git a/src/enc/histogram.c b/src/enc/histogram.c index 26244849..ba232fb2 100644 --- a/src/enc/histogram.c +++ b/src/enc/histogram.c @@ -68,12 +68,11 @@ void VP8LHistogramAddSinglePixOrCopy(VP8LHistogram* const p, } void VP8LHistogramCreate(VP8LHistogram* const p, - const PixOrCopy* const literal_and_length, - int n_literal_and_length) { + const VP8LBackwardRefs* const refs) { int i; VP8LHistogramClear(p); - for (i = 0; i < n_literal_and_length; ++i) { - VP8LHistogramAddSinglePixOrCopy(p, literal_and_length[i]); + for (i = 0; i < refs->size; ++i) { + VP8LHistogramAddSinglePixOrCopy(p, refs->refs[i]); } } @@ -196,11 +195,12 @@ double VP8LHistogramEstimateBitsHeader(const VP8LHistogram* const p) { HuffmanCost(&p->distance_[0], DISTANCE_CODES_MAX); } -int VP8LHistogramBuildImage(int xsize, int ysize, - int histobits, int palettebits, - const PixOrCopy* backward_refs, - int backward_refs_size, - VP8LHistogram*** image_arg, int* image_size) { +static int HistogramBuildImage(int xsize, int ysize, + int histobits, int palettebits, + const PixOrCopy* const backward_refs, + int backward_refs_size, + VP8LHistogram*** const image_arg, + int* const image_size) { int histo_xsize = histobits ? (xsize + (1 << histobits) - 1) >> histobits : 1; int histo_ysize = histobits ? (ysize + (1 << histobits) - 1) >> histobits : 1; int i; @@ -241,8 +241,9 @@ int VP8LHistogramBuildImage(int xsize, int ysize, return 1; } -int VP8LHistogramCombine(VP8LHistogram** in, int in_size, int quality, - VP8LHistogram*** out_arg, int* out_size) { +static int HistogramCombine(VP8LHistogram** const in, int in_size, int quality, + VP8LHistogram*** const out_arg, + int* const out_size) { int ok = 0; int i; unsigned int seed = 0; @@ -339,7 +340,7 @@ Error: static double HistogramDistance(const VP8LHistogram* const square_histogram, int cur_symbol, int candidate_symbol, - VP8LHistogram** candidate_histograms) { + VP8LHistogram** const candidate_histograms) { double new_bit_cost; double previous_bit_cost; VP8LHistogram modified; @@ -367,8 +368,9 @@ static double HistogramDistance(const VP8LHistogram* const square_histogram, return new_bit_cost - previous_bit_cost; } -void VP8LHistogramRefine(VP8LHistogram** raw, int raw_size, - uint32_t* symbols, int out_size, VP8LHistogram** out) { +static void HistogramRefine(VP8LHistogram** const raw, int raw_size, + uint32_t* const symbols, int out_size, + VP8LHistogram** const out) { int i; // Find the best 'out' histogram for each of the raw histograms 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 diff --git a/src/enc/histogram.h b/src/enc/histogram.h index 7ce29f7b..400fb262 100644 --- a/src/enc/histogram.h +++ b/src/enc/histogram.h @@ -59,8 +59,7 @@ static WEBP_INLINE void VP8LHistogramInit(VP8LHistogram* const p, // The input data is the PixOrCopy data, which models the // literals, stop codes and backward references (both distances and lengths) void VP8LHistogramCreate(VP8LHistogram* const p, - const PixOrCopy* const literal_and_length, - int n_literal_and_length); + const VP8LBackwardRefs* const refs); 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_); } +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( int n, const int* const population_counts, double* const output); -// Build a 2d image of histograms, subresolutioned by (1 << histobits) to -// the original image. -int VP8LHistogramBuildImage(int xsize, int ysize, - int histobits, int palette_bits, - const PixOrCopy* backward_refs, - int backward_refs_size, - VP8LHistogram*** image, - int* histogram_size); - -// 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); +// Builds the histogram image. +int VP8LGetHistImageSymbols(int xsize, int ysize, + const VP8LBackwardRefs* const refs, + int quality, int histogram_bits, + int cache_bits, + VP8LHistogram*** histogram_image, + int* const histogram_image_size, + uint32_t* const histogram_symbols); #if defined(__cplusplus) || defined(c_plusplus) } diff --git a/src/enc/vp8l.c b/src/enc/vp8l.c index 63ce1d4d..50b20f36 100644 --- a/src/enc/vp8l.c +++ b/src/enc/vp8l.c @@ -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) { if (refs != NULL) { refs->refs = NULL; @@ -209,11 +202,11 @@ static int GetBackwardReferences(int width, int height, if (histo == NULL) goto Error1; // Evaluate lz77 coding VP8LHistogramInit(histo, cache_bits); - VP8LHistogramCreate(histo, refs_lz77.refs, refs_lz77.size); + VP8LHistogramCreate(histo, &refs_lz77); bit_cost_lz77 = (int)VP8LHistogramEstimateBits(histo); // Evaluate RLE coding VP8LHistogramInit(histo, cache_bits); - VP8LHistogramCreate(histo, refs_rle.refs, refs_rle.size); + VP8LHistogramCreate(histo, &refs_rle); bit_cost_rle = (int)VP8LHistogramEstimateBits(histo); // Decide if LZ77 is useful. lz77_is_useful = (bit_cost_lz77 < bit_cost_rle); @@ -259,58 +252,6 @@ End: 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. static int ValuesShouldBeCollapsedToStrideAverage(int a, int b) { return abs(a - b) < 4; @@ -750,10 +691,10 @@ static int EncodeImageInternal(VP8LBitWriter* const bw, goto Error; } // Build histogram image & symbols from backward references. - if (!GetHistImageSymbols(width, height, &refs, - quality, histogram_bits, cache_bits, - &histogram_image, &histogram_image_size, - histogram_symbols)) { + if (!VP8LGetHistImageSymbols(width, height, &refs, + quality, histogram_bits, cache_bits, + &histogram_image, &histogram_image_size, + histogram_symbols)) { goto Error; } // Create Huffman bit lengths & codes for each histogram image. @@ -816,7 +757,7 @@ static int EncodeImageInternal(VP8LBitWriter* const bw, } // Free combined histograms. - DeleteHistograms(histogram_image, histogram_image_size); + VP8LDeleteHistograms(histogram_image, histogram_image_size); histogram_image = NULL; // Emit no bits if there is only one symbol in the histogram. @@ -832,7 +773,7 @@ static int EncodeImageInternal(VP8LBitWriter* const bw, Error: if (!ok) { - DeleteHistograms(histogram_image, histogram_image_size); + VP8LDeleteHistograms(histogram_image, histogram_image_size); } VP8LClearBackwardRefs(&refs); for (i = 0; i < 5 * histogram_image_size; ++i) {