diff options
Diffstat (limited to 'drivers/webp/utils')
| -rw-r--r-- | drivers/webp/utils/bit_reader.c | 23 | ||||
| -rw-r--r-- | drivers/webp/utils/bit_reader.h | 4 | ||||
| -rw-r--r-- | drivers/webp/utils/bit_reader_inl.h | 3 | ||||
| -rw-r--r-- | drivers/webp/utils/color_cache.c | 2 | ||||
| -rw-r--r-- | drivers/webp/utils/endian_inl.h | 4 | ||||
| -rw-r--r-- | drivers/webp/utils/huffman.c | 2 | ||||
| -rw-r--r-- | drivers/webp/utils/huffman_encode.c | 2 | ||||
| -rw-r--r-- | drivers/webp/utils/quant_levels_dec.c | 33 | ||||
| -rw-r--r-- | drivers/webp/utils/quant_levels_dec.h | 4 | ||||
| -rw-r--r-- | drivers/webp/utils/utils.c | 66 | ||||
| -rw-r--r-- | drivers/webp/utils/utils.h | 42 |
11 files changed, 146 insertions, 39 deletions
diff --git a/drivers/webp/utils/bit_reader.c b/drivers/webp/utils/bit_reader.c index 4d6b4f016..13c6cf316 100644 --- a/drivers/webp/utils/bit_reader.c +++ b/drivers/webp/utils/bit_reader.c @@ -16,8 +16,7 @@ #endif #include "./bit_reader_inl.h" - -#define JAVASCRIPT_ENABLED // testing +#include "../utils/utils.h" //------------------------------------------------------------------------------ // VP8BitReader @@ -42,10 +41,9 @@ void VP8InitBitReader(VP8BitReader* const br, br->bits_ = -8; // to load the very first 8bits br->eof_ = 0; VP8BitReaderSetBuffer(br, start, size); - #ifdef JAVASCRIPT_ENABLED // html5 required aligned reads while(((uintptr_t)br->buf_ & 1) != 0 && !br->eof_) - VP8LoadFinalBytes(br); + VP8LoadFinalBytes(br); #else VP8LoadNewBytes(br); #endif @@ -127,11 +125,10 @@ int32_t VP8GetSignedValue(VP8BitReader* const br, int bits) { #define VP8L_LOG8_WBITS 4 // Number of bytes needed to store VP8L_WBITS bits. -#if !defined(WEBP_FORCE_ALIGNED) && \ - (defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \ - defined(__i386__) || defined(_M_IX86) || \ - defined(__x86_64__) || defined(_M_X64)) -#define VP8L_USE_UNALIGNED_LOAD +#if defined(__arm__) || defined(_M_ARM) || defined(__aarch64__) || \ + defined(__i386__) || defined(_M_IX86) || \ + defined(__x86_64__) || defined(_M_X64) +#define VP8L_USE_FAST_LOAD #endif static const uint32_t kBitMask[VP8L_MAX_NUM_BIT_READ + 1] = { @@ -199,15 +196,11 @@ static void ShiftBytes(VP8LBitReader* const br) { void VP8LDoFillBitWindow(VP8LBitReader* const br) { assert(br->bit_pos_ >= VP8L_WBITS); - // TODO(jzern): given the fixed read size it may be possible to force - // alignment in this block. -#if defined(VP8L_USE_UNALIGNED_LOAD) +#if defined(VP8L_USE_FAST_LOAD) if (br->pos_ + sizeof(br->val_) < br->len_) { br->val_ >>= VP8L_WBITS; br->bit_pos_ -= VP8L_WBITS; - // The expression below needs a little-endian arch to work correctly. - // This gives a large speedup for decoding speed. - br->val_ |= (vp8l_val_t)*(const uint32_t*)(br->buf_ + br->pos_) << + br->val_ |= (vp8l_val_t)HToLE32(WebPMemToUint32(br->buf_ + br->pos_)) << (VP8L_LBITS - VP8L_WBITS); br->pos_ += VP8L_LOG8_WBITS; return; diff --git a/drivers/webp/utils/bit_reader.h b/drivers/webp/utils/bit_reader.h index f0f450231..c2dcc711c 100644 --- a/drivers/webp/utils/bit_reader.h +++ b/drivers/webp/utils/bit_reader.h @@ -49,10 +49,12 @@ extern "C" { #define BITS 56 #elif defined(__arm__) || defined(_M_ARM) // ARM #define BITS 24 +#elif defined(__aarch64__) // ARM 64bit +#define BITS 56 #elif defined(__mips__) // MIPS #define BITS 24 #else // reasonable default -#define BITS 24 // TODO(skal): test aarch64 and find the proper BITS value. +#define BITS 24 #endif #endif diff --git a/drivers/webp/utils/bit_reader_inl.h b/drivers/webp/utils/bit_reader_inl.h index 20ce5f3cc..21faf14d8 100644 --- a/drivers/webp/utils/bit_reader_inl.h +++ b/drivers/webp/utils/bit_reader_inl.h @@ -55,7 +55,8 @@ void VP8LoadFinalBytes(VP8BitReader* const br); // Inlined critical functions // makes sure br->value_ has at least BITS bits worth of data -static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) { +static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE +void VP8LoadNewBytes(VP8BitReader* const br) { assert(br != NULL && br->buf_ != NULL); // Read 'BITS' bits at a time if possible. if (br->buf_ < br->buf_max_) { diff --git a/drivers/webp/utils/color_cache.c b/drivers/webp/utils/color_cache.c index f9ff4b545..c34b2e7f1 100644 --- a/drivers/webp/utils/color_cache.c +++ b/drivers/webp/utils/color_cache.c @@ -15,7 +15,7 @@ #include <stdlib.h> #include <string.h> #include "./color_cache.h" -#include "../utils/utils.h" +#include "./utils.h" //------------------------------------------------------------------------------ // VP8LColorCache. diff --git a/drivers/webp/utils/endian_inl.h b/drivers/webp/utils/endian_inl.h index 253b7be8e..e11260ff7 100644 --- a/drivers/webp/utils/endian_inl.h +++ b/drivers/webp/utils/endian_inl.h @@ -13,11 +13,11 @@ #define WEBP_UTILS_ENDIAN_INL_H_ #ifdef HAVE_CONFIG_H -#include "webp/config.h" +#include "../webp/config.h" #endif #include "../dsp/dsp.h" -#include "webp/types.h" +#include "../webp/types.h" // some endian fix (e.g.: mips-gcc doesn't define __BIG_ENDIAN__) #if !defined(WORDS_BIGENDIAN) && \ diff --git a/drivers/webp/utils/huffman.c b/drivers/webp/utils/huffman.c index e6f482a6a..7c9d83db9 100644 --- a/drivers/webp/utils/huffman.c +++ b/drivers/webp/utils/huffman.c @@ -15,8 +15,8 @@ #include <stdlib.h> #include <string.h> #include "./huffman.h" -#include "../utils/utils.h" #include "webp/format_constants.h" +#include "./utils.h" // Huffman data read via DecodeImageStream is represented in two (red and green) // bytes. diff --git a/drivers/webp/utils/huffman_encode.c b/drivers/webp/utils/huffman_encode.c index d7aad6f56..0be414a8f 100644 --- a/drivers/webp/utils/huffman_encode.c +++ b/drivers/webp/utils/huffman_encode.c @@ -15,8 +15,8 @@ #include <stdlib.h> #include <string.h> #include "./huffman_encode.h" -#include "../utils/utils.h" #include "webp/format_constants.h" +#include "./utils.h" // ----------------------------------------------------------------------------- // Util function to optimize the symbol map for RLE coding diff --git a/drivers/webp/utils/quant_levels_dec.c b/drivers/webp/utils/quant_levels_dec.c index 5b8b8b49e..ee0a3fe12 100644 --- a/drivers/webp/utils/quant_levels_dec.c +++ b/drivers/webp/utils/quant_levels_dec.c @@ -44,6 +44,7 @@ static const uint8_t kOrderedDither[DSIZE][DSIZE] = { typedef struct { int width_, height_; // dimension + int stride_; // stride in bytes int row_; // current input row being processed uint8_t* src_; // input pointer uint8_t* dst_; // output pointer @@ -99,7 +100,7 @@ static void VFilter(SmoothParams* const p) { // We replicate edges, as it's somewhat easier as a boundary condition. // That's why we don't update the 'src' pointer on top/bottom area: if (p->row_ >= 0 && p->row_ < p->height_ - 1) { - p->src_ += p->width_; + p->src_ += p->stride_; } } @@ -149,7 +150,7 @@ static void ApplyFilter(SmoothParams* const p) { #endif } } - p->dst_ += w; // advance output pointer + p->dst_ += p->stride_; // advance output pointer } //------------------------------------------------------------------------------ @@ -178,17 +179,20 @@ static void InitCorrectionLUT(int16_t* const lut, int min_dist) { lut[0] = 0; } -static void CountLevels(const uint8_t* const data, int size, - SmoothParams* const p) { - int i, last_level; +static void CountLevels(SmoothParams* const p) { + int i, j, last_level; uint8_t used_levels[256] = { 0 }; + const uint8_t* data = p->src_; p->min_ = 255; p->max_ = 0; - for (i = 0; i < size; ++i) { - const int v = data[i]; - if (v < p->min_) p->min_ = v; - if (v > p->max_) p->max_ = v; - used_levels[v] = 1; + for (j = 0; j < p->height_; ++j) { + for (i = 0; i < p->width_; ++i) { + const int v = data[i]; + if (v < p->min_) p->min_ = v; + if (v > p->max_) p->max_ = v; + used_levels[v] = 1; + } + data += p->stride_; } // Compute the mininum distance between two non-zero levels. p->min_level_dist_ = p->max_ - p->min_; @@ -208,7 +212,7 @@ static void CountLevels(const uint8_t* const data, int size, } // Initialize all params. -static int InitParams(uint8_t* const data, int width, int height, +static int InitParams(uint8_t* const data, int width, int height, int stride, int radius, SmoothParams* const p) { const int R = 2 * radius + 1; // total size of the kernel @@ -233,6 +237,7 @@ static int InitParams(uint8_t* const data, int width, int height, p->width_ = width; p->height_ = height; + p->stride_ = stride; p->src_ = data; p->dst_ = data; p->radius_ = radius; @@ -240,7 +245,7 @@ static int InitParams(uint8_t* const data, int width, int height, p->row_ = -radius; // analyze the input distribution so we can best-fit the threshold - CountLevels(data, width * height, p); + CountLevels(p); // correction table p->correction_ = ((int16_t*)mem) + LUT_SIZE; @@ -253,7 +258,7 @@ static void CleanupParams(SmoothParams* const p) { WebPSafeFree(p->mem_); } -int WebPDequantizeLevels(uint8_t* const data, int width, int height, +int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, int strength) { const int radius = 4 * strength / 100; if (strength < 0 || strength > 100) return 0; @@ -261,7 +266,7 @@ int WebPDequantizeLevels(uint8_t* const data, int width, int height, if (radius > 0) { SmoothParams p; memset(&p, 0, sizeof(p)); - if (!InitParams(data, width, height, radius, &p)) return 0; + if (!InitParams(data, width, height, stride, radius, &p)) return 0; if (p.num_levels_ > 2) { for (; p.row_ < p.height_; ++p.row_) { VFilter(&p); // accumulate average of input diff --git a/drivers/webp/utils/quant_levels_dec.h b/drivers/webp/utils/quant_levels_dec.h index 29c7e6e20..c99a47538 100644 --- a/drivers/webp/utils/quant_levels_dec.h +++ b/drivers/webp/utils/quant_levels_dec.h @@ -21,11 +21,11 @@ extern "C" { #endif // Apply post-processing to input 'data' of size 'width'x'height' assuming that -// the source was quantized to a reduced number of levels. +// the source was quantized to a reduced number of levels. 'stride' is in bytes. // Strength is in [0..100] and controls the amount of dithering applied. // Returns false in case of error (data is NULL, invalid parameters, // malloc failure, ...). -int WebPDequantizeLevels(uint8_t* const data, int width, int height, +int WebPDequantizeLevels(uint8_t* const data, int width, int height, int stride, int strength); #ifdef __cplusplus diff --git a/drivers/webp/utils/utils.c b/drivers/webp/utils/utils.c index 35aeae6ab..b2193c4b4 100644 --- a/drivers/webp/utils/utils.c +++ b/drivers/webp/utils/utils.c @@ -15,6 +15,7 @@ #include <string.h> // for memcpy() #include "webp/decode.h" #include "webp/encode.h" +#include "webp/format_constants.h" // for MAX_PALETTE_SIZE #include "./utils.h" // If PRINT_MEM_INFO is defined, extra info (like total memory used, number of @@ -237,3 +238,68 @@ void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) { } //------------------------------------------------------------------------------ + +#define MAX_COLOR_COUNT MAX_PALETTE_SIZE +#define COLOR_HASH_SIZE (MAX_COLOR_COUNT * 4) +#define COLOR_HASH_RIGHT_SHIFT 22 // 32 - log2(COLOR_HASH_SIZE). + +int WebPGetColorPalette(const WebPPicture* const pic, uint32_t* const palette) { + int i; + int x, y; + int num_colors = 0; + uint8_t in_use[COLOR_HASH_SIZE] = { 0 }; + uint32_t colors[COLOR_HASH_SIZE]; + static const uint32_t kHashMul = 0x1e35a7bdU; + const uint32_t* argb = pic->argb; + const int width = pic->width; + const int height = pic->height; + uint32_t last_pix = ~argb[0]; // so we're sure that last_pix != argb[0] + assert(pic != NULL); + assert(pic->use_argb); + + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + int key; + if (argb[x] == last_pix) { + continue; + } + last_pix = argb[x]; + key = (kHashMul * last_pix) >> COLOR_HASH_RIGHT_SHIFT; + while (1) { + if (!in_use[key]) { + colors[key] = last_pix; + in_use[key] = 1; + ++num_colors; + if (num_colors > MAX_COLOR_COUNT) { + return MAX_COLOR_COUNT + 1; // Exact count not needed. + } + break; + } else if (colors[key] == last_pix) { + break; // The color is already there. + } else { + // Some other color sits here, so do linear conflict resolution. + ++key; + key &= (COLOR_HASH_SIZE - 1); // Key mask. + } + } + } + argb += pic->argb_stride; + } + + if (palette != NULL) { // Fill the colors into palette. + num_colors = 0; + for (i = 0; i < COLOR_HASH_SIZE; ++i) { + if (in_use[i]) { + palette[num_colors] = colors[i]; + ++num_colors; + } + } + } + return num_colors; +} + +#undef MAX_COLOR_COUNT +#undef COLOR_HASH_SIZE +#undef COLOR_HASH_RIGHT_SHIFT + +//------------------------------------------------------------------------------ diff --git a/drivers/webp/utils/utils.h b/drivers/webp/utils/utils.h index d0e1cb250..cef496af7 100644 --- a/drivers/webp/utils/utils.h +++ b/drivers/webp/utils/utils.h @@ -15,8 +15,13 @@ #ifndef WEBP_UTILS_UTILS_H_ #define WEBP_UTILS_UTILS_H_ +#ifdef HAVE_CONFIG_H +#include "webp/config.h" +#endif + #include <assert.h> +#include "../dsp/dsp.h" #include "webp/types.h" #ifdef __cplusplus @@ -47,7 +52,29 @@ WEBP_EXTERN(void) WebPSafeFree(void* const ptr); // Alignment #define WEBP_ALIGN_CST 31 -#define WEBP_ALIGN(PTR) ((uintptr_t)((PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST) +#define WEBP_ALIGN(PTR) (((uintptr_t)(PTR) + WEBP_ALIGN_CST) & ~WEBP_ALIGN_CST) + +#if defined(WEBP_FORCE_ALIGNED) +#include <string.h> +// memcpy() is the safe way of moving potentially unaligned 32b memory. +static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) { + uint32_t A; + memcpy(&A, (const int*)ptr, sizeof(A)); + return A; +} +static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { + memcpy(ptr, &val, sizeof(val)); +} +#else +static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE +uint32_t WebPMemToUint32(const uint8_t* const ptr) { + return *(const uint32_t*)ptr; +} +static WEBP_UBSAN_IGNORE_UNDEF WEBP_INLINE +void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) { + *(uint32_t*)ptr = val; +} +#endif //------------------------------------------------------------------------------ // Reading/writing data. @@ -134,6 +161,19 @@ WEBP_EXTERN(void) WebPCopyPixels(const struct WebPPicture* const src, struct WebPPicture* const dst); //------------------------------------------------------------------------------ +// Unique colors. + +// Returns count of unique colors in 'pic', assuming pic->use_argb is true. +// If the unique color count is more than MAX_COLOR_COUNT, returns +// MAX_COLOR_COUNT+1. +// If 'palette' is not NULL and number of unique colors is less than or equal to +// MAX_COLOR_COUNT, also outputs the actual unique colors into 'palette'. +// Note: 'palette' is assumed to be an array already allocated with at least +// MAX_COLOR_COUNT elements. +WEBP_EXTERN(int) WebPGetColorPalette(const struct WebPPicture* const pic, + uint32_t* const palette); + +//------------------------------------------------------------------------------ #ifdef __cplusplus } // extern "C" |
