fix a descaling bug for vertical/horizontal U/V interpolation

RGBToU/V calls expects two extra precision bits, they were only
given one by SUM2H and SUM2H macros.

For rounding coherency, also changed SUM1 macro.

Change-Id: I05f96a46f5d4f17b830d0420eaf79b066cdf78d4
This commit is contained in:
skal 2013-11-19 11:21:10 +01:00
parent bcb3955c41
commit cb261f790f

View File

@ -643,12 +643,15 @@ static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) {
return kGammaToLinearTab[v]; return kGammaToLinearTab[v];
} }
static WEBP_INLINE int LinearToGamma(uint32_t v, int shift) { // Convert a linear value 'v' to YUV_FIX+2 fixed-point precision
const int tab_pos = v >> (kGammaTabFix + shift); // integer part // U/V value, suitable for RGBToU/V calls.
const int x = v & ((kGammaTabScale << shift) - 1); // fractional part static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) {
const int v = base_value << shift; // final uplifted value
const int tab_pos = v >> (kGammaTabFix + 2); // integer part
const int x = v & ((kGammaTabScale << 2) - 1); // fractional part
const int v0 = kLinearToGammaTab[tab_pos]; const int v0 = kLinearToGammaTab[tab_pos];
const int v1 = kLinearToGammaTab[tab_pos + 1]; const int v1 = kLinearToGammaTab[tab_pos + 1];
const int y = v1 * x + v0 * ((kGammaTabScale << shift) - x); // interpolate const int y = v1 * x + v0 * ((kGammaTabScale << 2) - x); // interpolate
return (y + kGammaTabRounder) >> kGammaTabFix; // descale return (y + kGammaTabRounder) >> kGammaTabFix; // descale
} }
@ -656,7 +659,7 @@ static WEBP_INLINE int LinearToGamma(uint32_t v, int shift) {
static void InitGammaTables(void) {} static void InitGammaTables(void) {}
static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { return v; } static WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { return v; }
static WEBP_INLINE int LinearToGamma(uint32_t v, int shift) { static WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) {
(void)shift; (void)shift;
return v; return v;
} }
@ -669,13 +672,14 @@ static WEBP_INLINE int LinearToGamma(uint32_t v, int shift) {
GammaToLinear((ptr)[0]) + \ GammaToLinear((ptr)[0]) + \
GammaToLinear((ptr)[step]) + \ GammaToLinear((ptr)[step]) + \
GammaToLinear((ptr)[rgb_stride]) + \ GammaToLinear((ptr)[rgb_stride]) + \
GammaToLinear((ptr)[rgb_stride + step]), 2) \ GammaToLinear((ptr)[rgb_stride + step]), 0) \
#define SUM2H(ptr) \ #define SUM2H(ptr) \
LinearToGamma(GammaToLinear((ptr)[0]) + GammaToLinear((ptr)[step]), 1) LinearToGamma(GammaToLinear((ptr)[0]) + GammaToLinear((ptr)[step]), 1)
#define SUM2V(ptr) \ #define SUM2V(ptr) \
LinearToGamma(GammaToLinear((ptr)[0]) + GammaToLinear((ptr)[rgb_stride]), 1) LinearToGamma(GammaToLinear((ptr)[0]) + GammaToLinear((ptr)[rgb_stride]), 1)
#define SUM1(ptr) (4 * (ptr)[0]) #define SUM1(ptr) \
LinearToGamma(GammaToLinear((ptr)[0]), 2)
#define RGB_TO_UV(x, y, SUM) { \ #define RGB_TO_UV(x, y, SUM) { \
const int src = (2 * (step * (x) + (y) * rgb_stride)); \ const int src = (2 * (step * (x) + (y) * rgb_stride)); \