picture_csp_enc.c revision 8c098653157979e397d3954fc2ea0ee43bae6ab2
133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Copyright 2014 Google Inc. All Rights Reserved. 233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// 333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Use of this source code is governed by a BSD-style license 433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// that can be found in the COPYING file in the root of the source 533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// tree. An additional intellectual property rights grant can be found 633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// in the file PATENTS. All contributing project authors may 733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// be found in the AUTHORS file in the root of the source tree. 833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// ----------------------------------------------------------------------------- 933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// 1033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// WebPPicture utils for colorspace conversion 1133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// 1233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Author: Skal (pascal.massimino@gmail.com) 1333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 1433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include <assert.h> 1533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include <stdlib.h> 1633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include <math.h> 1733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 1833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include "./vp8enci.h" 1933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include "../utils/random.h" 208c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#include "../utils/utils.h" 2133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#include "../dsp/yuv.h" 2233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 2333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Uncomment to disable gamma-compression during RGB->U/V averaging 2433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define USE_GAMMA_COMPRESSION 2533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 268c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// If defined, use table to compute x / alpha. 278c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define USE_INVERSE_ALPHA_TABLE 288c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2933f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic const union { 3033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora uint32_t argb; 3133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora uint8_t bytes[4]; 3233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} test_endian = { 0xff000000u }; 3333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define ALPHA_IS_LAST (test_endian.bytes[3] == 0xff) 3433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 3533f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE uint32_t MakeARGB32(int a, int r, int g, int b) { 3633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return (((uint32_t)a << 24) | (r << 16) | (g << 8) | b); 3733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 3833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 3933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------ 4033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Detection of non-trivial transparency 4133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 4233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Returns true if alpha[] has non-0xff values. 4333f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic int CheckNonOpaque(const uint8_t* alpha, int width, int height, 4433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int x_step, int y_step) { 4533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (alpha == NULL) return 0; 4633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora while (height-- > 0) { 4733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int x; 4833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (x = 0; x < width * x_step; x += x_step) { 4933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (alpha[x] != 0xff) return 1; // TODO(skal): check 4/8 bytes at a time. 5033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 5133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora alpha += y_step; 5233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 5333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return 0; 5433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 5533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 5633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Checking for the presence of non-opaque alpha. 5733f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureHasTransparency(const WebPPicture* picture) { 5833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (picture == NULL) return 0; 5933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (!picture->use_argb) { 6033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return CheckNonOpaque(picture->a, picture->width, picture->height, 6133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 1, picture->a_stride); 6233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } else { 6333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int x, y; 6433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint32_t* argb = picture->argb; 6533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (argb == NULL) return 0; 6633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (y = 0; y < picture->height; ++y) { 6733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (x = 0; x < picture->width; ++x) { 6833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (argb[x] < 0xff000000u) return 1; // test any alpha values != 0xff 6933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 7033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora argb += picture->argb_stride; 7133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 7233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 7333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return 0; 7433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 7533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 7633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------ 778c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// Code for gamma correction 7833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 7933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#if defined(USE_GAMMA_COMPRESSION) 8033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 8133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// gamma-compensates loss of resolution during chroma subsampling 828c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define kGamma 0.80 // for now we use a different gamma value than kGammaF 8333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define kGammaFix 12 // fixed-point precision for linear values 8433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define kGammaScale ((1 << kGammaFix) - 1) 8533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define kGammaTabFix 7 // fixed-point fractional bits precision 8633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define kGammaTabScale (1 << kGammaTabFix) 8733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define kGammaTabRounder (kGammaTabScale >> 1) 8833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#define kGammaTabSize (1 << (kGammaFix - kGammaTabFix)) 8933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 9033f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic int kLinearToGammaTab[kGammaTabSize + 1]; 9133f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic uint16_t kGammaToLinearTab[256]; 9233f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic int kGammaTablesOk = 0; 9333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 9433f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void InitGammaTables(void) { 9533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (!kGammaTablesOk) { 9633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int v; 978c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const double scale = (double)(1 << kGammaTabFix) / kGammaScale; 988c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const double norm = 1. / 255.; 9933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (v = 0; v <= 255; ++v) { 10033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora kGammaToLinearTab[v] = 1018c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora (uint16_t)(pow(norm * v, kGamma) * kGammaScale + .5); 10233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 10333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (v = 0; v <= kGammaTabSize; ++v) { 1048c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora kLinearToGammaTab[v] = (int)(255. * pow(scale * v, 1. / kGamma) + .5); 10533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 10633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora kGammaTablesOk = 1; 10733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 10833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 10933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 11033f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { 11133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return kGammaToLinearTab[v]; 11233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 11333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 1148c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE int Interpolate(int v) { 11533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int tab_pos = v >> (kGammaTabFix + 2); // integer part 11633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int x = v & ((kGammaTabScale << 2) - 1); // fractional part 11733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int v0 = kLinearToGammaTab[tab_pos]; 11833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int v1 = kLinearToGammaTab[tab_pos + 1]; 11933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int y = v1 * x + v0 * ((kGammaTabScale << 2) - x); // interpolate 1208c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora assert(tab_pos + 1 < kGammaTabSize + 1); 1218c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return y; 1228c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 1238c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1248c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// Convert a linear value 'v' to YUV_FIX+2 fixed-point precision 1258c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// U/V value, suitable for RGBToU/V calls. 1268c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { 1278c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int y = Interpolate(base_value << shift); // final uplifted value 1288c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return (y + kGammaTabRounder) >> kGammaTabFix; // descale 12933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 13033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 13133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#else 13233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 13333f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic void InitGammaTables(void) {} 13433f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE uint32_t GammaToLinear(uint8_t v) { return v; } 13533f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic WEBP_INLINE int LinearToGamma(uint32_t base_value, int shift) { 13633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return (int)(base_value << shift); 13733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 13833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 13933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#endif // USE_GAMMA_COMPRESSION 14033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 14133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------ 1428c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// RGB -> YUV conversion 1438c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1448c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic int RGBToY(int r, int g, int b, VP8Random* const rg) { 1458c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return (rg == NULL) ? VP8RGBToY(r, g, b, YUV_HALF) 1468c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora : VP8RGBToY(r, g, b, VP8RandomBits(rg, YUV_FIX)); 1478c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 1488c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1498c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic int RGBToU(int r, int g, int b, VP8Random* const rg) { 1508c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return (rg == NULL) ? VP8RGBToU(r, g, b, YUV_HALF << 2) 1518c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora : VP8RGBToU(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); 1528c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 1538c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1548c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic int RGBToV(int r, int g, int b, VP8Random* const rg) { 1558c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return (rg == NULL) ? VP8RGBToV(r, g, b, YUV_HALF << 2) 1568c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora : VP8RGBToV(r, g, b, VP8RandomBits(rg, YUV_FIX + 2)); 1578c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 1588c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1598c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora//------------------------------------------------------------------------------ 1608c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// Smart RGB->YUV conversion 1618c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1628c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic const int kNumIterations = 6; 1638c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic const int kMinDimensionIterativeConversion = 4; 1648c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1658c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// We use a-priori a different precision for storing RGB and Y/W components 1668c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// We could use YFIX=0 and only uint8_t for fixed_y_t, but it produces some 1678c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// banding sometimes. Better use extra precision. 1688c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// TODO(skal): cleanup once TFIX/YFIX values are fixed. 1698c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1708c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Aroratypedef int16_t fixed_t; // signed type with extra TFIX precision for UV 1718c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Aroratypedef uint16_t fixed_y_t; // unsigned type with extra YFIX precision for W 1728c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define TFIX 6 // fixed-point precision of RGB 1738c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define YFIX 2 // fixed point precision for Y/W 1748c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1758c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define THALF ((1 << TFIX) >> 1) 1768c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define MAX_Y_T ((256 << YFIX) - 1) 1778c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define TROUNDER (1 << (YUV_FIX + TFIX - 1)) 1788c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1798c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#if defined(USE_GAMMA_COMPRESSION) 1808c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1818c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// float variant of gamma-correction 1828c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// We use tables of different size and precision, along with a 'real-world' 1838c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// Gamma value close to ~2. 1848c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define kGammaF 2.2 1858c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic float kGammaToLinearTabF[MAX_Y_T + 1]; // size scales with Y_FIX 1868c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic float kLinearToGammaTabF[kGammaTabSize + 2]; 1878c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic int kGammaTablesFOk = 0; 1888c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1898c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic void InitGammaTablesF(void) { 1908c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (!kGammaTablesFOk) { 1918c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int v; 1928c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const double norm = 1. / MAX_Y_T; 1938c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const double scale = 1. / kGammaTabSize; 1948c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (v = 0; v <= MAX_Y_T; ++v) { 1958c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora kGammaToLinearTabF[v] = (float)pow(norm * v, kGammaF); 1968c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 1978c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (v = 0; v <= kGammaTabSize; ++v) { 1988c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora kLinearToGammaTabF[v] = (float)(MAX_Y_T * pow(scale * v, 1. / kGammaF)); 1998c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 2008c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // to prevent small rounding errors to cause read-overflow: 2018c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora kLinearToGammaTabF[kGammaTabSize + 1] = kLinearToGammaTabF[kGammaTabSize]; 2028c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora kGammaTablesFOk = 1; 2038c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 2048c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2058c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2068c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE float GammaToLinearF(int v) { 2078c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return kGammaToLinearTabF[v]; 2088c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2098c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2108c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE float LinearToGammaF(float value) { 2118c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float v = value * kGammaTabSize; 2128c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int tab_pos = (int)v; 2138c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float x = v - (float)tab_pos; // fractional part 2148c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float v0 = kLinearToGammaTabF[tab_pos + 0]; 2158c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float v1 = kLinearToGammaTabF[tab_pos + 1]; 2168c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float y = v1 * x + v0 * (1.f - x); // interpolate 2178c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return y; 2188c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2198c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2208c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#else 2218c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2228c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic void InitGammaTablesF(void) {} 2238c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE float GammaToLinearF(int v) { 2248c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float norm = 1.f / MAX_Y_T; 2258c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return norm * v; 2268c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2278c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE float LinearToGammaF(float value) { 2288c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return MAX_Y_T * value; 2298c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2308c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2318c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#endif // USE_GAMMA_COMPRESSION 2328c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2338c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora//------------------------------------------------------------------------------ 2348c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2358c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// precision: YFIX -> TFIX 2368c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE int FixedYToW(int v) { 2378c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#if TFIX == YFIX 2388c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return v; 2398c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#elif TFIX >= YFIX 2408c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return v << (TFIX - YFIX); 2418c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#else 2428c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return v >> (YFIX - TFIX); 2438c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#endif 2448c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2458c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2468c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE int FixedWToY(int v) { 2478c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#if TFIX == YFIX 2488c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return v; 2498c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#elif YFIX >= TFIX 2508c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return v << (YFIX - TFIX); 2518c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#else 2528c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return v >> (TFIX - YFIX); 2538c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#endif 2548c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2558c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2568c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic uint8_t clip_8b(fixed_t v) { 2578c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return (!(v & ~0xff)) ? (uint8_t)v : (v < 0) ? 0u : 255u; 2588c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2598c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2608c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic fixed_y_t clip_y(int y) { 2618c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return (!(y & ~MAX_Y_T)) ? (fixed_y_t)y : (y < 0) ? 0 : MAX_Y_T; 2628c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2638c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2648c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// precision: TFIX -> YFIX 2658c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic fixed_y_t clip_fixed_t(fixed_t v) { 2668c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int y = FixedWToY(v); 2678c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const fixed_y_t w = clip_y(y); 2688c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return w; 2698c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2708c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2718c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora//------------------------------------------------------------------------------ 27233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 2738c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic int RGBToGray(int r, int g, int b) { 2748c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int luma = 19595 * r + 38470 * g + 7471 * b + YUV_HALF; 2758c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return (luma >> YUV_FIX); 2768c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2778c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2788c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic float RGBToGrayF(float r, float g, float b) { 2798c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return 0.299f * r + 0.587f * g + 0.114f * b; 2808c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 28133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 2828c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic float ScaleDown(int a, int b, int c, int d) { 2838c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float A = GammaToLinearF(a); 2848c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float B = GammaToLinearF(b); 2858c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float C = GammaToLinearF(c); 2868c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float D = GammaToLinearF(d); 2878c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return LinearToGammaF(0.25f * (A + B + C + D)); 2888c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 2898c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2908c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE void UpdateW(const fixed_y_t* src, fixed_y_t* dst, int len) { 2918c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora while (len-- > 0) { 2928c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float R = GammaToLinearF(src[0]); 2938c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float G = GammaToLinearF(src[1]); 2948c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float B = GammaToLinearF(src[2]); 2958c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float Y = RGBToGrayF(R, G, B); 2968c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora *dst++ = (fixed_y_t)(LinearToGammaF(Y) + .5); 2978c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora src += 3; 2988c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 2998c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 3008c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3018c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE void UpdateChroma(const fixed_y_t* src1, 3028c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const fixed_y_t* src2, 3038c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_t* dst, fixed_y_t* tmp, int len) { 3048c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora while (len--> 0) { 3058c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float r = ScaleDown(src1[0], src1[3], src2[0], src2[3]); 3068c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float g = ScaleDown(src1[1], src1[4], src2[1], src2[4]); 3078c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float b = ScaleDown(src1[2], src1[5], src2[2], src2[5]); 3088c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const float W = RGBToGrayF(r, g, b); 3098c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst[0] = (fixed_t)FixedYToW((int)(r - W)); 3108c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst[1] = (fixed_t)FixedYToW((int)(g - W)); 3118c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst[2] = (fixed_t)FixedYToW((int)(b - W)); 3128c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst += 3; 3138c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora src1 += 6; 3148c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora src2 += 6; 3158c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (tmp != NULL) { 3168c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora tmp[0] = tmp[1] = clip_y((int)(W + .5)); 3178c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora tmp += 2; 3188c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3198c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3208c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 3218c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3228c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora//------------------------------------------------------------------------------ 3238c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3248c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE int Filter(const fixed_t* const A, const fixed_t* const B, 3258c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int rightwise) { 3268c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int v; 3278c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (!rightwise) { 3288c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora v = (A[0] * 9 + A[-3] * 3 + B[0] * 3 + B[-3]); 3298c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } else { 3308c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora v = (A[0] * 9 + A[+3] * 3 + B[0] * 3 + B[+3]); 3318c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3328c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return (v + 8) >> 4; 3338c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 3348c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3358c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE int Filter2(int A, int B) { return (A * 3 + B + 2) >> 2; } 3368c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3378c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora//------------------------------------------------------------------------------ 3388c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3398c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// 8bit -> YFIX 3408c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE fixed_y_t UpLift(uint8_t a) { 3418c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return ((fixed_y_t)a << YFIX) | (1 << (YFIX - 1)); 3428c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 3438c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3448c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic void ImportOneRow(const uint8_t* const r_ptr, 3458c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* const g_ptr, 3468c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* const b_ptr, 3478c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int step, 3488c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int pic_width, 3498c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const dst) { 3508c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int i; 3518c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (i = 0; i < pic_width; ++i) { 3528c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off = i * step; 3538c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst[3 * i + 0] = UpLift(r_ptr[off]); 3548c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst[3 * i + 1] = UpLift(g_ptr[off]); 3558c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst[3 * i + 2] = UpLift(b_ptr[off]); 3568c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3578c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (pic_width & 1) { // replicate rightmost pixel 3588c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora memcpy(dst + 3 * pic_width, dst + 3 * (pic_width - 1), 3 * sizeof(*dst)); 3598c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3608c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 3618c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3628c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic void InterpolateTwoRows(const fixed_y_t* const best_y, 3638c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const fixed_t* const prev_uv, 3648c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const fixed_t* const cur_uv, 3658c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const fixed_t* const next_uv, 3668c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int w, 3678c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const out1, 3688c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const out2) { 3698c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int i, k; 3708c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora { // special boundary case for i==0 3718c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int W0 = FixedYToW(best_y[0]); 3728c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int W1 = FixedYToW(best_y[w]); 3738c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (k = 0; k <= 2; ++k) { 3748c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora out1[k] = clip_fixed_t(Filter2(cur_uv[k], prev_uv[k]) + W0); 3758c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora out2[k] = clip_fixed_t(Filter2(cur_uv[k], next_uv[k]) + W1); 3768c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3778c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3788c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (i = 1; i < w - 1; ++i) { 3798c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int W0 = FixedYToW(best_y[i + 0]); 3808c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int W1 = FixedYToW(best_y[i + w]); 3818c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off = 3 * (i >> 1); 3828c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (k = 0; k <= 2; ++k) { 3838c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int tmp0 = Filter(cur_uv + off + k, prev_uv + off + k, i & 1); 3848c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int tmp1 = Filter(cur_uv + off + k, next_uv + off + k, i & 1); 3858c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora out1[3 * i + k] = clip_fixed_t(tmp0 + W0); 3868c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora out2[3 * i + k] = clip_fixed_t(tmp1 + W1); 3878c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3888c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3898c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora { // special boundary case for i == w - 1 3908c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int W0 = FixedYToW(best_y[i + 0]); 3918c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int W1 = FixedYToW(best_y[i + w]); 3928c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off = 3 * (i >> 1); 3938c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (k = 0; k <= 2; ++k) { 3948c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora out1[3 * i + k] = 3958c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora clip_fixed_t(Filter2(cur_uv[off + k], prev_uv[off + k]) + W0); 3968c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora out2[3 * i + k] = 3978c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora clip_fixed_t(Filter2(cur_uv[off + k], next_uv[off + k]) + W1); 3988c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 3998c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 4008c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 4018c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4028c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE uint8_t ConvertRGBToY(int r, int g, int b) { 4038c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int luma = 16839 * r + 33059 * g + 6420 * b + TROUNDER; 4048c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return clip_8b(16 + (luma >> (YUV_FIX + TFIX))); 4058c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 4068c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4078c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE uint8_t ConvertRGBToU(int r, int g, int b) { 4088c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int u = -9719 * r - 19081 * g + 28800 * b + TROUNDER; 4098c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return clip_8b(128 + (u >> (YUV_FIX + TFIX))); 4108c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 4118c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4128c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE uint8_t ConvertRGBToV(int r, int g, int b) { 4138c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int v = +28800 * r - 24116 * g - 4684 * b + TROUNDER; 4148c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return clip_8b(128 + (v >> (YUV_FIX + TFIX))); 4158c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 4168c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4178c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic int ConvertWRGBToYUV(const fixed_y_t* const best_y, 4188c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const fixed_t* const best_uv, 4198c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPPicture* const picture) { 4208c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int i, j; 4218c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int w = (picture->width + 1) & ~1; 4228c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int h = (picture->height + 1) & ~1; 4238c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int uv_w = w >> 1; 4248c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int uv_h = h >> 1; 4258c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (j = 0; j < picture->height; ++j) { 4268c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (i = 0; i < picture->width; ++i) { 4278c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off = 3 * ((i >> 1) + (j >> 1) * uv_w); 4288c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off2 = i + j * picture->y_stride; 4298c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int W = FixedYToW(best_y[i + j * w]); 4308c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int r = best_uv[off + 0] + W; 4318c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int g = best_uv[off + 1] + W; 4328c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int b = best_uv[off + 2] + W; 4338c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora picture->y[off2] = ConvertRGBToY(r, g, b); 4348c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 4358c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 4368c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (j = 0; j < uv_h; ++j) { 4378c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* const dst_u = picture->u + j * picture->uv_stride; 4388c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* const dst_v = picture->v + j * picture->uv_stride; 4398c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (i = 0; i < uv_w; ++i) { 4408c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off = 3 * (i + j * uv_w); 4418c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int r = best_uv[off + 0]; 4428c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int g = best_uv[off + 1]; 4438c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int b = best_uv[off + 2]; 4448c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_u[i] = ConvertRGBToU(r, g, b); 4458c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_v[i] = ConvertRGBToV(r, g, b); 4468c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 4478c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 4488c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return 1; 4498c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 4508c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4518c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora//------------------------------------------------------------------------------ 4528c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// Main function 4538c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4548c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define SAFE_ALLOC(W, H, T) ((T*)WebPSafeMalloc((W) * (H), sizeof(T))) 4558c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4568c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic int PreprocessARGB(const uint8_t* const r_ptr, 4578c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* const g_ptr, 4588c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* const b_ptr, 4598c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int step, int rgb_stride, 4608c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPPicture* const picture) { 4618c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // we expand the right/bottom border if needed 4628c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int w = (picture->width + 1) & ~1; 4638c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int h = (picture->height + 1) & ~1; 4648c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int uv_w = w >> 1; 4658c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int uv_h = h >> 1; 4668c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int i, j, iter; 4678c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4688c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // TODO(skal): allocate one big memory chunk. But for now, it's easier 4698c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // for valgrind debugging to have several chunks. 4708c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const tmp_buffer = SAFE_ALLOC(w * 3, 2, fixed_y_t); // scratch 4718c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const best_y = SAFE_ALLOC(w, h, fixed_y_t); 4728c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const target_y = SAFE_ALLOC(w, h, fixed_y_t); 4738c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const best_rgb_y = SAFE_ALLOC(w, 2, fixed_y_t); 4748c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_t* const best_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); 4758c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_t* const target_uv = SAFE_ALLOC(uv_w * 3, uv_h, fixed_t); 4768c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_t* const best_rgb_uv = SAFE_ALLOC(uv_w * 3, 1, fixed_t); 4778c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int ok; 4788c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4798c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (best_y == NULL || best_uv == NULL || 4808c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora target_y == NULL || target_uv == NULL || 4818c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora best_rgb_y == NULL || best_rgb_uv == NULL || 4828c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora tmp_buffer == NULL) { 4838c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora ok = WebPEncodingSetError(picture, VP8_ENC_ERROR_OUT_OF_MEMORY); 4848c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora goto End; 4858c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 4868c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora assert(picture->width >= kMinDimensionIterativeConversion); 4878c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora assert(picture->height >= kMinDimensionIterativeConversion); 4888c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4898c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // Import RGB samples to W/RGB representation. 4908c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (j = 0; j < picture->height; j += 2) { 4918c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int is_last_row = (j == picture->height - 1); 4928c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const src1 = tmp_buffer; 4938c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const src2 = tmp_buffer + 3 * w; 4948c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off1 = j * rgb_stride; 4958c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off2 = off1 + rgb_stride; 4968c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int uv_off = (j >> 1) * 3 * uv_w; 4978c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const dst_y = best_y + j * w; 4988c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4998c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // prepare two rows of input 5008c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora ImportOneRow(r_ptr + off1, g_ptr + off1, b_ptr + off1, 5018c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora step, picture->width, src1); 5028c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (!is_last_row) { 5038c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora ImportOneRow(r_ptr + off2, g_ptr + off2, b_ptr + off2, 5048c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora step, picture->width, src2); 5058c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } else { 5068c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora memcpy(src2, src1, 3 * w * sizeof(*src2)); 5078c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 5088c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora UpdateW(src1, target_y + (j + 0) * w, w); 5098c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora UpdateW(src2, target_y + (j + 1) * w, w); 5108c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora UpdateChroma(src1, src2, target_uv + uv_off, dst_y, uv_w); 5118c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora memcpy(best_uv + uv_off, target_uv + uv_off, 3 * uv_w * sizeof(*best_uv)); 5128c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora memcpy(dst_y + w, dst_y, w * sizeof(*dst_y)); 5138c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 5148c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5158c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // Iterate and resolve clipping conflicts. 5168c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (iter = 0; iter < kNumIterations; ++iter) { 5178c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int k; 5188c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const fixed_t* cur_uv = best_uv; 5198c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const fixed_t* prev_uv = best_uv; 5208c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (j = 0; j < h; j += 2) { 5218c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const src1 = tmp_buffer; 5228c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora fixed_y_t* const src2 = tmp_buffer + 3 * w; 5238c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5248c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora { 5258c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const fixed_t* const next_uv = cur_uv + ((j < h - 2) ? 3 * uv_w : 0); 5268c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora InterpolateTwoRows(best_y + j * w, prev_uv, cur_uv, next_uv, 5278c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora w, src1, src2); 5288c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora prev_uv = cur_uv; 5298c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora cur_uv = next_uv; 5308c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 5318c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5328c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora UpdateW(src1, best_rgb_y + 0 * w, w); 5338c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora UpdateW(src2, best_rgb_y + 1 * w, w); 5348c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora UpdateChroma(src1, src2, best_rgb_uv, NULL, uv_w); 5358c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5368c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // update two rows of Y and one row of RGB 5378c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (i = 0; i < 2 * w; ++i) { 5388c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off = i + j * w; 5398c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int diff_y = target_y[off] - best_rgb_y[i]; 5408c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int new_y = (int)best_y[off] + diff_y; 5418c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora best_y[off] = clip_y(new_y); 5428c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 5438c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (i = 0; i < uv_w; ++i) { 5448c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off = 3 * (i + (j >> 1) * uv_w); 5458c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int W; 5468c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (k = 0; k <= 2; ++k) { 5478c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int diff_uv = (int)target_uv[off + k] - best_rgb_uv[3 * i + k]; 5488c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora best_uv[off + k] += diff_uv; 5498c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 5508c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora W = RGBToGray(best_uv[off + 0], best_uv[off + 1], best_uv[off + 2]); 5518c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (k = 0; k <= 2; ++k) { 5528c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora best_uv[off + k] -= W; 5538c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 5548c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 5558c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 5568c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // TODO(skal): add early-termination criterion 5578c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 5588c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5598c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // final reconstruction 5608c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora ok = ConvertWRGBToYUV(best_y, best_uv, picture); 5618c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5628c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora End: 5638c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPSafeFree(best_y); 5648c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPSafeFree(best_uv); 5658c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPSafeFree(target_y); 5668c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPSafeFree(target_uv); 5678c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPSafeFree(best_rgb_y); 5688c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPSafeFree(best_rgb_uv); 5698c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPSafeFree(tmp_buffer); 5708c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return ok; 5718c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 5728c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#undef SAFE_ALLOC 5738c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5748c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora//------------------------------------------------------------------------------ 5758c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// "Fast" regular RGB->YUV 5768c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5778c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define SUM4(ptr, step) LinearToGamma( \ 5788c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora GammaToLinear((ptr)[0]) + \ 5798c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora GammaToLinear((ptr)[(step)]) + \ 5808c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora GammaToLinear((ptr)[rgb_stride]) + \ 5818c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora GammaToLinear((ptr)[rgb_stride + (step)]), 0) \ 5828c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5838c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define SUM2(ptr) \ 58433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora LinearToGamma(GammaToLinear((ptr)[0]) + GammaToLinear((ptr)[rgb_stride]), 1) 58533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 5868c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define SUM2ALPHA(ptr) ((ptr)[0] + (ptr)[rgb_stride]) 5878c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define SUM4ALPHA(ptr) (SUM2ALPHA(ptr) + SUM2ALPHA((ptr) + 4)) 5888c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5898c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#if defined(USE_INVERSE_ALPHA_TABLE) 5908c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5918c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic const int kAlphaFix = 19; 5928c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// Following table is (1 << kAlphaFix) / a. The (v * kInvAlpha[a]) >> kAlphaFix 5938c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// formula is then equal to v / a in most (99.6%) cases. Note that this table 5948c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// and constant are adjusted very tightly to fit 32b arithmetic. 5958c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// In particular, they use the fact that the operands for 'v / a' are actually 5968c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// derived as v = (a0.p0 + a1.p1 + a2.p2 + a3.p3) and a = a0 + a1 + a2 + a3 5978c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// with ai in [0..255] and pi in [0..1<<kGammaFix). The constraint to avoid 5988c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// overflow is: kGammaFix + kAlphaFix <= 31. 5998c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic const uint32_t kInvAlpha[4 * 0xff + 1] = { 6008c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 0, /* alpha = 0 */ 6018c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 524288, 262144, 174762, 131072, 104857, 87381, 74898, 65536, 6028c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 58254, 52428, 47662, 43690, 40329, 37449, 34952, 32768, 6038c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 30840, 29127, 27594, 26214, 24966, 23831, 22795, 21845, 6048c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 20971, 20164, 19418, 18724, 18078, 17476, 16912, 16384, 6058c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 15887, 15420, 14979, 14563, 14169, 13797, 13443, 13107, 6068c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 12787, 12483, 12192, 11915, 11650, 11397, 11155, 10922, 6078c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 10699, 10485, 10280, 10082, 9892, 9709, 9532, 9362, 6088c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 9198, 9039, 8886, 8738, 8594, 8456, 8322, 8192, 6098c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 8065, 7943, 7825, 7710, 7598, 7489, 7384, 7281, 6108c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 7182, 7084, 6990, 6898, 6808, 6721, 6636, 6553, 6118c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 6472, 6393, 6316, 6241, 6168, 6096, 6026, 5957, 6128c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5890, 5825, 5761, 5698, 5637, 5577, 5518, 5461, 6138c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 5405, 5349, 5295, 5242, 5190, 5140, 5090, 5041, 6148c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4993, 4946, 4899, 4854, 4809, 4766, 4723, 4681, 6158c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4639, 4599, 4559, 4519, 4481, 4443, 4405, 4369, 6168c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4332, 4297, 4262, 4228, 4194, 4161, 4128, 4096, 6178c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 4064, 4032, 4002, 3971, 3942, 3912, 3883, 3855, 6188c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3826, 3799, 3771, 3744, 3718, 3692, 3666, 3640, 6198c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3615, 3591, 3566, 3542, 3518, 3495, 3472, 3449, 6208c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3426, 3404, 3382, 3360, 3339, 3318, 3297, 3276, 6218c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3256, 3236, 3216, 3196, 3177, 3158, 3139, 3120, 6228c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 3102, 3084, 3066, 3048, 3030, 3013, 2995, 2978, 6238c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2962, 2945, 2928, 2912, 2896, 2880, 2864, 2849, 6248c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2833, 2818, 2803, 2788, 2774, 2759, 2744, 2730, 6258c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2716, 2702, 2688, 2674, 2661, 2647, 2634, 2621, 6268c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2608, 2595, 2582, 2570, 2557, 2545, 2532, 2520, 6278c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2508, 2496, 2484, 2473, 2461, 2449, 2438, 2427, 6288c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2416, 2404, 2394, 2383, 2372, 2361, 2351, 2340, 6298c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2330, 2319, 2309, 2299, 2289, 2279, 2269, 2259, 6308c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2250, 2240, 2231, 2221, 2212, 2202, 2193, 2184, 6318c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2175, 2166, 2157, 2148, 2139, 2131, 2122, 2114, 6328c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2105, 2097, 2088, 2080, 2072, 2064, 2056, 2048, 6338c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 2040, 2032, 2024, 2016, 2008, 2001, 1993, 1985, 6348c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1978, 1971, 1963, 1956, 1949, 1941, 1934, 1927, 6358c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1920, 1913, 1906, 1899, 1892, 1885, 1879, 1872, 6368c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1865, 1859, 1852, 1846, 1839, 1833, 1826, 1820, 6378c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1814, 1807, 1801, 1795, 1789, 1783, 1777, 1771, 6388c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1765, 1759, 1753, 1747, 1741, 1736, 1730, 1724, 6398c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1718, 1713, 1707, 1702, 1696, 1691, 1685, 1680, 6408c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1675, 1669, 1664, 1659, 1653, 1648, 1643, 1638, 6418c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1633, 1628, 1623, 1618, 1613, 1608, 1603, 1598, 6428c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1593, 1588, 1583, 1579, 1574, 1569, 1565, 1560, 6438c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1555, 1551, 1546, 1542, 1537, 1533, 1528, 1524, 6448c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1519, 1515, 1510, 1506, 1502, 1497, 1493, 1489, 6458c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1485, 1481, 1476, 1472, 1468, 1464, 1460, 1456, 6468c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1452, 1448, 1444, 1440, 1436, 1432, 1428, 1424, 6478c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1420, 1416, 1413, 1409, 1405, 1401, 1398, 1394, 6488c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1390, 1387, 1383, 1379, 1376, 1372, 1368, 1365, 6498c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1361, 1358, 1354, 1351, 1347, 1344, 1340, 1337, 6508c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1334, 1330, 1327, 1323, 1320, 1317, 1314, 1310, 6518c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1307, 1304, 1300, 1297, 1294, 1291, 1288, 1285, 6528c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1281, 1278, 1275, 1272, 1269, 1266, 1263, 1260, 6538c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1257, 1254, 1251, 1248, 1245, 1242, 1239, 1236, 6548c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1233, 1230, 1227, 1224, 1222, 1219, 1216, 1213, 6558c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1210, 1208, 1205, 1202, 1199, 1197, 1194, 1191, 6568c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1188, 1186, 1183, 1180, 1178, 1175, 1172, 1170, 6578c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1167, 1165, 1162, 1159, 1157, 1154, 1152, 1149, 6588c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1147, 1144, 1142, 1139, 1137, 1134, 1132, 1129, 6598c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1127, 1125, 1122, 1120, 1117, 1115, 1113, 1110, 6608c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1108, 1106, 1103, 1101, 1099, 1096, 1094, 1092, 6618c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1089, 1087, 1085, 1083, 1081, 1078, 1076, 1074, 6628c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1072, 1069, 1067, 1065, 1063, 1061, 1059, 1057, 6638c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1054, 1052, 1050, 1048, 1046, 1044, 1042, 1040, 6648c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1038, 1036, 1034, 1032, 1030, 1028, 1026, 1024, 6658c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1022, 1020, 1018, 1016, 1014, 1012, 1010, 1008, 6668c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 1006, 1004, 1002, 1000, 998, 996, 994, 992, 6678c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 991, 989, 987, 985, 983, 981, 979, 978, 6688c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 976, 974, 972, 970, 969, 967, 965, 963, 6698c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 961, 960, 958, 956, 954, 953, 951, 949, 6708c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 948, 946, 944, 942, 941, 939, 937, 936, 6718c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 934, 932, 931, 929, 927, 926, 924, 923, 6728c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 921, 919, 918, 916, 914, 913, 911, 910, 6738c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 908, 907, 905, 903, 902, 900, 899, 897, 6748c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 896, 894, 893, 891, 890, 888, 887, 885, 6758c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 884, 882, 881, 879, 878, 876, 875, 873, 6768c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 872, 870, 869, 868, 866, 865, 863, 862, 6778c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 860, 859, 858, 856, 855, 853, 852, 851, 6788c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 849, 848, 846, 845, 844, 842, 841, 840, 6798c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 838, 837, 836, 834, 833, 832, 830, 829, 6808c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 828, 826, 825, 824, 823, 821, 820, 819, 6818c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 817, 816, 815, 814, 812, 811, 810, 809, 6828c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 807, 806, 805, 804, 802, 801, 800, 799, 6838c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 798, 796, 795, 794, 793, 791, 790, 789, 6848c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 788, 787, 786, 784, 783, 782, 781, 780, 6858c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 779, 777, 776, 775, 774, 773, 772, 771, 6868c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 769, 768, 767, 766, 765, 764, 763, 762, 6878c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 760, 759, 758, 757, 756, 755, 754, 753, 6888c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 752, 751, 750, 748, 747, 746, 745, 744, 6898c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 743, 742, 741, 740, 739, 738, 737, 736, 6908c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 735, 734, 733, 732, 731, 730, 729, 728, 6918c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 727, 726, 725, 724, 723, 722, 721, 720, 6928c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 719, 718, 717, 716, 715, 714, 713, 712, 6938c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 711, 710, 709, 708, 707, 706, 705, 704, 6948c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 703, 702, 701, 700, 699, 699, 698, 697, 6958c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 696, 695, 694, 693, 692, 691, 690, 689, 6968c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 688, 688, 687, 686, 685, 684, 683, 682, 6978c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 681, 680, 680, 679, 678, 677, 676, 675, 6988c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 674, 673, 673, 672, 671, 670, 669, 668, 6998c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 667, 667, 666, 665, 664, 663, 662, 661, 7008c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 661, 660, 659, 658, 657, 657, 656, 655, 7018c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 654, 653, 652, 652, 651, 650, 649, 648, 7028c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 648, 647, 646, 645, 644, 644, 643, 642, 7038c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 641, 640, 640, 639, 638, 637, 637, 636, 7048c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 635, 634, 633, 633, 632, 631, 630, 630, 7058c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 629, 628, 627, 627, 626, 625, 624, 624, 7068c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 623, 622, 621, 621, 620, 619, 618, 618, 7078c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 617, 616, 616, 615, 614, 613, 613, 612, 7088c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 611, 611, 610, 609, 608, 608, 607, 606, 7098c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 606, 605, 604, 604, 603, 602, 601, 601, 7108c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 600, 599, 599, 598, 597, 597, 596, 595, 7118c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 595, 594, 593, 593, 592, 591, 591, 590, 7128c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 589, 589, 588, 587, 587, 586, 585, 585, 7138c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 584, 583, 583, 582, 581, 581, 580, 579, 7148c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 579, 578, 578, 577, 576, 576, 575, 574, 7158c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 574, 573, 572, 572, 571, 571, 570, 569, 7168c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 569, 568, 568, 567, 566, 566, 565, 564, 7178c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 564, 563, 563, 562, 561, 561, 560, 560, 7188c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 559, 558, 558, 557, 557, 556, 555, 555, 7198c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 554, 554, 553, 553, 552, 551, 551, 550, 7208c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 550, 549, 548, 548, 547, 547, 546, 546, 7218c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 545, 544, 544, 543, 543, 542, 542, 541, 7228c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 541, 540, 539, 539, 538, 538, 537, 537, 7238c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 536, 536, 535, 534, 534, 533, 533, 532, 7248c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 532, 531, 531, 530, 530, 529, 529, 528, 7258c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 527, 527, 526, 526, 525, 525, 524, 524, 7268c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 523, 523, 522, 522, 521, 521, 520, 520, 7278c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 519, 519, 518, 518, 517, 517, 516, 516, 7288c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 515, 515, 514, 514 7298c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora}; 7308c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 7318c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// Note that LinearToGamma() expects the values to be premultiplied by 4, 7328c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora// so we incorporate this factor 4 inside the DIVIDE_BY_ALPHA macro directly. 7338c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define DIVIDE_BY_ALPHA(sum, a) (((sum) * kInvAlpha[(a)]) >> (kAlphaFix - 2)) 7348c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 7358c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#else 7368c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 7378c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#define DIVIDE_BY_ALPHA(sum, a) (4 * (sum) / (a)) 7388c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 7398c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#endif // USE_INVERSE_ALPHA_TABLE 7408c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 7418c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE int LinearToGammaWeighted(const uint8_t* src, 7428c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* a_ptr, 7438c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint32_t total_a, int step, 7448c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int rgb_stride) { 7458c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint32_t sum = 7468c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora a_ptr[0] * GammaToLinear(src[0]) + 7478c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora a_ptr[step] * GammaToLinear(src[step]) + 7488c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora a_ptr[rgb_stride] * GammaToLinear(src[rgb_stride]) + 7498c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora a_ptr[rgb_stride + step] * GammaToLinear(src[rgb_stride + step]); 7508c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora assert(total_a > 0 && total_a <= 4 * 0xff); 7518c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#if defined(USE_INVERSE_ALPHA_TABLE) 7528c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora assert((uint64_t)sum * kInvAlpha[total_a] < ((uint64_t)1 << 32)); 7538c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#endif 7548c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return LinearToGamma(DIVIDE_BY_ALPHA(sum, total_a), 0); 7558c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 7568c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 7578c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE void ConvertRowToY(const uint8_t* const r_ptr, 7588c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* const g_ptr, 7598c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* const b_ptr, 7608c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int step, 7618c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* const dst_y, 7628c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int width, 7638c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora VP8Random* const rg) { 7648c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int i, j; 7658c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (i = 0, j = 0; i < width; ++i, j += step) { 7668c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_y[i] = RGBToY(r_ptr[j], g_ptr[j], b_ptr[j], rg); 7678c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 7688c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 7698c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 7708c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE void ConvertRowsToUVWithAlpha(const uint8_t* const r_ptr, 7718c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* const g_ptr, 7728c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* const b_ptr, 7738c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* const a_ptr, 7748c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int rgb_stride, 7758c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* const dst_u, 7768c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* const dst_v, 7778c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int width, 7788c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora VP8Random* const rg) { 7798c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int i, j; 7808c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // we loop over 2x2 blocks and produce one U/V value for each. 7818c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (i = 0, j = 0; i < (width >> 1); ++i, j += 2 * sizeof(uint32_t)) { 7828c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint32_t a = SUM4ALPHA(a_ptr + j); 7838c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int r, g, b; 7848c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (a == 4 * 0xff || a == 0) { 7858c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora r = SUM4(r_ptr + j, 4); 7868c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora g = SUM4(g_ptr + j, 4); 7878c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora b = SUM4(b_ptr + j, 4); 7888c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } else { 7898c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 4, rgb_stride); 7908c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 4, rgb_stride); 7918c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 4, rgb_stride); 7928c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 7938c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_u[i] = RGBToU(r, g, b, rg); 7948c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_v[i] = RGBToV(r, g, b, rg); 7958c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 7968c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (width & 1) { 7978c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint32_t a = 2u * SUM2ALPHA(a_ptr + j); 7988c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int r, g, b; 7998c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (a == 4 * 0xff || a == 0) { 8008c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora r = SUM2(r_ptr + j); 8018c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora g = SUM2(g_ptr + j); 8028c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora b = SUM2(b_ptr + j); 8038c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } else { 8048c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora r = LinearToGammaWeighted(r_ptr + j, a_ptr + j, a, 0, rgb_stride); 8058c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora g = LinearToGammaWeighted(g_ptr + j, a_ptr + j, a, 0, rgb_stride); 8068c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora b = LinearToGammaWeighted(b_ptr + j, a_ptr + j, a, 0, rgb_stride); 8078c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 8088c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_u[i] = RGBToU(r, g, b, rg); 8098c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_v[i] = RGBToV(r, g, b, rg); 8108c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 8118c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 8128c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 8138c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic WEBP_INLINE void ConvertRowsToUV(const uint8_t* const r_ptr, 8148c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* const g_ptr, 8158c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const uint8_t* const b_ptr, 8168c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int step, int rgb_stride, 8178c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* const dst_u, 8188c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* const dst_v, 8198c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int width, 8208c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora VP8Random* const rg) { 8218c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int i, j; 8228c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (i = 0, j = 0; i < (width >> 1); ++i, j += 2 * step) { 8238c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int r = SUM4(r_ptr + j, step); 8248c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int g = SUM4(g_ptr + j, step); 8258c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int b = SUM4(b_ptr + j, step); 8268c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_u[i] = RGBToU(r, g, b, rg); 8278c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_v[i] = RGBToV(r, g, b, rg); 8288c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 8298c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (width & 1) { 8308c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int r = SUM2(r_ptr + j); 8318c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int g = SUM2(g_ptr + j); 8328c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int b = SUM2(b_ptr + j); 8338c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_u[i] = RGBToU(r, g, b, rg); 8348c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_v[i] = RGBToV(r, g, b, rg); 8358c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 83633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 83733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 83833f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic int ImportYUVAFromRGBA(const uint8_t* const r_ptr, 83933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const g_ptr, 84033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const b_ptr, 84133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const a_ptr, 84233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int step, // bytes per pixel 84333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int rgb_stride, // bytes per scanline 84433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora float dithering, 8458c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int use_iterative_conversion, 84633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPPicture* const picture) { 8478c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int y; 84833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int width = picture->width; 84933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int height = picture->height; 85033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int has_alpha = CheckNonOpaque(a_ptr, width, height, step, rgb_stride); 85133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 8528c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora picture->colorspace = has_alpha ? WEBP_YUV420A : WEBP_YUV420; 85333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora picture->use_argb = 0; 85433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 8558c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // disable smart conversion if source is too small (overkill). 8568c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (width < kMinDimensionIterativeConversion || 8578c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora height < kMinDimensionIterativeConversion) { 8588c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora use_iterative_conversion = 0; 8598c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 86033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 8618c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (!WebPPictureAllocYUVA(picture, width, height)) { 8628c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return 0; 8638c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 8648c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (has_alpha) { 8658c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPInitAlphaProcessing(); 8668c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora assert(step == 4); 8678c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#if defined(USE_INVERSE_ALPHA_TABLE) 8688c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora assert(kAlphaFix + kGammaFix <= 31); 8698c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#endif 87033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 87133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 8728c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (use_iterative_conversion) { 8738c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora InitGammaTablesF(); 8748c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (!PreprocessARGB(r_ptr, g_ptr, b_ptr, step, rgb_stride, picture)) { 8758c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return 0; 87633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 8778c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (has_alpha) { 8788c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora WebPExtractAlpha(a_ptr, rgb_stride, width, height, 8798c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora picture->a, picture->a_stride); 88033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 8818c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } else { 8828c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* dst_y = picture->y; 8838c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* dst_u = picture->u; 8848c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* dst_v = picture->v; 8858c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora uint8_t* dst_a = picture->a; 8868c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 8878c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora VP8Random base_rg; 8888c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora VP8Random* rg = NULL; 8898c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (dithering > 0.) { 8908c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora VP8InitRandom(&base_rg, dithering); 8918c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora rg = &base_rg; 89233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 89333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 8948c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora InitGammaTables(); 8958c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 8968c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora // Downsample Y/U/V planes, two rows at a time 8978c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora for (y = 0; y < (height >> 1); ++y) { 8988c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int rows_have_alpha = has_alpha; 8998c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off1 = (2 * y + 0) * rgb_stride; 9008c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off2 = (2 * y + 1) * rgb_stride; 9018c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora ConvertRowToY(r_ptr + off1, g_ptr + off1, b_ptr + off1, step, 9028c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_y, width, rg); 9038c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora ConvertRowToY(r_ptr + off2, g_ptr + off2, b_ptr + off2, step, 9048c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_y + picture->y_stride, width, rg); 9058c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_y += 2 * picture->y_stride; 9068c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (has_alpha) { 9078c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora rows_have_alpha &= !WebPExtractAlpha(a_ptr + off1, rgb_stride, 9088c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora width, 2, 9098c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_a, picture->a_stride); 9108c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_a += 2 * picture->a_stride; 9118c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 9128c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (!rows_have_alpha) { 9138c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora ConvertRowsToUV(r_ptr + off1, g_ptr + off1, b_ptr + off1, 9148c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora step, rgb_stride, dst_u, dst_v, width, rg); 9158c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } else { 9168c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora ConvertRowsToUVWithAlpha(r_ptr + off1, g_ptr + off1, b_ptr + off1, 9178c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora a_ptr + off1, rgb_stride, 9188c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_u, dst_v, width, rg); 9198c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 9208c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_u += picture->uv_stride; 9218c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_v += picture->uv_stride; 9228c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 9238c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (height & 1) { // extra last row 9248c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora const int off = 2 * y * rgb_stride; 9258c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora int row_has_alpha = has_alpha; 9268c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora ConvertRowToY(r_ptr + off, g_ptr + off, b_ptr + off, step, 9278c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_y, width, rg); 9288c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (row_has_alpha) { 9298c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora row_has_alpha &= !WebPExtractAlpha(a_ptr + off, 0, width, 1, dst_a, 0); 9308c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } 9318c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora if (!row_has_alpha) { 9328c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora ConvertRowsToUV(r_ptr + off, g_ptr + off, b_ptr + off, 9338c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora step, 0, dst_u, dst_v, width, rg); 9348c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } else { 9358c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora ConvertRowsToUVWithAlpha(r_ptr + off, g_ptr + off, b_ptr + off, 9368c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora a_ptr + off, 0, 9378c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dst_u, dst_v, width, rg); 93833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 93933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 94033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 94133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return 1; 94233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 94333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 94433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora#undef SUM4 9458c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#undef SUM2 9468c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#undef SUM4ALPHA 9478c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#undef SUM2ALPHA 94833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 94933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------ 95033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// call for ARGB->YUVA conversion 95133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 9528c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arorastatic int PictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace, 9538c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora float dithering, int use_iterative_conversion) { 95433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (picture == NULL) return 0; 95533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (picture->argb == NULL) { 95633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); 9578c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora } else if ((colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { 9588c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); 95933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } else { 96033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const argb = (const uint8_t*)picture->argb; 96133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const r = ALPHA_IS_LAST ? argb + 2 : argb + 1; 96233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const g = ALPHA_IS_LAST ? argb + 1 : argb + 2; 96333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const b = ALPHA_IS_LAST ? argb + 0 : argb + 3; 96433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const a = ALPHA_IS_LAST ? argb + 3 : argb + 0; 96533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 9668c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora picture->colorspace = WEBP_YUV420; 96733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return ImportYUVAFromRGBA(r, g, b, a, 4, 4 * picture->argb_stride, 9688c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora dithering, use_iterative_conversion, picture); 96933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 97033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 97133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 9728c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Aroraint WebPPictureARGBToYUVADithered(WebPPicture* picture, WebPEncCSP colorspace, 9738c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora float dithering) { 9748c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return PictureARGBToYUVA(picture, colorspace, dithering, 0); 9758c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 9768c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 97733f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureARGBToYUVA(WebPPicture* picture, WebPEncCSP colorspace) { 9788c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return PictureARGBToYUVA(picture, colorspace, 0.f, 0); 9798c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora} 9808c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 9818c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#if WEBP_ENCODER_ABI_VERSION > 0x0204 9828c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Aroraint WebPPictureSmartARGBToYUVA(WebPPicture* picture) { 9838c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora return PictureARGBToYUVA(picture, WEBP_YUV420, 0.f, 1); 98433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 9858c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora#endif 98633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 98733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------ 98833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// call for YUVA -> ARGB conversion 98933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 99033f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureYUVAToARGB(WebPPicture* picture) { 99133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (picture == NULL) return 0; 99233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (picture->y == NULL || picture->u == NULL || picture->v == NULL) { 99333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); 99433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 99533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if ((picture->colorspace & WEBP_CSP_ALPHA_BIT) && picture->a == NULL) { 99633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return WebPEncodingSetError(picture, VP8_ENC_ERROR_NULL_PARAMETER); 99733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 99833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if ((picture->colorspace & WEBP_CSP_UV_MASK) != WEBP_YUV420) { 99933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return WebPEncodingSetError(picture, VP8_ENC_ERROR_INVALID_CONFIGURATION); 100033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 100133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora // Allocate a new argb buffer (discarding the previous one). 100233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (!WebPPictureAllocARGB(picture, picture->width, picture->height)) return 0; 100333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora picture->use_argb = 1; 100433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 100533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora // Convert 100633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora { 100733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int y; 100833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int width = picture->width; 100933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int height = picture->height; 101033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int argb_stride = 4 * picture->argb_stride; 101133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora uint8_t* dst = (uint8_t*)picture->argb; 101233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t *cur_u = picture->u, *cur_v = picture->v, *cur_y = picture->y; 101333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora WebPUpsampleLinePairFunc upsample = WebPGetLinePairConverter(ALPHA_IS_LAST); 101433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 101533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora // First row, with replicated top samples. 101633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); 101733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora cur_y += picture->y_stride; 101833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora dst += argb_stride; 101933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora // Center rows. 102033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (y = 1; y + 1 < height; y += 2) { 102133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const top_u = cur_u; 102233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const top_v = cur_v; 102333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora cur_u += picture->uv_stride; 102433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora cur_v += picture->uv_stride; 102533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora upsample(cur_y, cur_y + picture->y_stride, top_u, top_v, cur_u, cur_v, 102633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora dst, dst + argb_stride, width); 102733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora cur_y += 2 * picture->y_stride; 102833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora dst += 2 * argb_stride; 102933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 103033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora // Last row (if needed), with replicated bottom samples. 103133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (height > 1 && !(height & 1)) { 103233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora upsample(cur_y, NULL, cur_u, cur_v, cur_u, cur_v, dst, NULL, width); 103333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 103433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora // Insert alpha values if needed, in replacement for the default 0xff ones. 103533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (picture->colorspace & WEBP_CSP_ALPHA_BIT) { 103633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (y = 0; y < height; ++y) { 103733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora uint32_t* const argb_dst = picture->argb + y * picture->argb_stride; 103833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const src = picture->a + y * picture->a_stride; 103933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int x; 104033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (x = 0; x < width; ++x) { 104133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora argb_dst[x] = (argb_dst[x] & 0x00ffffffu) | ((uint32_t)src[x] << 24); 104233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 104333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 104433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 104533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 104633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return 1; 104733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 104833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 104933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------ 105033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// automatic import / conversion 105133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 105233f74dabbc7920a65ed435d7417987589febdc16Vikas Arorastatic int Import(WebPPicture* const picture, 105333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const rgb, int rgb_stride, 105433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int step, int swap_rb, int import_alpha) { 105533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int y; 105633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const r_ptr = rgb + (swap_rb ? 2 : 0); 105733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const g_ptr = rgb + 1; 105833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const b_ptr = rgb + (swap_rb ? 0 : 2); 105933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* const a_ptr = import_alpha ? rgb + 3 : NULL; 106033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int width = picture->width; 106133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int height = picture->height; 106233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 106333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (!picture->use_argb) { 106433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return ImportYUVAFromRGBA(r_ptr, g_ptr, b_ptr, a_ptr, step, rgb_stride, 10658c098653157979e397d3954fc2ea0ee43bae6ab2Vikas Arora 0.f /* no dithering */, 0, picture); 106633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 106733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora if (!WebPPictureAlloc(picture)) return 0; 106833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 106933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora assert(step >= (import_alpha ? 4 : 3)); 107033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (y = 0; y < height; ++y) { 107133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora uint32_t* const dst = &picture->argb[y * picture->argb_stride]; 107233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora int x; 107333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora for (x = 0; x < width; ++x) { 107433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const int offset = step * x + y * rgb_stride; 107533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora dst[x] = MakeARGB32(import_alpha ? a_ptr[offset] : 0xff, 107633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora r_ptr[offset], g_ptr[offset], b_ptr[offset]); 107733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 107833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora } 107933f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return 1; 108033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 108133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 108233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora// Public API 108333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 108433f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureImportRGB(WebPPicture* picture, 108533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* rgb, int rgb_stride) { 108633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 0, 0) : 0; 108733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 108833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 108933f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureImportBGR(WebPPicture* picture, 109033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* rgb, int rgb_stride) { 109133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return (picture != NULL) ? Import(picture, rgb, rgb_stride, 3, 1, 0) : 0; 109233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 109333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 109433f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureImportRGBA(WebPPicture* picture, 109533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* rgba, int rgba_stride) { 109633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 1) : 0; 109733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 109833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 109933f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureImportBGRA(WebPPicture* picture, 110033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* rgba, int rgba_stride) { 110133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 1) : 0; 110233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 110333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 110433f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureImportRGBX(WebPPicture* picture, 110533f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* rgba, int rgba_stride) { 110633f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 0, 0) : 0; 110733f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 110833f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 110933f74dabbc7920a65ed435d7417987589febdc16Vikas Aroraint WebPPictureImportBGRX(WebPPicture* picture, 111033f74dabbc7920a65ed435d7417987589febdc16Vikas Arora const uint8_t* rgba, int rgba_stride) { 111133f74dabbc7920a65ed435d7417987589febdc16Vikas Arora return (picture != NULL) ? Import(picture, rgba, rgba_stride, 4, 1, 0) : 0; 111233f74dabbc7920a65ed435d7417987589febdc16Vikas Arora} 111333f74dabbc7920a65ed435d7417987589febdc16Vikas Arora 111433f74dabbc7920a65ed435d7417987589febdc16Vikas Arora//------------------------------------------------------------------------------ 1115