mirror of
https://github.com/webmproject/libwebp.git
synced 2025-07-13 06:24:27 +02:00
further simplification for the meta-Huffman coding
* don't transmit the number of Huffman tree group explicitly * move color-cache information before the meta-Huffman block * also add a check that color_cache_bits is in [1..11] range, as per spec. Change-Id: I81d7711068653b509cdbc1151d93e229c4254580
This commit is contained in:
committed by
James Zern
parent
e491729905
commit
8415ddf3be
@ -31,6 +31,7 @@ static const int kCodeLengthRepeatOffsets[3] = { 3, 3, 11 };
|
||||
#define NUM_LENGTH_CODES 24
|
||||
#define NUM_DISTANCE_CODES 40
|
||||
#define DEFAULT_CODE_LENGTH 8
|
||||
#define MAX_CACHE_BITS 11
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// Five Huffman codes are used at each meta code:
|
||||
@ -307,10 +308,9 @@ static void DeleteHtreeGroups(HTreeGroup* htree_groups, int num_htree_groups) {
|
||||
}
|
||||
|
||||
static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
int* const color_cache_bits_ptr) {
|
||||
int color_cache_bits) {
|
||||
int ok = 0;
|
||||
int i, j;
|
||||
int color_cache_size;
|
||||
VP8LBitReader* const br = &dec->br_;
|
||||
VP8LMetadata* const hdr = &dec->hdr_;
|
||||
uint32_t* huffman_image = NULL;
|
||||
@ -318,11 +318,11 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
int num_htree_groups = 1;
|
||||
|
||||
if (VP8LReadBits(br, 1)) { // use meta Huffman codes
|
||||
int meta_codes_nbits;
|
||||
const int huffman_precision = VP8LReadBits(br, 4);
|
||||
const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
|
||||
const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
|
||||
const int huffman_pixs = huffman_xsize * huffman_ysize;
|
||||
|
||||
if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
|
||||
&huffman_image)) {
|
||||
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
@ -331,19 +331,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
hdr->huffman_subsample_bits_ = huffman_precision;
|
||||
for (i = 0; i < huffman_pixs; ++i) {
|
||||
// The huffman data is stored in red and green bytes.
|
||||
huffman_image[i] = (huffman_image[i] >> 8) & 0xffff;
|
||||
const int index = (huffman_image[i] >> 8) & 0xffff;
|
||||
huffman_image[i] = index;
|
||||
if (index >= num_htree_groups) {
|
||||
num_htree_groups = index + 1;
|
||||
}
|
||||
}
|
||||
|
||||
meta_codes_nbits = VP8LReadBits(br, 4);
|
||||
num_htree_groups = 2 + VP8LReadBits(br, meta_codes_nbits);
|
||||
}
|
||||
|
||||
if (VP8LReadBits(br, 1)) { // use color cache
|
||||
*color_cache_bits_ptr = VP8LReadBits(br, 4);
|
||||
color_cache_size = 1 << *color_cache_bits_ptr;
|
||||
} else {
|
||||
*color_cache_bits_ptr = 0;
|
||||
color_cache_size = 0;
|
||||
}
|
||||
|
||||
htree_groups = (HTreeGroup*)calloc(num_htree_groups, sizeof(*htree_groups));
|
||||
@ -357,10 +350,10 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
|
||||
HuffmanTree* const htrees = htree_groups[i].htrees_;
|
||||
for (j = 0; j < HUFFMAN_CODES_PER_META_CODE; ++j) {
|
||||
int alphabet_size = kAlphabetSize[j];
|
||||
if (j == 0) {
|
||||
alphabet_size += color_cache_size;
|
||||
if (j == 0 && color_cache_bits > 0) {
|
||||
alphabet_size += 1 << color_cache_bits;
|
||||
}
|
||||
ok = ReadHuffmanCode(alphabet_size, dec, &htrees[j]);
|
||||
ok = ReadHuffmanCode(alphabet_size, dec, htrees + j);
|
||||
ok = ok && !br->error_;
|
||||
}
|
||||
}
|
||||
@ -835,29 +828,38 @@ static int DecodeImageStream(int xsize, int ysize,
|
||||
int ok = 1;
|
||||
int transform_xsize = xsize;
|
||||
int transform_ysize = ysize;
|
||||
VP8LBitReader* const br = &dec->br_;
|
||||
VP8LMetadata* const hdr = &dec->hdr_;
|
||||
uint32_t* data = NULL;
|
||||
const int transform_start_idx = dec->next_transform_;
|
||||
int color_cache_bits = 0;
|
||||
|
||||
VP8LBitReader* const br = &dec->br_;
|
||||
int transform_start_idx = dec->next_transform_;
|
||||
|
||||
// Step#1: Read the transforms (may recurse).
|
||||
// Read the transforms (may recurse).
|
||||
if (is_level0) {
|
||||
while (ok && VP8LReadBits(br, 1)) {
|
||||
ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
|
||||
}
|
||||
}
|
||||
|
||||
// Step#2: Read the Huffman codes (may recurse).
|
||||
ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
|
||||
&color_cache_bits);
|
||||
// Color cache
|
||||
if (ok && VP8LReadBits(br, 1)) {
|
||||
color_cache_bits = VP8LReadBits(br, 4);
|
||||
ok = (color_cache_bits >= 1 && color_cache_bits <= MAX_CACHE_BITS);
|
||||
if (!ok) {
|
||||
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
goto End;
|
||||
}
|
||||
}
|
||||
|
||||
// Read the Huffman codes (may recurse).
|
||||
ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
|
||||
color_cache_bits);
|
||||
if (!ok) {
|
||||
dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
|
||||
goto End;
|
||||
}
|
||||
|
||||
// Finish setting up the color-cache
|
||||
if (color_cache_bits > 0) {
|
||||
hdr->color_cache_size_ = 1 << color_cache_bits;
|
||||
hdr->color_cache_ = (VP8LColorCache*)malloc(sizeof(*hdr->color_cache_));
|
||||
@ -868,7 +870,6 @@ static int DecodeImageStream(int xsize, int ysize,
|
||||
goto End;
|
||||
}
|
||||
}
|
||||
|
||||
UpdateDecoder(dec, transform_xsize, transform_ysize);
|
||||
|
||||
if (is_level0) { // level 0 complete
|
||||
@ -883,11 +884,11 @@ static int DecodeImageStream(int xsize, int ysize,
|
||||
goto End;
|
||||
}
|
||||
|
||||
// Step#3: Use the Huffman trees to decode the LZ77 encoded data.
|
||||
// Use the Huffman trees to decode the LZ77 encoded data.
|
||||
ok = DecodeImageData(dec, data, transform_xsize, transform_ysize, 0);
|
||||
ok = ok && !br->error_;
|
||||
|
||||
// Step#4: Apply transforms on the decoded data.
|
||||
// Apply transforms on the decoded data.
|
||||
if (ok) ApplyInverseTransforms(dec, transform_start_idx, data);
|
||||
|
||||
End:
|
||||
|
Reference in New Issue
Block a user