roytam followup webp patch

This commit is contained in:
Cameron Kaiser 2023-09-17 22:55:38 -07:00
parent d43821e1f8
commit b1c0b3e0c7
2 changed files with 74 additions and 59 deletions

View File

@ -364,11 +364,7 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
VP8LMetadata* const hdr = &dec->hdr_; VP8LMetadata* const hdr = &dec->hdr_;
uint32_t* huffman_image = NULL; uint32_t* huffman_image = NULL;
HTreeGroup* htree_groups = NULL; HTreeGroup* htree_groups = NULL;
// When reading htrees, some might be unused, as the format allows it.
// We will still read them but put them in this htree_group_bogus.
HTreeGroup htree_group_bogus;
HuffmanTables* huffman_tables = &hdr->huffman_tables_; HuffmanTables* huffman_tables = &hdr->huffman_tables_;
HuffmanCode* next = NULL;
int num_htree_groups = 1; int num_htree_groups = 1;
int num_htree_groups_max = 1; int num_htree_groups_max = 1;
int max_alphabet_size = 0; int max_alphabet_size = 0;
@ -453,59 +449,70 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
} }
for (i = 0; i < num_htree_groups_max; ++i) { for (i = 0; i < num_htree_groups_max; ++i) {
// If the index "i" is unused in the Huffman image, read the coefficients // If the index "i" is unused in the Huffman image, just make sure the
// but store them to a bogus htree_group. // coefficients are valid but do not store them.
const int is_bogus = (mapping != NULL && mapping[i] == -1); if (mapping != NULL && mapping[i] == -1) {
HTreeGroup* const htree_group = for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
is_bogus ? &htree_group_bogus : int alphabet_size = kAlphabetSize[j];
&htree_groups[(mapping == NULL) ? i : mapping[i]]; if (j == 0 && color_cache_bits > 0) {
HuffmanCode** const htrees = htree_group->htrees; alphabet_size += (1 << color_cache_bits);
int size; }
int total_size = 0; // Passing in NULL so that nothing gets filled.
int is_trivial_literal = 1; if (!ReadHuffmanCode(alphabet_size, dec, code_lengths, NULL)) {
int max_bits = 0; goto Error;
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
int alphabet_size = kAlphabetSize[j];
if (j == 0 && color_cache_bits > 0) {
alphabet_size += 1 << color_cache_bits;
}
size =
ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);
htrees[j] = huffman_tables->curr_segment->curr_table;
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
is_trivial_literal = (htrees[j]->bits == 0);
}
total_size += htrees[j]->bits;
huffman_tables->curr_segment->curr_table += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
for (k = 1; k < alphabet_size; ++k) {
if (code_lengths[k] > local_max_bits) {
local_max_bits = code_lengths[k];
}
} }
max_bits += local_max_bits;
} }
} } else {
htree_group->is_trivial_literal = is_trivial_literal; HTreeGroup* const htree_group =
htree_group->is_trivial_code = 0; &htree_groups[(mapping == NULL) ? i : mapping[i]];
if (is_trivial_literal) { HuffmanCode** const htrees = htree_group->htrees;
const int red = htrees[RED][0].value; int size;
const int blue = htrees[BLUE][0].value; int total_size = 0;
const int alpha = htrees[ALPHA][0].value; int is_trivial_literal = 1;
htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue; int max_bits = 0;
if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) { for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
htree_group->is_trivial_code = 1; int alphabet_size = kAlphabetSize[j];
htree_group->literal_arb |= htrees[GREEN][0].value << 8; if (j == 0 && color_cache_bits > 0) {
alphabet_size += (1 << color_cache_bits);
}
size =
ReadHuffmanCode(alphabet_size, dec, code_lengths, huffman_tables);
htrees[j] = huffman_tables->curr_segment->curr_table;
if (size == 0) {
goto Error;
}
if (is_trivial_literal && kLiteralMap[j] == 1) {
is_trivial_literal = (htrees[j]->bits == 0);
}
total_size += htrees[j]->bits;
huffman_tables->curr_segment->curr_table += size;
if (j <= ALPHA) {
int local_max_bits = code_lengths[0];
int k;
for (k = 1; k < alphabet_size; ++k) {
if (code_lengths[k] > local_max_bits) {
local_max_bits = code_lengths[k];
}
}
max_bits += local_max_bits;
}
} }
htree_group->is_trivial_literal = is_trivial_literal;
htree_group->is_trivial_code = 0;
if (is_trivial_literal) {
const int red = htrees[RED][0].value;
const int blue = htrees[BLUE][0].value;
const int alpha = htrees[ALPHA][0].value;
htree_group->literal_arb = ((uint32_t)alpha << 24) | (red << 16) | blue;
if (total_size == 0 && htrees[GREEN][0].value < NUM_LITERAL_CODES) {
htree_group->is_trivial_code = 1;
htree_group->literal_arb |= htrees[GREEN][0].value << 8;
}
}
htree_group->use_packed_table =
!htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
if (htree_group->use_packed_table) BuildPackedTable(htree_group);
} }
htree_group->use_packed_table =
!htree_group->is_trivial_code && (max_bits < HUFFMAN_PACKED_BITS);
if (htree_group->use_packed_table) BuildPackedTable(htree_group);
} }
ok = 1; ok = 1;

View File

@ -91,7 +91,8 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
assert(code_lengths_size != 0); assert(code_lengths_size != 0);
assert(code_lengths != NULL); assert(code_lengths != NULL);
assert(root_table != NULL); assert((root_table != NULL && sorted != NULL) ||
(root_table == NULL && sorted == NULL));
assert(root_bits > 0); assert(root_bits > 0);
// Build histogram of code lengths. // Build histogram of code lengths.
@ -120,16 +121,22 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
for (symbol = 0; symbol < code_lengths_size; ++symbol) { for (symbol = 0; symbol < code_lengths_size; ++symbol) {
const int symbol_code_length = code_lengths[symbol]; const int symbol_code_length = code_lengths[symbol];
if (code_lengths[symbol] > 0) { if (code_lengths[symbol] > 0) {
sorted[offset[symbol_code_length]++] = symbol; if (sorted != NULL) {
sorted[offset[symbol_code_length]++] = symbol;
} else {
offset[symbol_code_length]++;
}
} }
} }
// Special case code with only one value. // Special case code with only one value.
if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) { if (offset[MAX_ALLOWED_CODE_LENGTH] == 1) {
HuffmanCode code; if (sorted != NULL) {
code.bits = 0; HuffmanCode code;
code.value = (uint16_t)sorted[0]; code.bits = 0;
ReplicateValue(table, 1, total_size, code); code.value = (uint16_t)sorted[0];
ReplicateValue(table, 1, total_size, code);
}
return total_size; return total_size;
} }
@ -151,6 +158,7 @@ static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
if (num_open < 0) { if (num_open < 0) {
return 0; return 0;
} }
if (root_table == NULL) continue;
for (; count[len] > 0; --count[len]) { for (; count[len] > 0; --count[len]) {
HuffmanCode code; HuffmanCode code;
code.bits = (uint8_t)len; code.bits = (uint8_t)len;