mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-27 06:08:21 +01:00
Few more HuffmanTreeToken conversions.
Change-Id: I932b5368d279f83c462c7d916978dab3e81d7709
This commit is contained in:
parent
89c07c9660
commit
817c9dce61
@ -256,16 +256,13 @@ static void ClearHuffmanTreeIfOnlyOneSymbol(
|
|||||||
|
|
||||||
static void StoreHuffmanTreeToBitMask(
|
static void StoreHuffmanTreeToBitMask(
|
||||||
VP8LBitWriter* const bw,
|
VP8LBitWriter* const bw,
|
||||||
const HuffmanTreeToken* const tokens,
|
const HuffmanTreeToken* const tokens, const int num_tokens,
|
||||||
const int num_tokens,
|
const HuffmanTreeCode* const huffman_code) {
|
||||||
const uint8_t* code_length_bitdepth,
|
|
||||||
const uint16_t* code_length_bitdepth_symbols) {
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < num_tokens; ++i) {
|
for (i = 0; i < num_tokens; ++i) {
|
||||||
const int ix = tokens[i].code;
|
const int ix = tokens[i].code;
|
||||||
const int extra_bits = tokens[i].extra_bits;
|
const int extra_bits = tokens[i].extra_bits;
|
||||||
VP8LWriteBits(bw, code_length_bitdepth[ix],
|
VP8LWriteBits(bw, huffman_code->code_lengths[ix], huffman_code->codes[ix]);
|
||||||
code_length_bitdepth_symbols[ix]);
|
|
||||||
switch (ix) {
|
switch (ix) {
|
||||||
case 16:
|
case 16:
|
||||||
VP8LWriteBits(bw, 2, extra_bits);
|
VP8LWriteBits(bw, 2, extra_bits);
|
||||||
@ -281,15 +278,15 @@ static void StoreHuffmanTreeToBitMask(
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int StoreFullHuffmanCode(VP8LBitWriter* const bw,
|
static int StoreFullHuffmanCode(VP8LBitWriter* const bw,
|
||||||
const uint8_t* const bit_lengths,
|
const HuffmanTreeCode* const tree) {
|
||||||
int bit_lengths_size) {
|
|
||||||
int ok = 0;
|
int ok = 0;
|
||||||
uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 };
|
uint8_t code_length_bitdepth[CODE_LENGTH_CODES] = { 0 };
|
||||||
uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 };
|
uint16_t code_length_bitdepth_symbols[CODE_LENGTH_CODES] = { 0 };
|
||||||
|
const int max_tokens = tree->num_symbols;
|
||||||
int num_tokens;
|
int num_tokens;
|
||||||
HuffmanTreeCode huffman_code;
|
HuffmanTreeCode huffman_code;
|
||||||
HuffmanTreeToken* const tokens =
|
HuffmanTreeToken* const tokens =
|
||||||
(HuffmanTreeToken*)malloc(bit_lengths_size * sizeof(*tokens));
|
(HuffmanTreeToken*)malloc(max_tokens * sizeof(*tokens));
|
||||||
if (tokens == NULL) return 0;
|
if (tokens == NULL) return 0;
|
||||||
|
|
||||||
huffman_code.num_symbols = CODE_LENGTH_CODES;
|
huffman_code.num_symbols = CODE_LENGTH_CODES;
|
||||||
@ -297,8 +294,7 @@ static int StoreFullHuffmanCode(VP8LBitWriter* const bw,
|
|||||||
huffman_code.codes = code_length_bitdepth_symbols;
|
huffman_code.codes = code_length_bitdepth_symbols;
|
||||||
|
|
||||||
VP8LWriteBits(bw, 1, 0);
|
VP8LWriteBits(bw, 1, 0);
|
||||||
num_tokens = VP8LCreateCompressedHuffmanTree(bit_lengths, bit_lengths_size,
|
num_tokens = VP8LCreateCompressedHuffmanTree(tree, tokens, max_tokens);
|
||||||
tokens, bit_lengths_size);
|
|
||||||
{
|
{
|
||||||
int histogram[CODE_LENGTH_CODES] = { 0 };
|
int histogram[CODE_LENGTH_CODES] = { 0 };
|
||||||
int i;
|
int i;
|
||||||
@ -342,9 +338,7 @@ static int StoreFullHuffmanCode(VP8LBitWriter* const bw,
|
|||||||
VP8LWriteBits(bw, 3, nbitpairs - 1);
|
VP8LWriteBits(bw, 3, nbitpairs - 1);
|
||||||
VP8LWriteBits(bw, nbitpairs * 2, trimmed_length - 2);
|
VP8LWriteBits(bw, nbitpairs * 2, trimmed_length - 2);
|
||||||
}
|
}
|
||||||
StoreHuffmanTreeToBitMask(bw, tokens,
|
StoreHuffmanTreeToBitMask(bw, tokens, length, &huffman_code);
|
||||||
length, code_length_bitdepth,
|
|
||||||
code_length_bitdepth_symbols);
|
|
||||||
}
|
}
|
||||||
ok = 1;
|
ok = 1;
|
||||||
End:
|
End:
|
||||||
@ -353,8 +347,7 @@ static int StoreFullHuffmanCode(VP8LBitWriter* const bw,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int StoreHuffmanCode(VP8LBitWriter* const bw,
|
static int StoreHuffmanCode(VP8LBitWriter* const bw,
|
||||||
const uint8_t* const bit_lengths,
|
const HuffmanTreeCode* const huffman_code) {
|
||||||
int bit_lengths_size) {
|
|
||||||
int i;
|
int i;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
int symbols[2] = { 0, 0 };
|
int symbols[2] = { 0, 0 };
|
||||||
@ -362,8 +355,8 @@ static int StoreHuffmanCode(VP8LBitWriter* const bw,
|
|||||||
const int kMaxSymbol = 1 << kMaxBits;
|
const int kMaxSymbol = 1 << kMaxBits;
|
||||||
|
|
||||||
// Check whether it's a small tree.
|
// Check whether it's a small tree.
|
||||||
for (i = 0; i < bit_lengths_size && count < 3; ++i) {
|
for (i = 0; i < huffman_code->num_symbols && count < 3; ++i) {
|
||||||
if (bit_lengths[i] != 0) {
|
if (huffman_code->code_lengths[i] != 0) {
|
||||||
if (count < 2) symbols[count] = i;
|
if (count < 2) symbols[count] = i;
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
@ -388,7 +381,7 @@ static int StoreHuffmanCode(VP8LBitWriter* const bw,
|
|||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
return StoreFullHuffmanCode(bw, bit_lengths, bit_lengths_size);
|
return StoreFullHuffmanCode(bw, huffman_code);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -403,7 +396,7 @@ static void StoreImageToBitMask(
|
|||||||
VP8LBitWriter* const bw, int width, int histo_bits,
|
VP8LBitWriter* const bw, int width, int histo_bits,
|
||||||
const VP8LBackwardRefs* const refs,
|
const VP8LBackwardRefs* const refs,
|
||||||
const uint16_t* histogram_symbols,
|
const uint16_t* histogram_symbols,
|
||||||
HuffmanTreeCode* const huffman_codes) {
|
const HuffmanTreeCode* const huffman_codes) {
|
||||||
// x and y trace the position in the image.
|
// x and y trace the position in the image.
|
||||||
int x = 0;
|
int x = 0;
|
||||||
int y = 0;
|
int y = 0;
|
||||||
@ -526,11 +519,11 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
|
|||||||
|
|
||||||
// Store Huffman codes.
|
// Store Huffman codes.
|
||||||
for (i = 0; i < 5 * histogram_image_size; ++i) {
|
for (i = 0; i < 5 * histogram_image_size; ++i) {
|
||||||
const HuffmanTreeCode* const codes = &huffman_codes[i];
|
HuffmanTreeCode* const codes = &huffman_codes[i];
|
||||||
if (!StoreHuffmanCode(bw, codes->code_lengths, codes->num_symbols)) {
|
if (!StoreHuffmanCode(bw, codes)) {
|
||||||
goto Error;
|
goto Error;
|
||||||
}
|
}
|
||||||
ClearHuffmanTreeIfOnlyOneSymbol(&huffman_codes[i]);
|
ClearHuffmanTreeIfOnlyOneSymbol(codes);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Free combined histograms.
|
// Free combined histograms.
|
||||||
|
@ -349,20 +349,19 @@ static HuffmanTreeToken* CodeRepeatedZeros(int repetitions,
|
|||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|
||||||
int VP8LCreateCompressedHuffmanTree(const uint8_t* const depth,
|
int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree,
|
||||||
int depth_size,
|
HuffmanTreeToken* tokens, int max_tokens) {
|
||||||
HuffmanTreeToken* tokens,
|
|
||||||
int max_tokens) {
|
|
||||||
HuffmanTreeToken* const starting_token = tokens;
|
HuffmanTreeToken* const starting_token = tokens;
|
||||||
HuffmanTreeToken* const ending_token = tokens + max_tokens;
|
HuffmanTreeToken* const ending_token = tokens + max_tokens;
|
||||||
|
const int depth_size = tree->num_symbols;
|
||||||
int prev_value = 8; // 8 is the initial value for rle.
|
int prev_value = 8; // 8 is the initial value for rle.
|
||||||
int i = 0;
|
int i = 0;
|
||||||
assert(tokens != NULL);
|
assert(tokens != NULL);
|
||||||
while (i < depth_size) {
|
while (i < depth_size) {
|
||||||
const int value = depth[i];
|
const int value = tree->code_lengths[i];
|
||||||
int k = i + 1;
|
int k = i + 1;
|
||||||
int runs;
|
int runs;
|
||||||
while (k < depth_size && depth[k] == value) ++k;
|
while (k < depth_size && tree->code_lengths[k] == value) ++k;
|
||||||
runs = k - i;
|
runs = k - i;
|
||||||
if (value == 0) {
|
if (value == 0) {
|
||||||
tokens = CodeRepeatedZeros(runs, tokens);
|
tokens = CodeRepeatedZeros(runs, tokens);
|
||||||
|
@ -26,11 +26,6 @@ typedef struct {
|
|||||||
uint8_t extra_bits; // extra bits for escape codes
|
uint8_t extra_bits; // extra bits for escape codes
|
||||||
} HuffmanTreeToken;
|
} HuffmanTreeToken;
|
||||||
|
|
||||||
// Turn the Huffman tree into a token sequence.
|
|
||||||
// Returns the number of tokens used.
|
|
||||||
int VP8LCreateCompressedHuffmanTree(const uint8_t* const depth, int depth_size,
|
|
||||||
HuffmanTreeToken* tokens, int max_tokens);
|
|
||||||
|
|
||||||
// Struct to represent the tree codes (depth and bits array).
|
// Struct to represent the tree codes (depth and bits array).
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int num_symbols; // Number of symbols.
|
int num_symbols; // Number of symbols.
|
||||||
@ -38,6 +33,11 @@ typedef struct {
|
|||||||
uint16_t* codes; // Symbol Codes.
|
uint16_t* codes; // Symbol Codes.
|
||||||
} HuffmanTreeCode;
|
} HuffmanTreeCode;
|
||||||
|
|
||||||
|
// Turn the Huffman tree into a token sequence.
|
||||||
|
// Returns the number of tokens used.
|
||||||
|
int VP8LCreateCompressedHuffmanTree(const HuffmanTreeCode* const tree,
|
||||||
|
HuffmanTreeToken* tokens, int max_tokens);
|
||||||
|
|
||||||
// Create an optimized tree, and tokenize it.
|
// Create an optimized tree, and tokenize it.
|
||||||
int VP8LCreateHuffmanTree(int* const histogram, int tree_depth_limit,
|
int VP8LCreateHuffmanTree(int* const histogram, int tree_depth_limit,
|
||||||
HuffmanTreeCode* const tree);
|
HuffmanTreeCode* const tree);
|
||||||
|
Loading…
Reference in New Issue
Block a user