summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/libwebp/src/utils
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/libwebp/src/utils')
-rw-r--r--src/3rdparty/libwebp/src/utils/bit_reader_inl_utils.h (renamed from src/3rdparty/libwebp/src/utils/bit_reader_inl.h)82
-rw-r--r--src/3rdparty/libwebp/src/utils/bit_reader_utils.c (renamed from src/3rdparty/libwebp/src/utils/bit_reader.c)20
-rw-r--r--src/3rdparty/libwebp/src/utils/bit_reader_utils.h (renamed from src/3rdparty/libwebp/src/utils/bit_reader.h)0
-rw-r--r--src/3rdparty/libwebp/src/utils/bit_writer_utils.c (renamed from src/3rdparty/libwebp/src/utils/bit_writer.c)10
-rw-r--r--src/3rdparty/libwebp/src/utils/bit_writer_utils.h (renamed from src/3rdparty/libwebp/src/utils/bit_writer.h)3
-rw-r--r--src/3rdparty/libwebp/src/utils/color_cache_utils.c (renamed from src/3rdparty/libwebp/src/utils/color_cache.c)4
-rw-r--r--src/3rdparty/libwebp/src/utils/color_cache_utils.h (renamed from src/3rdparty/libwebp/src/utils/color_cache.h)15
-rw-r--r--src/3rdparty/libwebp/src/utils/endian_inl_utils.h (renamed from src/3rdparty/libwebp/src/utils/endian_inl.h)0
-rw-r--r--src/3rdparty/libwebp/src/utils/filters_utils.c (renamed from src/3rdparty/libwebp/src/utils/filters.c)2
-rw-r--r--src/3rdparty/libwebp/src/utils/filters_utils.h (renamed from src/3rdparty/libwebp/src/utils/filters.h)0
-rw-r--r--src/3rdparty/libwebp/src/utils/huffman_encode_utils.c (renamed from src/3rdparty/libwebp/src/utils/huffman_encode.c)4
-rw-r--r--src/3rdparty/libwebp/src/utils/huffman_encode_utils.h (renamed from src/3rdparty/libwebp/src/utils/huffman_encode.h)0
-rw-r--r--src/3rdparty/libwebp/src/utils/huffman_utils.c (renamed from src/3rdparty/libwebp/src/utils/huffman.c)50
-rw-r--r--src/3rdparty/libwebp/src/utils/huffman_utils.h (renamed from src/3rdparty/libwebp/src/utils/huffman.h)0
-rw-r--r--src/3rdparty/libwebp/src/utils/quant_levels_dec_utils.c (renamed from src/3rdparty/libwebp/src/utils/quant_levels_dec.c)35
-rw-r--r--src/3rdparty/libwebp/src/utils/quant_levels_dec_utils.h (renamed from src/3rdparty/libwebp/src/utils/quant_levels_dec.h)4
-rw-r--r--src/3rdparty/libwebp/src/utils/quant_levels_utils.c (renamed from src/3rdparty/libwebp/src/utils/quant_levels.c)2
-rw-r--r--src/3rdparty/libwebp/src/utils/quant_levels_utils.h (renamed from src/3rdparty/libwebp/src/utils/quant_levels.h)0
-rw-r--r--src/3rdparty/libwebp/src/utils/random_utils.c (renamed from src/3rdparty/libwebp/src/utils/random.c)2
-rw-r--r--src/3rdparty/libwebp/src/utils/random_utils.h (renamed from src/3rdparty/libwebp/src/utils/random.h)0
-rw-r--r--src/3rdparty/libwebp/src/utils/rescaler_utils.c (renamed from src/3rdparty/libwebp/src/utils/rescaler.c)10
-rw-r--r--src/3rdparty/libwebp/src/utils/rescaler_utils.h (renamed from src/3rdparty/libwebp/src/utils/rescaler.h)0
-rw-r--r--src/3rdparty/libwebp/src/utils/thread_utils.c (renamed from src/3rdparty/libwebp/src/utils/thread.c)8
-rw-r--r--src/3rdparty/libwebp/src/utils/thread_utils.h (renamed from src/3rdparty/libwebp/src/utils/thread.h)0
-rw-r--r--src/3rdparty/libwebp/src/utils/utils.c97
-rw-r--r--src/3rdparty/libwebp/src/utils/utils.h66
26 files changed, 281 insertions, 133 deletions
diff --git a/src/3rdparty/libwebp/src/utils/bit_reader_inl.h b/src/3rdparty/libwebp/src/utils/bit_reader_inl_utils.h
index 3721570..fd7fb04 100644
--- a/src/3rdparty/libwebp/src/utils/bit_reader_inl.h
+++ b/src/3rdparty/libwebp/src/utils/bit_reader_inl_utils.h
@@ -20,13 +20,12 @@
#include "../webp/config.h"
#endif
-#ifdef WEBP_FORCE_ALIGNED
-#include <string.h> // memcpy
-#endif
+#include <string.h> // for memcpy
#include "../dsp/dsp.h"
-#include "./bit_reader.h"
-#include "./endian_inl.h"
+#include "./bit_reader_utils.h"
+#include "./endian_inl_utils.h"
+#include "./utils.h"
#ifdef __cplusplus
extern "C" {
@@ -55,16 +54,14 @@ 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_) {
// convert memory type to register type (with some zero'ing!)
bit_t bits;
-#if defined(WEBP_FORCE_ALIGNED)
- lbit_t in_bits;
- memcpy(&in_bits, br->buf_, sizeof(in_bits));
-#elif defined(WEBP_USE_MIPS32)
+#if defined(WEBP_USE_MIPS32)
// This is needed because of un-aligned read.
lbit_t in_bits;
lbit_t* p_buf_ = (lbit_t*)br->buf_;
@@ -79,7 +76,8 @@ static WEBP_INLINE void VP8LoadNewBytes(VP8BitReader* const br) {
: "memory", "at"
);
#else
- const lbit_t in_bits = *(const lbit_t*)br->buf_;
+ lbit_t in_bits;
+ memcpy(&in_bits, br->buf_, sizeof(in_bits));
#endif
br->buf_ += BITS >> 3;
#if !defined(WORDS_BIGENDIAN)
@@ -118,37 +116,26 @@ static WEBP_INLINE int VP8GetBit(VP8BitReader* const br, int prob) {
const int pos = br->bits_;
const range_t split = (range * prob) >> 8;
const range_t value = (range_t)(br->value_ >> pos);
-#if defined(__arm__) || defined(_M_ARM) // ARM-specific
- const int bit = ((int)(split - value) >> 31) & 1;
- if (value > split) {
- range -= split + 1;
- br->value_ -= (bit_t)(split + 1) << pos;
- } else {
- range = split;
- }
-#else // faster version on x86
- int bit; // Don't use 'const int bit = (value > split);", it's slower.
- if (value > split) {
- range -= split + 1;
+ const int bit = (value > split);
+ if (bit) {
+ range -= split;
br->value_ -= (bit_t)(split + 1) << pos;
- bit = 1;
} else {
- range = split;
- bit = 0;
+ range = split + 1;
}
-#endif
- if (range <= (range_t)0x7e) {
- const int shift = kVP8Log2Range[range];
- range = kVP8NewRange[range];
+ {
+ const int shift = 7 ^ BitsLog2Floor(range);
+ range <<= shift;
br->bits_ -= shift;
}
- br->range_ = range;
+ br->range_ = range - 1;
return bit;
}
}
// simplified version of VP8GetBit() for prob=0x80 (note shift is always 1 here)
-static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) {
+static WEBP_UBSAN_IGNORE_UNSIGNED_OVERFLOW WEBP_INLINE
+int VP8GetSigned(VP8BitReader* const br, int v) {
if (br->bits_ < 0) {
VP8LoadNewBytes(br);
}
@@ -165,6 +152,37 @@ static WEBP_INLINE int VP8GetSigned(VP8BitReader* const br, int v) {
}
}
+static WEBP_INLINE int VP8GetBitAlt(VP8BitReader* const br, int prob) {
+ // Don't move this declaration! It makes a big speed difference to store
+ // 'range' *before* calling VP8LoadNewBytes(), even if this function doesn't
+ // alter br->range_ value.
+ range_t range = br->range_;
+ if (br->bits_ < 0) {
+ VP8LoadNewBytes(br);
+ }
+ {
+ const int pos = br->bits_;
+ const range_t split = (range * prob) >> 8;
+ const range_t value = (range_t)(br->value_ >> pos);
+ int bit; // Don't use 'const int bit = (value > split);", it's slower.
+ if (value > split) {
+ range -= split + 1;
+ br->value_ -= (bit_t)(split + 1) << pos;
+ bit = 1;
+ } else {
+ range = split;
+ bit = 0;
+ }
+ if (range <= (range_t)0x7e) {
+ const int shift = kVP8Log2Range[range];
+ range = kVP8NewRange[range];
+ br->bits_ -= shift;
+ }
+ br->range_ = range;
+ return bit;
+ }
+}
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/src/3rdparty/libwebp/src/utils/bit_reader.c b/src/3rdparty/libwebp/src/utils/bit_reader_utils.c
index 45198e1..c3157e8 100644
--- a/src/3rdparty/libwebp/src/utils/bit_reader.c
+++ b/src/3rdparty/libwebp/src/utils/bit_reader_utils.c
@@ -15,7 +15,8 @@
#include "../webp/config.h"
#endif
-#include "./bit_reader_inl.h"
+#include "./bit_reader_inl_utils.h"
+#include "../utils/utils.h"
//------------------------------------------------------------------------------
// VP8BitReader
@@ -119,11 +120,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] = {
@@ -191,15 +191,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)WebPMemToUint32(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/src/3rdparty/libwebp/src/utils/bit_reader.h b/src/3rdparty/libwebp/src/utils/bit_reader_utils.h
index ec3426c..ec3426c 100644
--- a/src/3rdparty/libwebp/src/utils/bit_reader.h
+++ b/src/3rdparty/libwebp/src/utils/bit_reader_utils.h
diff --git a/src/3rdparty/libwebp/src/utils/bit_writer.c b/src/3rdparty/libwebp/src/utils/bit_writer_utils.c
index 0644286..ab0c49d 100644
--- a/src/3rdparty/libwebp/src/utils/bit_writer.c
+++ b/src/3rdparty/libwebp/src/utils/bit_writer_utils.c
@@ -16,8 +16,8 @@
#include <string.h> // for memcpy()
#include <stdlib.h>
-#include "./bit_writer.h"
-#include "./endian_inl.h"
+#include "./bit_writer_utils.h"
+#include "./endian_inl_utils.h"
#include "./utils.h"
//------------------------------------------------------------------------------
@@ -143,13 +143,13 @@ int VP8PutBitUniform(VP8BitWriter* const bw, int bit) {
void VP8PutBits(VP8BitWriter* const bw, uint32_t value, int nb_bits) {
uint32_t mask;
assert(nb_bits > 0 && nb_bits < 32);
- for (mask = 1u << (nb_bits - 1); mask; mask >>= 1)
+ for (mask = 1u << (nb_bits - 1); mask; mask >>= 1) {
VP8PutBitUniform(bw, value & mask);
+ }
}
void VP8PutSignedBits(VP8BitWriter* const bw, int value, int nb_bits) {
- if (!VP8PutBitUniform(bw, value != 0))
- return;
+ if (!VP8PutBitUniform(bw, value != 0)) return;
if (value < 0) {
VP8PutBits(bw, ((-value) << 1) | 1, nb_bits + 1);
} else {
diff --git a/src/3rdparty/libwebp/src/utils/bit_writer.h b/src/3rdparty/libwebp/src/utils/bit_writer_utils.h
index ef360d1..9c02bbc 100644
--- a/src/3rdparty/libwebp/src/utils/bit_writer.h
+++ b/src/3rdparty/libwebp/src/utils/bit_writer_utils.h
@@ -54,7 +54,8 @@ int VP8BitWriterAppend(VP8BitWriter* const bw,
// return approximate write position (in bits)
static WEBP_INLINE uint64_t VP8BitWriterPos(const VP8BitWriter* const bw) {
- return (uint64_t)(bw->pos_ + bw->run_) * 8 + 8 + bw->nb_bits_;
+ const uint64_t nb_bits = 8 + bw->nb_bits_; // bw->nb_bits_ is <= 0, note
+ return (bw->pos_ + bw->run_) * 8 + nb_bits;
}
// Returns a pointer to the internal buffer.
diff --git a/src/3rdparty/libwebp/src/utils/color_cache.c b/src/3rdparty/libwebp/src/utils/color_cache_utils.c
index f9ff4b5..0172590 100644
--- a/src/3rdparty/libwebp/src/utils/color_cache.c
+++ b/src/3rdparty/libwebp/src/utils/color_cache_utils.c
@@ -14,8 +14,8 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
-#include "./color_cache.h"
-#include "../utils/utils.h"
+#include "./color_cache_utils.h"
+#include "./utils.h"
//------------------------------------------------------------------------------
// VP8LColorCache.
diff --git a/src/3rdparty/libwebp/src/utils/color_cache.h b/src/3rdparty/libwebp/src/utils/color_cache_utils.h
index a9a9f64..c373e6b 100644
--- a/src/3rdparty/libwebp/src/utils/color_cache.h
+++ b/src/3rdparty/libwebp/src/utils/color_cache_utils.h
@@ -28,7 +28,11 @@ typedef struct {
int hash_bits_;
} VP8LColorCache;
-static const uint32_t kHashMul = 0x1e35a7bd;
+static const uint64_t kHashMul = 0x1e35a7bdull;
+
+static WEBP_INLINE int HashPix(uint32_t argb, int shift) {
+ return (int)(((argb * kHashMul) & 0xffffffffu) >> shift);
+}
static WEBP_INLINE uint32_t VP8LColorCacheLookup(
const VP8LColorCache* const cc, uint32_t key) {
@@ -44,19 +48,20 @@ static WEBP_INLINE void VP8LColorCacheSet(const VP8LColorCache* const cc,
static WEBP_INLINE void VP8LColorCacheInsert(const VP8LColorCache* const cc,
uint32_t argb) {
- const uint32_t key = (kHashMul * argb) >> cc->hash_shift_;
+ const int key = HashPix(argb, cc->hash_shift_);
cc->colors_[key] = argb;
}
static WEBP_INLINE int VP8LColorCacheGetIndex(const VP8LColorCache* const cc,
uint32_t argb) {
- return (kHashMul * argb) >> cc->hash_shift_;
+ return HashPix(argb, cc->hash_shift_);
}
+// Return the key if cc contains argb, and -1 otherwise.
static WEBP_INLINE int VP8LColorCacheContains(const VP8LColorCache* const cc,
uint32_t argb) {
- const uint32_t key = (kHashMul * argb) >> cc->hash_shift_;
- return (cc->colors_[key] == argb);
+ const int key = HashPix(argb, cc->hash_shift_);
+ return (cc->colors_[key] == argb) ? key : -1;
}
//------------------------------------------------------------------------------
diff --git a/src/3rdparty/libwebp/src/utils/endian_inl.h b/src/3rdparty/libwebp/src/utils/endian_inl_utils.h
index e11260f..e11260f 100644
--- a/src/3rdparty/libwebp/src/utils/endian_inl.h
+++ b/src/3rdparty/libwebp/src/utils/endian_inl_utils.h
diff --git a/src/3rdparty/libwebp/src/utils/filters.c b/src/3rdparty/libwebp/src/utils/filters_utils.c
index 15543b1..49c1d18 100644
--- a/src/3rdparty/libwebp/src/utils/filters.c
+++ b/src/3rdparty/libwebp/src/utils/filters_utils.c
@@ -11,7 +11,7 @@
//
// Author: Urvang (urvang@google.com)
-#include "./filters.h"
+#include "./filters_utils.h"
#include <stdlib.h>
#include <string.h>
diff --git a/src/3rdparty/libwebp/src/utils/filters.h b/src/3rdparty/libwebp/src/utils/filters_utils.h
index 088b132..088b132 100644
--- a/src/3rdparty/libwebp/src/utils/filters.h
+++ b/src/3rdparty/libwebp/src/utils/filters_utils.h
diff --git a/src/3rdparty/libwebp/src/utils/huffman_encode.c b/src/3rdparty/libwebp/src/utils/huffman_encode_utils.c
index 6421c2b..f950465 100644
--- a/src/3rdparty/libwebp/src/utils/huffman_encode.c
+++ b/src/3rdparty/libwebp/src/utils/huffman_encode_utils.c
@@ -14,8 +14,8 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
-#include "./huffman_encode.h"
-#include "../utils/utils.h"
+#include "./huffman_encode_utils.h"
+#include "./utils.h"
#include "../webp/format_constants.h"
// -----------------------------------------------------------------------------
diff --git a/src/3rdparty/libwebp/src/utils/huffman_encode.h b/src/3rdparty/libwebp/src/utils/huffman_encode_utils.h
index a157165..a157165 100644
--- a/src/3rdparty/libwebp/src/utils/huffman_encode.h
+++ b/src/3rdparty/libwebp/src/utils/huffman_encode_utils.h
diff --git a/src/3rdparty/libwebp/src/utils/huffman.c b/src/3rdparty/libwebp/src/utils/huffman_utils.c
index d57376a..008b5d7 100644
--- a/src/3rdparty/libwebp/src/utils/huffman.c
+++ b/src/3rdparty/libwebp/src/utils/huffman_utils.c
@@ -14,8 +14,8 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
-#include "./huffman.h"
-#include "../utils/utils.h"
+#include "./huffman_utils.h"
+#include "./utils.h"
#include "../webp/format_constants.h"
// Huffman data read via DecodeImageStream is represented in two (red and green)
@@ -45,7 +45,7 @@ static WEBP_INLINE uint32_t GetNextKey(uint32_t key, int len) {
while (key & step) {
step >>= 1;
}
- return (key & (step - 1)) + step;
+ return step ? (key & (step - 1)) + step : key;
}
// Stores code in table[0], table[step], table[2*step], ..., table[end].
@@ -75,11 +75,13 @@ static WEBP_INLINE int NextTableBitSize(const int* const count,
return len - root_bits;
}
-int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
- const int code_lengths[], int code_lengths_size) {
+// sorted[code_lengths_size] is a pre-allocated array for sorting symbols
+// by code length.
+static int BuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
+ const int code_lengths[], int code_lengths_size,
+ uint16_t sorted[]) {
HuffmanCode* table = root_table; // next available space in table
int total_size = 1 << root_bits; // total size root table + 2nd level table
- int* sorted = NULL; // symbols sorted by code length
int len; // current code length
int symbol; // symbol index in original or sorted table
// number of codes of each length:
@@ -114,11 +116,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
offset[len + 1] = offset[len] + count[len];
}
- sorted = (int*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
- if (sorted == NULL) {
- return 0;
- }
-
// Sort symbols by length, by symbol order within each length.
for (symbol = 0; symbol < code_lengths_size; ++symbol) {
const int symbol_code_length = code_lengths[symbol];
@@ -133,7 +130,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
code.bits = 0;
code.value = (uint16_t)sorted[0];
ReplicateValue(table, 1, total_size, code);
- WebPSafeFree(sorted);
return total_size;
}
@@ -153,7 +149,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
num_nodes += num_open;
num_open -= count[len];
if (num_open < 0) {
- WebPSafeFree(sorted);
return 0;
}
for (; count[len] > 0; --count[len]) {
@@ -172,7 +167,6 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
num_nodes += num_open;
num_open -= count[len];
if (num_open < 0) {
- WebPSafeFree(sorted);
return 0;
}
for (; count[len] > 0; --count[len]) {
@@ -195,11 +189,35 @@ int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
// Check if tree is full.
if (num_nodes != 2 * offset[MAX_ALLOWED_CODE_LENGTH] - 1) {
- WebPSafeFree(sorted);
return 0;
}
}
- WebPSafeFree(sorted);
+ return total_size;
+}
+
+// Maximum code_lengths_size is 2328 (reached for 11-bit color_cache_bits).
+// More commonly, the value is around ~280.
+#define MAX_CODE_LENGTHS_SIZE \
+ ((1 << MAX_CACHE_BITS) + NUM_LITERAL_CODES + NUM_LENGTH_CODES)
+// Cut-off value for switching between heap and stack allocation.
+#define SORTED_SIZE_CUTOFF 512
+int VP8LBuildHuffmanTable(HuffmanCode* const root_table, int root_bits,
+ const int code_lengths[], int code_lengths_size) {
+ int total_size;
+ assert(code_lengths_size <= MAX_CODE_LENGTHS_SIZE);
+ if (code_lengths_size <= SORTED_SIZE_CUTOFF) {
+ // use local stack-allocated array.
+ uint16_t sorted[SORTED_SIZE_CUTOFF];
+ total_size = BuildHuffmanTable(root_table, root_bits,
+ code_lengths, code_lengths_size, sorted);
+ } else { // rare case. Use heap allocation.
+ uint16_t* const sorted =
+ (uint16_t*)WebPSafeMalloc(code_lengths_size, sizeof(*sorted));
+ if (sorted == NULL) return 0;
+ total_size = BuildHuffmanTable(root_table, root_bits,
+ code_lengths, code_lengths_size, sorted);
+ WebPSafeFree(sorted);
+ }
return total_size;
}
diff --git a/src/3rdparty/libwebp/src/utils/huffman.h b/src/3rdparty/libwebp/src/utils/huffman_utils.h
index c6dd6aa..c6dd6aa 100644
--- a/src/3rdparty/libwebp/src/utils/huffman.h
+++ b/src/3rdparty/libwebp/src/utils/huffman_utils.h
diff --git a/src/3rdparty/libwebp/src/utils/quant_levels_dec.c b/src/3rdparty/libwebp/src/utils/quant_levels_dec_utils.c
index 5b8b8b4..d4d23d3 100644
--- a/src/3rdparty/libwebp/src/utils/quant_levels_dec.c
+++ b/src/3rdparty/libwebp/src/utils/quant_levels_dec_utils.c
@@ -14,7 +14,7 @@
//
// Author: Skal (pascal.massimino@gmail.com)
-#include "./quant_levels_dec.h"
+#include "./quant_levels_dec_utils.h"
#include <string.h> // for memset
@@ -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/src/3rdparty/libwebp/src/utils/quant_levels_dec.h b/src/3rdparty/libwebp/src/utils/quant_levels_dec_utils.h
index 9aab068..59a1349 100644
--- a/src/3rdparty/libwebp/src/utils/quant_levels_dec.h
+++ b/src/3rdparty/libwebp/src/utils/quant_levels_dec_utils.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/src/3rdparty/libwebp/src/utils/quant_levels.c b/src/3rdparty/libwebp/src/utils/quant_levels_utils.c
index d7c8aab..73174e8 100644
--- a/src/3rdparty/libwebp/src/utils/quant_levels.c
+++ b/src/3rdparty/libwebp/src/utils/quant_levels_utils.c
@@ -14,7 +14,7 @@
#include <assert.h>
-#include "./quant_levels.h"
+#include "./quant_levels_utils.h"
#define NUM_SYMBOLS 256
diff --git a/src/3rdparty/libwebp/src/utils/quant_levels.h b/src/3rdparty/libwebp/src/utils/quant_levels_utils.h
index 1cb5a32..1cb5a32 100644
--- a/src/3rdparty/libwebp/src/utils/quant_levels.h
+++ b/src/3rdparty/libwebp/src/utils/quant_levels_utils.h
diff --git a/src/3rdparty/libwebp/src/utils/random.c b/src/3rdparty/libwebp/src/utils/random_utils.c
index 24e96ad..9f1e415 100644
--- a/src/3rdparty/libwebp/src/utils/random.c
+++ b/src/3rdparty/libwebp/src/utils/random_utils.c
@@ -12,7 +12,7 @@
// Author: Skal (pascal.massimino@gmail.com)
#include <string.h>
-#include "./random.h"
+#include "./random_utils.h"
//------------------------------------------------------------------------------
diff --git a/src/3rdparty/libwebp/src/utils/random.h b/src/3rdparty/libwebp/src/utils/random_utils.h
index c392a61..c392a61 100644
--- a/src/3rdparty/libwebp/src/utils/random.h
+++ b/src/3rdparty/libwebp/src/utils/random_utils.h
diff --git a/src/3rdparty/libwebp/src/utils/rescaler.c b/src/3rdparty/libwebp/src/utils/rescaler_utils.c
index 00c9300..0d1f80d 100644
--- a/src/3rdparty/libwebp/src/utils/rescaler.c
+++ b/src/3rdparty/libwebp/src/utils/rescaler_utils.c
@@ -15,7 +15,7 @@
#include <stdlib.h>
#include <string.h>
#include "../dsp/dsp.h"
-#include "./rescaler.h"
+#include "./rescaler_utils.h"
//------------------------------------------------------------------------------
@@ -48,11 +48,15 @@ void WebPRescalerInit(WebPRescaler* const wrk, int src_width, int src_height,
wrk->y_sub = wrk->y_expand ? y_sub - 1 : y_sub;
wrk->y_accum = wrk->y_expand ? wrk->y_sub : wrk->y_add;
if (!wrk->y_expand) {
- // this is WEBP_RESCALER_FRAC(dst_height, x_add * y_add) without the cast.
+ // This is WEBP_RESCALER_FRAC(dst_height, x_add * y_add) without the cast.
+ // Its value is <= WEBP_RESCALER_ONE, because dst_height <= wrk->y_add, and
+ // wrk->x_add >= 1;
const uint64_t ratio =
(uint64_t)dst_height * WEBP_RESCALER_ONE / (wrk->x_add * wrk->y_add);
if (ratio != (uint32_t)ratio) {
- // We can't represent the ratio with the current fixed-point precision.
+ // When ratio == WEBP_RESCALER_ONE, we can't represent the ratio with the
+ // current fixed-point precision. This happens when src_height ==
+ // wrk->y_add (which == src_height), and wrk->x_add == 1.
// => We special-case fxy_scale = 0, in WebPRescalerExportRow().
wrk->fxy_scale = 0;
} else {
diff --git a/src/3rdparty/libwebp/src/utils/rescaler.h b/src/3rdparty/libwebp/src/utils/rescaler_utils.h
index 98b01a7..98b01a7 100644
--- a/src/3rdparty/libwebp/src/utils/rescaler.h
+++ b/src/3rdparty/libwebp/src/utils/rescaler_utils.h
diff --git a/src/3rdparty/libwebp/src/utils/thread.c b/src/3rdparty/libwebp/src/utils/thread_utils.c
index 93f7622..1729060 100644
--- a/src/3rdparty/libwebp/src/utils/thread.c
+++ b/src/3rdparty/libwebp/src/utils/thread_utils.c
@@ -13,7 +13,7 @@
#include <assert.h>
#include <string.h> // for memset()
-#include "./thread.h"
+#include "./thread_utils.h"
#include "./utils.h"
#ifdef WEBP_USE_THREAD
@@ -183,8 +183,7 @@ static int pthread_cond_wait(pthread_cond_t* const condition,
#else
// note that there is a consumer available so the signal isn't dropped in
// pthread_cond_signal
- if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL))
- return 1;
+ if (!ReleaseSemaphore(condition->waiting_sem_, 1, NULL)) return 1;
// now unlock the mutex so pthread_cond_signal may be issued
pthread_mutex_unlock(mutex);
ok = (WaitForSingleObject(condition->signal_event_, INFINITE) ==
@@ -226,8 +225,7 @@ static THREADFN ThreadLoop(void* ptr) {
}
// main thread state control
-static void ChangeState(WebPWorker* const worker,
- WebPWorkerStatus new_status) {
+static void ChangeState(WebPWorker* const worker, WebPWorkerStatus new_status) {
// No-op when attempting to change state on a thread that didn't come up.
// Checking status_ without acquiring the lock first would result in a data
// race.
diff --git a/src/3rdparty/libwebp/src/utils/thread.h b/src/3rdparty/libwebp/src/utils/thread_utils.h
index 8408311..8408311 100644
--- a/src/3rdparty/libwebp/src/utils/thread.h
+++ b/src/3rdparty/libwebp/src/utils/thread_utils.h
diff --git a/src/3rdparty/libwebp/src/utils/utils.c b/src/3rdparty/libwebp/src/utils/utils.c
index d8e3093..504d924 100644
--- a/src/3rdparty/libwebp/src/utils/utils.c
+++ b/src/3rdparty/libwebp/src/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
@@ -24,7 +25,7 @@
// http://valgrind.org/docs/manual/ms-manual.html
// Here is an example command line:
/* valgrind --tool=massif --massif-out-file=massif.out \
- --stacks=yes --alloc-fn=WebPSafeAlloc --alloc-fn=WebPSafeCalloc
+ --stacks=yes --alloc-fn=WebPSafeMalloc --alloc-fn=WebPSafeCalloc
ms_print massif.out
*/
// In addition:
@@ -174,8 +175,12 @@ static int CheckSizeArgumentsOverflow(uint64_t nmemb, size_t size) {
}
#endif
#if defined(MALLOC_LIMIT)
- if (mem_limit > 0 && total_mem + total_size >= mem_limit) {
- return 0; // fake fail!
+ if (mem_limit > 0) {
+ const uint64_t new_total_mem = (uint64_t)total_mem + total_size;
+ if (new_total_mem != (size_t)new_total_mem ||
+ new_total_mem > mem_limit) {
+ return 0; // fake fail!
+ }
}
#endif
@@ -237,3 +242,89 @@ void WebPCopyPixels(const WebPPicture* const src, WebPPicture* const dst) {
}
//------------------------------------------------------------------------------
+
+#define COLOR_HASH_SIZE (MAX_PALETTE_SIZE * 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 uint64_t kHashMul = 0x1e35a7bdull;
+ 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 = ((last_pix * kHashMul) & 0xffffffffu) >> COLOR_HASH_RIGHT_SHIFT;
+ while (1) {
+ if (!in_use[key]) {
+ colors[key] = last_pix;
+ in_use[key] = 1;
+ ++num_colors;
+ if (num_colors > MAX_PALETTE_SIZE) {
+ return MAX_PALETTE_SIZE + 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 COLOR_HASH_SIZE
+#undef COLOR_HASH_RIGHT_SHIFT
+
+//------------------------------------------------------------------------------
+
+#if defined(WEBP_NEED_LOG_TABLE_8BIT)
+const uint8_t WebPLogTable8bit[256] = { // 31 ^ clz(i)
+ 0, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
+ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7
+};
+#endif
+
+//------------------------------------------------------------------------------
diff --git a/src/3rdparty/libwebp/src/utils/utils.h b/src/3rdparty/libwebp/src/utils/utils.h
index f506d66..3ab4590 100644
--- a/src/3rdparty/libwebp/src/utils/utils.h
+++ b/src/3rdparty/libwebp/src/utils/utils.h
@@ -20,7 +20,9 @@
#endif
#include <assert.h>
+#include <limits.h>
+#include "../dsp/dsp.h"
#include "../webp/types.h"
#ifdef __cplusplus
@@ -31,7 +33,14 @@ extern "C" {
// Memory allocation
// This is the maximum memory amount that libwebp will ever try to allocate.
-#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 40)
+#ifndef WEBP_MAX_ALLOCABLE_MEMORY
+#if SIZE_MAX > (1ULL << 34)
+#define WEBP_MAX_ALLOCABLE_MEMORY (1ULL << 34)
+#else
+// For 32-bit targets keep this below INT_MAX to avoid valgrind warnings.
+#define WEBP_MAX_ALLOCABLE_MEMORY ((1ULL << 31) - (1 << 16))
+#endif
+#endif // WEBP_MAX_ALLOCABLE_MEMORY
// size-checking safe malloc/calloc: verify that the requested size is not too
// large, or return NULL. You don't need to call these for constructs like
@@ -51,9 +60,8 @@ 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) {
@@ -64,14 +72,6 @@ static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) {
static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) {
memcpy(ptr, &val, sizeof(val));
}
-#else
-static WEBP_INLINE uint32_t WebPMemToUint32(const uint8_t* const ptr) {
- return *(const uint32_t*)ptr;
-}
-static WEBP_INLINE void WebPUint32ToMem(uint8_t* const ptr, uint32_t val) {
- *(uint32_t*)ptr = val;
-}
-#endif
//------------------------------------------------------------------------------
// Reading/writing data.
@@ -107,6 +107,19 @@ static WEBP_INLINE void PutLE32(uint8_t* const data, uint32_t val) {
PutLE16(data + 2, (int)(val >> 16));
}
+// Returns 31 ^ clz(n) = log2(n). This is the default C-implementation, either
+// based on table or not. Can be used as fallback if clz() is not available.
+#define WEBP_NEED_LOG_TABLE_8BIT
+extern const uint8_t WebPLogTable8bit[256];
+static WEBP_INLINE int WebPLog2FloorC(uint32_t n) {
+ int log = 0;
+ while (n >= 256) {
+ log += 8;
+ n >>= 8;
+ }
+ return log + WebPLogTable8bit[n];
+}
+
// Returns (int)floor(log2(n)). n must be > 0.
// use GNU builtins where available.
#if defined(__GNUC__) && \
@@ -124,22 +137,8 @@ static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
_BitScanReverse(&first_set_bit, n);
return first_set_bit;
}
-#else
-static WEBP_INLINE int BitsLog2Floor(uint32_t n) {
- int log = 0;
- uint32_t value = n;
- int i;
-
- 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;
-}
+#else // default: use the C-version.
+static WEBP_INLINE int BitsLog2Floor(uint32_t n) { return WebPLog2FloorC(n); }
#endif
//------------------------------------------------------------------------------
@@ -158,6 +157,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_PALETTE_SIZE, returns
+// MAX_PALETTE_SIZE+1.
+// If 'palette' is not NULL and number of unique colors is less than or equal to
+// MAX_PALETTE_SIZE, also outputs the actual unique colors into 'palette'.
+// Note: 'palette' is assumed to be an array already allocated with at least
+// MAX_PALETTE_SIZE elements.
+WEBP_EXTERN(int) WebPGetColorPalette(const struct WebPPicture* const pic,
+ uint32_t* const palette);
+
+//------------------------------------------------------------------------------
#ifdef __cplusplus
} // extern "C"