Merge "Stop indefinite recursion for Huffman Image."

This commit is contained in:
pascal massimino 2012-06-07 10:52:26 -07:00 committed by Gerrit Code Review
commit e2ffe446bd
2 changed files with 41 additions and 31 deletions

View File

@ -302,7 +302,7 @@ static void DeleteHtreeGroups(HTreeGroup* htree_groups, int num_htree_groups) {
} }
static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize, static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
int color_cache_bits) { int color_cache_bits, int allow_recursion) {
int i, j; int i, j;
VP8LBitReader* const br = &dec->br_; VP8LBitReader* const br = &dec->br_;
VP8LMetadata* const hdr = &dec->hdr_; VP8LMetadata* const hdr = &dec->hdr_;
@ -310,12 +310,12 @@ static int ReadHuffmanCodes(VP8LDecoder* const dec, int xsize, int ysize,
HTreeGroup* htree_groups = NULL; HTreeGroup* htree_groups = NULL;
int num_htree_groups = 1; int num_htree_groups = 1;
if (VP8LReadBits(br, 1)) { // use meta Huffman codes if (allow_recursion && VP8LReadBits(br, 1)) {
// use meta Huffman codes.
const int huffman_precision = VP8LReadBits(br, 3) + 2; const int huffman_precision = VP8LReadBits(br, 3) + 2;
const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision); const int huffman_xsize = VP8LSubSampleSize(xsize, huffman_precision);
const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision); const int huffman_ysize = VP8LSubSampleSize(ysize, huffman_precision);
const int huffman_pixs = huffman_xsize * huffman_ysize; const int huffman_pixs = huffman_xsize * huffman_ysize;
if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec, if (!DecodeImageStream(huffman_xsize, huffman_ysize, 0, dec,
&huffman_image)) { &huffman_image)) {
dec->status_ = VP8_STATUS_BITSTREAM_ERROR; dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
@ -862,7 +862,7 @@ static int DecodeImageStream(int xsize, int ysize,
// Read the Huffman codes (may recurse). // Read the Huffman codes (may recurse).
ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize, ok = ok && ReadHuffmanCodes(dec, transform_xsize, transform_ysize,
color_cache_bits); color_cache_bits, is_level0);
if (!ok) { if (!ok) {
dec->status_ = VP8_STATUS_BITSTREAM_ERROR; dec->status_ = VP8_STATUS_BITSTREAM_ERROR;
goto End; goto End;

View File

@ -33,6 +33,10 @@ extern "C" {
#define MIN_HISTO_BITS 2 #define MIN_HISTO_BITS 2
#define MAX_HISTO_BITS 9 #define MAX_HISTO_BITS 9
// NO_HISTO_BITS needs to be large enough so that all bits in the image
// size are thrown away by shifting.
#define NO_HISTO_BITS (VP8L_IMAGE_SIZE_BITS + 1)
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Palette // Palette
@ -442,10 +446,11 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
int cache_bits, int histogram_bits) { int cache_bits, int histogram_bits) {
int i; int i;
int ok = 0; int ok = 0;
int write_histogram_image;
const int use_2d_locality = 1; const int use_2d_locality = 1;
const int use_color_cache = (cache_bits > 0); const int use_color_cache = (cache_bits > 0);
const int histogram_image_xysize = const int histogram_image_xysize =
(histogram_bits == NO_HISTO_BITS) ?
1 :
VP8LSubSampleSize(width, histogram_bits) * VP8LSubSampleSize(width, histogram_bits) *
VP8LSubSampleSize(height, histogram_bits); VP8LSubSampleSize(height, histogram_bits);
VP8LHistogramSet* histogram_image = VP8LHistogramSet* histogram_image =
@ -456,7 +461,8 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
VP8LBackwardRefs refs; VP8LBackwardRefs refs;
uint16_t* const histogram_symbols = uint16_t* const histogram_symbols =
(uint16_t*)malloc(histogram_image_xysize * sizeof(*histogram_symbols)); (uint16_t*)malloc(histogram_image_xysize * sizeof(*histogram_symbols));
assert((histogram_bits >= 2 && histogram_bits <= 9) ||
histogram_bits == NO_HISTO_BITS);
if (histogram_image == NULL || histogram_symbols == NULL) goto Error; if (histogram_image == NULL || histogram_symbols == NULL) goto Error;
// Calculate backward references from ARGB image. // Calculate backward references from ARGB image.
@ -488,30 +494,31 @@ static int EncodeImageInternal(VP8LBitWriter* const bw,
} }
// Huffman image + meta huffman. // Huffman image + meta huffman.
write_histogram_image = (histogram_image_size > 1); if (histogram_bits != NO_HISTO_BITS) {
VP8LWriteBits(bw, 1, write_histogram_image); const int write_histogram_image = (histogram_image_size > 1);
if (write_histogram_image) { VP8LWriteBits(bw, 1, write_histogram_image);
uint32_t* const histogram_argb = if (write_histogram_image) {
(uint32_t*)malloc(histogram_image_xysize * sizeof(*histogram_argb)); uint32_t* const histogram_argb =
int max_index = 0; (uint32_t*)malloc(histogram_image_xysize * sizeof(*histogram_argb));
if (histogram_argb == NULL) goto Error; int max_index = 0;
for (i = 0; i < histogram_image_xysize; ++i) { if (histogram_argb == NULL) goto Error;
const int index = histogram_symbols[i] & 0xffff; for (i = 0; i < histogram_image_xysize; ++i) {
histogram_argb[i] = 0xff000000 | (index << 8); const int index = histogram_symbols[i] & 0xffff;
if (index >= max_index) { histogram_argb[i] = 0xff000000 | (index << 8);
max_index = index + 1; if (index >= max_index) {
max_index = index + 1;
}
} }
} histogram_image_size = max_index;
histogram_image_size = max_index;
assert(histogram_bits >= 2); VP8LWriteBits(bw, 3, histogram_bits - 2);
VP8LWriteBits(bw, 3, histogram_bits - 2); ok = EncodeImageInternal(bw, histogram_argb,
ok = EncodeImageInternal(bw, histogram_argb, VP8LSubSampleSize(width, histogram_bits),
VP8LSubSampleSize(width, histogram_bits), VP8LSubSampleSize(height, histogram_bits),
VP8LSubSampleSize(height, histogram_bits), quality, 0, NO_HISTO_BITS);
quality, 0, 0); free(histogram_argb);
free(histogram_argb); if (!ok) goto Error;
if (!ok) goto Error; }
} }
// Store Huffman codes. // Store Huffman codes.
@ -601,7 +608,8 @@ static int ApplyPredictFilter(const VP8LEncoder* const enc,
assert(pred_bits >= 2); assert(pred_bits >= 2);
VP8LWriteBits(bw, 3, pred_bits - 2); VP8LWriteBits(bw, 3, pred_bits - 2);
if (!EncodeImageInternal(bw, enc->transform_data_, if (!EncodeImageInternal(bw, enc->transform_data_,
transform_width, transform_height, quality, 0, 0)) { transform_width, transform_height, quality, 0,
NO_HISTO_BITS)) {
return 0; return 0;
} }
return 1; return 1;
@ -622,7 +630,8 @@ static int ApplyCrossColorFilter(const VP8LEncoder* const enc,
assert(ccolor_transform_bits >= 2); assert(ccolor_transform_bits >= 2);
VP8LWriteBits(bw, 3, ccolor_transform_bits - 2); VP8LWriteBits(bw, 3, ccolor_transform_bits - 2);
if (!EncodeImageInternal(bw, enc->transform_data_, if (!EncodeImageInternal(bw, enc->transform_data_,
transform_width, transform_height, quality, 0, 0)) { transform_width, transform_height, quality, 0,
NO_HISTO_BITS)) {
return 0; return 0;
} }
return 1; return 1;
@ -786,7 +795,8 @@ static WebPEncodingError ApplyPalette(VP8LBitWriter* const bw,
for (i = palette_size - 1; i >= 1; --i) { for (i = palette_size - 1; i >= 1; --i) {
palette[i] = VP8LSubPixels(palette[i], palette[i - 1]); palette[i] = VP8LSubPixels(palette[i], palette[i - 1]);
} }
if (!EncodeImageInternal(bw, palette, palette_size, 1, quality, 0, 0)) { if (!EncodeImageInternal(bw, palette, palette_size, 1, quality, 0,
NO_HISTO_BITS)) {
err = VP8_ENC_ERROR_INVALID_CONFIGURATION; err = VP8_ENC_ERROR_INVALID_CONFIGURATION;
goto Error; goto Error;
} }