summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/libwebp/src/enc/near_lossless.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/libwebp/src/enc/near_lossless.c')
-rw-r--r--src/3rdparty/libwebp/src/enc/near_lossless.c56
1 files changed, 9 insertions, 47 deletions
diff --git a/src/3rdparty/libwebp/src/enc/near_lossless.c b/src/3rdparty/libwebp/src/enc/near_lossless.c
index 9bc0f0e..f4ab91f 100644
--- a/src/3rdparty/libwebp/src/enc/near_lossless.c
+++ b/src/3rdparty/libwebp/src/enc/near_lossless.c
@@ -14,6 +14,7 @@
// Author: Jyrki Alakuijala (jyrki@google.com)
// Converted to C by Aleksander Kramarz (akramarz@google.com)
+#include <assert.h>
#include <stdlib.h>
#include "../dsp/lossless.h"
@@ -23,42 +24,14 @@
#define MIN_DIM_FOR_NEAR_LOSSLESS 64
#define MAX_LIMIT_BITS 5
-// Computes quantized pixel value and distance from original value.
-static void GetValAndDistance(int a, int initial, int bits,
- int* const val, int* const distance) {
- const int mask = ~((1 << bits) - 1);
- *val = (initial & mask) | (initial >> (8 - bits));
- *distance = 2 * abs(a - *val);
-}
-
-// Clamps the value to range [0, 255].
-static int Clamp8b(int val) {
- const int min_val = 0;
- const int max_val = 0xff;
- return (val < min_val) ? min_val : (val > max_val) ? max_val : val;
-}
-
-// Quantizes values {a, a+(1<<bits), a-(1<<bits)} and returns the nearest one.
+// Quantizes the value up or down to a multiple of 1<<bits (or to 255),
+// choosing the closer one, resolving ties using bankers' rounding.
static int FindClosestDiscretized(int a, int bits) {
- int best_val = a, i;
- int min_distance = 256;
-
- for (i = -1; i <= 1; ++i) {
- int candidate, distance;
- const int val = Clamp8b(a + i * (1 << bits));
- GetValAndDistance(a, val, bits, &candidate, &distance);
- if (i != 0) {
- ++distance;
- }
- // Smallest distance but favor i == 0 over i == -1 and i == 1
- // since that keeps the overall intensity more constant in the
- // images.
- if (distance < min_distance) {
- min_distance = distance;
- best_val = candidate;
- }
- }
- return best_val;
+ const int mask = (1 << bits) - 1;
+ const int biased = a + (mask >> 1) + ((a >> bits) & 1);
+ assert(bits > 0);
+ if (biased > 0xff) return 0xff;
+ return biased & ~mask;
}
// Applies FindClosestDiscretized to all channels of pixel.
@@ -124,22 +97,11 @@ static void NearLossless(int xsize, int ysize, uint32_t* argb,
}
}
-static int QualityToLimitBits(int quality) {
- // quality mapping:
- // 0..19 -> 5
- // 0..39 -> 4
- // 0..59 -> 3
- // 0..79 -> 2
- // 0..99 -> 1
- // 100 -> 0
- return MAX_LIMIT_BITS - quality / 20;
-}
-
int VP8ApplyNearLossless(int xsize, int ysize, uint32_t* argb, int quality) {
int i;
uint32_t* const copy_buffer =
(uint32_t*)WebPSafeMalloc(xsize * 3, sizeof(*copy_buffer));
- const int limit_bits = QualityToLimitBits(quality);
+ const int limit_bits = VP8LNearLosslessBits(quality);
assert(argb != NULL);
assert(limit_bits >= 0);
assert(limit_bits <= MAX_LIMIT_BITS);