Skip to content

Commit

Permalink
Remove a useless malloc for entropy image
Browse files Browse the repository at this point in the history
histogram_symbols is converted to uint32_t and <<8 into
histogram_argb.
Using a uint32_t buffer from the start prevents copying and
converting the data.

Change-Id: I245003a6a0f048c31519afa25a600d4479e762e3
  • Loading branch information
vrabaud committed Sep 18, 2024
1 parent bc49176 commit a78c535
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 47 deletions.
20 changes: 10 additions & 10 deletions src/enc/histogram_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,11 +601,11 @@ static void HistogramBuild(
}

// Copies the histograms and computes its bit_cost.
static const uint16_t kInvalidHistogramSymbol = (uint16_t)(-1);
static const uint32_t kInvalidHistogramSymbol = (uint32_t)(-1);
static void HistogramCopyAndAnalyze(VP8LHistogramSet* const orig_histo,
VP8LHistogramSet* const image_histo,
int* const num_used,
uint16_t* const histogram_symbols) {
uint32_t* const histogram_symbols) {
int i, cluster_id;
int num_used_orig = *num_used;
VP8LHistogram** const orig_histograms = orig_histo->histograms;
Expand Down Expand Up @@ -667,7 +667,7 @@ static void HistogramAnalyzeEntropyBin(VP8LHistogramSet* const image_histo,
// 'combine_cost_factor' has to be divided by 100.
static void HistogramCombineEntropyBin(
VP8LHistogramSet* const image_histo, int* num_used,
const uint16_t* const clusters, uint16_t* const cluster_mappings,
const uint32_t* const clusters, uint16_t* const cluster_mappings,
VP8LHistogram* cur_combo, const uint16_t* const bin_map, int num_bins,
int32_t combine_cost_factor, int low_effort) {
VP8LHistogram** const histograms = image_histo->histograms;
Expand Down Expand Up @@ -1070,7 +1070,7 @@ static int HistogramCombineStochastic(VP8LHistogramSet* const image_histo,
// Note: we assume that out[]->bit_cost_ is already up-to-date.
static void HistogramRemap(const VP8LHistogramSet* const in,
VP8LHistogramSet* const out,
uint16_t* const symbols) {
uint32_t* const symbols) {
int i;
VP8LHistogram** const in_histo = in->histograms;
VP8LHistogram** const out_histo = out->histograms;
Expand Down Expand Up @@ -1131,10 +1131,10 @@ static int32_t GetCombineCostFactor(int histo_size, int quality) {
// assign the smallest possible clusters values.
static void OptimizeHistogramSymbols(const VP8LHistogramSet* const set,
uint16_t* const cluster_mappings,
int num_clusters,
uint32_t num_clusters,
uint16_t* const cluster_mappings_tmp,
uint16_t* const symbols) {
int i, cluster_max;
uint32_t* const symbols) {
uint32_t i, cluster_max;
int do_continue = 1;
// First, assign the lowest cluster to each pixel.
while (do_continue) {
Expand All @@ -1158,7 +1158,7 @@ static void OptimizeHistogramSymbols(const VP8LHistogramSet* const set,
set->max_size * sizeof(*cluster_mappings_tmp));
assert(cluster_mappings[0] == 0);
// Re-map the ids.
for (i = 0; i < set->max_size; ++i) {
for (i = 0; i < (uint32_t)set->max_size; ++i) {
int cluster;
if (symbols[i] == kInvalidHistogramSymbol) continue;
cluster = cluster_mappings[symbols[i]];
Expand All @@ -1172,7 +1172,7 @@ static void OptimizeHistogramSymbols(const VP8LHistogramSet* const set,

// Make sure all cluster values are used.
cluster_max = 0;
for (i = 0; i < set->max_size; ++i) {
for (i = 0; i < (uint32_t)set->max_size; ++i) {
if (symbols[i] == kInvalidHistogramSymbol) continue;
if (symbols[i] <= cluster_max) continue;
++cluster_max;
Expand All @@ -1195,7 +1195,7 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
int low_effort, int histogram_bits, int cache_bits,
VP8LHistogramSet* const image_histo,
VP8LHistogram* const tmp_histo,
uint16_t* const histogram_symbols,
uint32_t* const histogram_symbols,
const WebPPicture* const pic, int percent_range,
int* const percent) {
const int histo_xsize =
Expand Down
2 changes: 1 addition & 1 deletion src/enc/histogram_enc.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ int VP8LGetHistoImageSymbols(int xsize, int ysize,
int low_effort, int histogram_bits, int cache_bits,
VP8LHistogramSet* const image_histo,
VP8LHistogram* const tmp_histo,
uint16_t* const histogram_symbols,
uint32_t* const histogram_symbols,
const WebPPicture* const pic, int percent_range,
int* const percent);

Expand Down
63 changes: 27 additions & 36 deletions src/enc/vp8l_enc.c
Original file line number Diff line number Diff line change
Expand Up @@ -664,28 +664,31 @@ static WEBP_INLINE void WriteHuffmanCodeWithExtraBits(
VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits);
}

static int StoreImageToBitMask(
VP8LBitWriter* const bw, int width, int histo_bits,
const VP8LBackwardRefs* const refs,
const uint16_t* histogram_symbols,
const HuffmanTreeCode* const huffman_codes, const WebPPicture* const pic) {
static int StoreImageToBitMask(VP8LBitWriter* const bw, int width,
int histo_bits,
const VP8LBackwardRefs* const refs,
const uint32_t* histogram_symbols,
const HuffmanTreeCode* const huffman_codes,
const WebPPicture* const pic) {
const int histo_xsize = histo_bits ? VP8LSubSampleSize(width, histo_bits) : 1;
const int tile_mask = (histo_bits == 0) ? 0 : -(1 << histo_bits);
// x and y trace the position in the image.
int x = 0;
int y = 0;
int tile_x = x & tile_mask;
int tile_y = y & tile_mask;
int histogram_ix = histogram_symbols[0];
int histogram_ix = (histogram_symbols[0] >> 8) & 0xffff;
const HuffmanTreeCode* codes = huffman_codes + 5 * histogram_ix;
VP8LRefsCursor c = VP8LRefsCursorInit(refs);
while (VP8LRefsCursorOk(&c)) {
const PixOrCopy* const v = c.cur_pos;
if ((tile_x != (x & tile_mask)) || (tile_y != (y & tile_mask))) {
tile_x = x & tile_mask;
tile_y = y & tile_mask;
histogram_ix = histogram_symbols[(y >> histo_bits) * histo_xsize +
(x >> histo_bits)];
histogram_ix = (histogram_symbols[(y >> histo_bits) * histo_xsize +
(x >> histo_bits)] >>
8) &
0xffff;
codes = huffman_codes + 5 * histogram_ix;
}
if (PixOrCopyIsLiteral(v)) {
Expand Down Expand Up @@ -741,7 +744,7 @@ static int EncodeImageNoHuffman(VP8LBitWriter* const bw,
VP8LBackwardRefs* refs;
HuffmanTreeToken* tokens = NULL;
HuffmanTreeCode huffman_codes[5] = {{0, NULL, NULL}};
const uint16_t histogram_symbols[1] = {0}; // only one tree, one symbol
const uint32_t histogram_symbols[1] = {0}; // only one tree, one symbol
int cache_bits = 0;
VP8LHistogramSet* histogram_image = NULL;
HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc(
Expand Down Expand Up @@ -834,14 +837,14 @@ static int EncodeImageInternal(
int percent_start = *percent;
VP8LHistogramSet* histogram_image = NULL;
VP8LHistogram* tmp_histo = NULL;
int histogram_image_size = 0;
uint32_t i, histogram_image_size = 0;
size_t bit_array_size = 0;
HuffmanTree* const huff_tree = (HuffmanTree*)WebPSafeMalloc(
3ULL * CODE_LENGTH_CODES, sizeof(*huff_tree));
HuffmanTreeToken* tokens = NULL;
HuffmanTreeCode* huffman_codes = NULL;
uint16_t* const histogram_symbols = (uint16_t*)WebPSafeMalloc(
histogram_image_xysize, sizeof(*histogram_symbols));
uint32_t* const histogram_argb = (uint32_t*)WebPSafeMalloc(
histogram_image_xysize, sizeof(*histogram_argb));
int sub_configs_idx;
int cache_bits_init, write_histogram_image;
VP8LBitWriter bw_init = *bw, bw_best;
Expand All @@ -860,7 +863,7 @@ static int EncodeImageInternal(
}

// Make sure we can allocate the different objects.
if (huff_tree == NULL || histogram_symbols == NULL ||
if (huff_tree == NULL || histogram_argb == NULL ||
!VP8LHashChainInit(&hash_chain_histogram, histogram_image_xysize)) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
goto Error;
Expand Down Expand Up @@ -923,7 +926,7 @@ static int EncodeImageInternal(
if (!VP8LGetHistoImageSymbols(
width, height, &refs_array[i_cache], quality, low_effort,
histogram_bits, cache_bits_tmp, histogram_image, tmp_histo,
histogram_symbols, pic, i_percent_range, percent)) {
histogram_argb, pic, i_percent_range, percent)) {
goto Error;
}
// Create Huffman bit lengths and codes for each histogram image.
Expand Down Expand Up @@ -956,26 +959,17 @@ static int EncodeImageInternal(
}

// Huffman image + meta huffman.
histogram_image_size = 0;
for (i = 0; i < histogram_image_xysize; ++i) {
if (histogram_argb[i] >= histogram_image_size) {
histogram_image_size = histogram_argb[i] + 1;
}
histogram_argb[i] <<= 8;
}

write_histogram_image = (histogram_image_size > 1);
VP8LPutBits(bw, write_histogram_image, 1);
if (write_histogram_image) {
uint32_t* const histogram_argb = (uint32_t*)WebPSafeMalloc(
histogram_image_xysize, sizeof(*histogram_argb));
int max_index = 0;
uint32_t i;
if (histogram_argb == NULL) {
WebPEncodingSetError(pic, VP8_ENC_ERROR_OUT_OF_MEMORY);
goto Error;
}
for (i = 0; i < histogram_image_xysize; ++i) {
const int symbol_index = histogram_symbols[i] & 0xffff;
histogram_argb[i] = (symbol_index << 8);
if (symbol_index >= max_index) {
max_index = symbol_index + 1;
}
}
histogram_image_size = max_index;

VP8LPutBits(bw, histogram_bits - 2, 3);
i_percent_range = i_remaining_percent / 2;
i_remaining_percent -= i_percent_range;
Expand All @@ -984,15 +978,12 @@ static int EncodeImageInternal(
VP8LSubSampleSize(width, histogram_bits),
VP8LSubSampleSize(height, histogram_bits), quality, low_effort,
pic, i_percent_range, percent)) {
WebPSafeFree(histogram_argb);
goto Error;
}
WebPSafeFree(histogram_argb);
}

// Store Huffman codes.
{
int i;
int max_tokens = 0;
// Find maximum number of symbols for the huffman tree-set.
for (i = 0; i < 5 * histogram_image_size; ++i) {
Expand All @@ -1015,7 +1006,7 @@ static int EncodeImageInternal(
// Store actual literals.
hdr_size_tmp = (int)(VP8LBitWriterNumBytes(bw) - init_byte_position);
if (!StoreImageToBitMask(bw, width, histogram_bits, &refs_array[i_cache],
histogram_symbols, huffman_codes, pic)) {
histogram_argb, huffman_codes, pic)) {
goto Error;
}
// Keep track of the smallest image so far.
Expand Down Expand Up @@ -1052,7 +1043,7 @@ static int EncodeImageInternal(
WebPSafeFree(huffman_codes->codes);
WebPSafeFree(huffman_codes);
}
WebPSafeFree(histogram_symbols);
WebPSafeFree(histogram_argb);
VP8LBitWriterWipeOut(&bw_best);
return (pic->error_code == VP8_ENC_OK);
}
Expand Down

0 comments on commit a78c535

Please sign in to comment.