Create LUT for PrefixEncode.

This speeds up lossless compression by 5%.
Change-Id: Ifd114b1d9850dc3aac74593809e7d48529d35e3d
This commit is contained in:
Vikas Arora
2013-08-05 10:19:24 -07:00
parent 988b70844e
commit 69257f70df
6 changed files with 191 additions and 80 deletions

View File

@ -30,73 +30,6 @@ extern "C" {
#define PIX_OR_COPY_CODES_MAX \
(NUM_LITERAL_CODES + NUM_LENGTH_CODES + (1 << MAX_COLOR_CACHE_BITS))
// -----------------------------------------------------------------------------
// PrefixEncode()
// use GNU builtins where available.
#if defined(__GNUC__) && \
((__GNUC__ == 3 && __GNUC_MINOR__ >= 4) || __GNUC__ >= 4)
static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
assert(n != 0);
return 31 ^ __builtin_clz(n);
}
#elif defined(_MSC_VER) && (defined(_M_X64) || defined(_M_IX86))
#include <intrin.h>
#pragma intrinsic(_BitScanReverse)
static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
unsigned long first_set_bit;
assert(n != 0);
_BitScanReverse(&first_set_bit, n);
return first_set_bit;
}
#else
// Returns (int)floor(log2(n)). n must be > 0.
static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
int log = 0;
uint32_t value = n;
int i;
assert(n != 0);
for (i = 4; i >= 0; --i) {
const int shift = (1 << i);
const uint32_t x = value >> shift;
if (x != 0) {
value = x;
log += shift;
}
}
return log;
}
#endif
static WEBP_INLINE int VP8LBitsLog2Ceiling(uint32_t n) {
const int log_floor = BitsLog2Floor(n);
if (n == (n & ~(n - 1))) // zero or a power of two.
return log_floor;
else
return log_floor + 1;
}
// Splitting of distance and length codes into prefixes and
// extra bits. The prefixes are encoded with an entropy code
// while the extra bits are stored just as normal bits.
static WEBP_INLINE void PrefixEncode(int distance, int* const code,
int* const extra_bits_count,
int* const extra_bits_value) {
if (distance > 2) { // Collect the two most significant bits.
const int highest_bit = BitsLog2Floor(--distance);
const int second_highest_bit = (distance >> (highest_bit - 1)) & 1;
*extra_bits_count = highest_bit - 1;
*extra_bits_value = distance & ((1 << *extra_bits_count) - 1);
*code = 2 * highest_bit + second_highest_bit;
} else {
*extra_bits_count = 0;
*extra_bits_value = 0;
*code = (distance == 2) ? 1 : 0;
}
}
// -----------------------------------------------------------------------------
// PixOrCopy