in Extended/libwebp/src/dec/vp8l_dec.c [1414:1501]
static int DecodeImageStream(int xsize, int ysize,
int is_level0,
VP8LDecoder* const dec,
uint32_t** const decoded_data) {
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;
int color_cache_bits = 0;
// Read the transforms (may recurse).
if (is_level0) {
while (ok && VP8LReadBits(br, 1)) {
ok = ReadTransform(&transform_xsize, &transform_ysize, dec);
}
}
// 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, is_level0);
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;
if (!VP8LColorCacheInit(&hdr->color_cache_, color_cache_bits)) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
ok = 0;
goto End;
}
} else {
hdr->color_cache_size_ = 0;
}
UpdateDecoder(dec, transform_xsize, transform_ysize);
if (is_level0) { // level 0 complete
dec->state_ = READ_HDR;
goto End;
}
{
const uint64_t total_size = (uint64_t)transform_xsize * transform_ysize;
data = (uint32_t*)WebPSafeMalloc(total_size, sizeof(*data));
if (data == NULL) {
dec->status_ = VP8_STATUS_OUT_OF_MEMORY;
ok = 0;
goto End;
}
}
// Use the Huffman trees to decode the LZ77 encoded data.
ok = DecodeImageData(dec, data, transform_xsize, transform_ysize,
transform_ysize, NULL);
ok = ok && !br->eos_;
End:
if (!ok) {
WebPSafeFree(data);
ClearMetadata(hdr);
} else {
if (decoded_data != NULL) {
*decoded_data = data;
} else {
// We allocate image data in this function only for transforms. At level 0
// (that is: not the transforms), we shouldn't have allocated anything.
assert(data == NULL);
assert(is_level0);
}
dec->last_pixel_ = 0; // Reset for future DECODE_DATA_FUNC() calls.
if (!is_level0) ClearMetadata(hdr); // Clean up temporary data behind.
}
return ok;
}