lossless: combine the Huffman code with extra bits

gives 2 % speedup
24.9 -> 25.5 MP/s for a photo with -q 0 -m 0

Change-Id: If9ae04683a86dd7b1fced2183cf79b9349a24a9e
This commit is contained in:
Jyrki Alakuijala 2015-06-29 13:25:42 +00:00 committed by James Zern
parent c4855ca249
commit 52931fd548

View File

@ -663,7 +663,7 @@ static void StoreHuffmanCode(VP8LBitWriter* const bw,
} }
} }
static void WriteHuffmanCode(VP8LBitWriter* const bw, static WEBP_INLINE void WriteHuffmanCode(VP8LBitWriter* const bw,
const HuffmanTreeCode* const code, const HuffmanTreeCode* const code,
int code_index) { int code_index) {
const int depth = code->code_lengths[code_index]; const int depth = code->code_lengths[code_index];
@ -671,6 +671,17 @@ static void WriteHuffmanCode(VP8LBitWriter* const bw,
VP8LPutBits(bw, symbol, depth); VP8LPutBits(bw, symbol, depth);
} }
static WEBP_INLINE void WriteHuffmanCodeWithExtraBits(
VP8LBitWriter* const bw,
const HuffmanTreeCode* const code,
int code_index,
int bits,
int n_bits) {
const int depth = code->code_lengths[code_index];
const int symbol = code->codes[code_index];
VP8LPutBits(bw, (bits << depth) | symbol, depth + n_bits);
}
static WebPEncodingError StoreImageToBitMask( static WebPEncodingError StoreImageToBitMask(
VP8LBitWriter* const bw, int width, int histo_bits, VP8LBitWriter* const bw, int width, int histo_bits,
VP8LBackwardRefs* const refs, VP8LBackwardRefs* const refs,
@ -695,26 +706,29 @@ static WebPEncodingError StoreImageToBitMask(
(x >> histo_bits)]; (x >> histo_bits)];
codes = huffman_codes + 5 * histogram_ix; codes = huffman_codes + 5 * histogram_ix;
} }
if (PixOrCopyIsCacheIdx(v)) { if (PixOrCopyIsLiteral(v)) {
const int code = PixOrCopyCacheIdx(v);
const int literal_ix = 256 + NUM_LENGTH_CODES + code;
WriteHuffmanCode(bw, codes, literal_ix);
} else if (PixOrCopyIsLiteral(v)) {
static const int order[] = { 1, 2, 0, 3 }; static const int order[] = { 1, 2, 0, 3 };
int k; int k;
for (k = 0; k < 4; ++k) { for (k = 0; k < 4; ++k) {
const int code = PixOrCopyLiteral(v, order[k]); const int code = PixOrCopyLiteral(v, order[k]);
WriteHuffmanCode(bw, codes + k, code); WriteHuffmanCode(bw, codes + k, code);
} }
} else if (PixOrCopyIsCacheIdx(v)) {
const int code = PixOrCopyCacheIdx(v);
const int literal_ix = 256 + NUM_LENGTH_CODES + code;
WriteHuffmanCode(bw, codes, literal_ix);
} else { } else {
int bits, n_bits; int bits, n_bits;
int code, distance; int code;
const int distance = PixOrCopyDistance(v);
VP8LPrefixEncode(v->len, &code, &n_bits, &bits); VP8LPrefixEncode(v->len, &code, &n_bits, &bits);
WriteHuffmanCode(bw, codes, 256 + code); WriteHuffmanCodeWithExtraBits(bw, codes, 256 + code, bits, n_bits);
VP8LPutBits(bw, bits, n_bits);
distance = PixOrCopyDistance(v); // Don't write the distance with the extra bits code since
// the distance can be up to 18 bits of extra bits, and the prefix
// 15 bits, totaling to 33, and our PutBits only supports up to 32 bits.
// TODO(jyrki): optimize this further.
VP8LPrefixEncode(distance, &code, &n_bits, &bits); VP8LPrefixEncode(distance, &code, &n_bits, &bits);
WriteHuffmanCode(bw, codes + 4, code); WriteHuffmanCode(bw, codes + 4, code);
VP8LPutBits(bw, bits, n_bits); VP8LPutBits(bw, bits, n_bits);