yuv.h revision 0406ce1417f76f2034833414dcecc9f56253640c
1a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// Copyright 2010 Google Inc. All Rights Reserved. 29aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 30406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Use of this source code is governed by a BSD-style license 40406ce1417f76f2034833414dcecc9f56253640cVikas Arora// that can be found in the COPYING file in the root of the source 50406ce1417f76f2034833414dcecc9f56253640cVikas Arora// tree. An additional intellectual property rights grant can be found 60406ce1417f76f2034833414dcecc9f56253640cVikas Arora// in the file PATENTS. All contributing project authors may 70406ce1417f76f2034833414dcecc9f56253640cVikas Arora// be found in the AUTHORS file in the root of the source tree. 89aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// ----------------------------------------------------------------------------- 99aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 10a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// inline YUV<->RGB conversion function 119aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// 121e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// The exact naming is Y'CbCr, following the ITU-R BT.601 standard. 131e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// More information at: http://en.wikipedia.org/wiki/YCbCr 141e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16 151e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128 161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128 171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// We use 16bit fixed point operations for RGB->YUV conversion. 181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// 191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// For the Y'CbCr to RGB conversion, the BT.601 specification reads: 201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// R = 1.164 * (Y-16) + 1.596 * (V-128) 211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128) 221e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// B = 1.164 * (Y-16) + 2.018 * (U-128) 231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// where Y is in the [16,235] range, and U/V in the [16,240] range. 240406ce1417f76f2034833414dcecc9f56253640cVikas Arora// In the table-lookup version (WEBP_YUV_USE_TABLE), the common factor 250406ce1417f76f2034833414dcecc9f56253640cVikas Arora// "1.164 * (Y-16)" can be handled as an offset in the VP8kClip[] table. 260406ce1417f76f2034833414dcecc9f56253640cVikas Arora// So in this case the formulae should be read as: 271e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// R = 1.164 * [Y + 1.371 * (V-128) ] - 18.624 281e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// G = 1.164 * [Y - 0.698 * (V-128) - 0.336 * (U-128)] - 18.624 291e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// B = 1.164 * [Y + 1.733 * (U-128)] - 18.624 301e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// once factorized. Here too, 16bit fixed precision is used. 311e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// 329aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Author: Skal (pascal.massimino@gmail.com) 339aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 34a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#ifndef WEBP_DSP_YUV_H_ 35a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#define WEBP_DSP_YUV_H_ 369aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 37a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#include "../dec/decode_vp8.h" 389aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 390406ce1417f76f2034833414dcecc9f56253640cVikas Arora// Define the following to use the LUT-based code: 400406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define WEBP_YUV_USE_TABLE 410406ce1417f76f2034833414dcecc9f56253640cVikas Arora 421e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#if defined(WEBP_EXPERIMENTAL_FEATURES) 431e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// Do NOT activate this feature for real compression. This is only experimental! 441e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace. 451e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// This colorspace is close to Rec.601's Y'CbCr model with the notable 461e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// difference of allowing larger range for luma/chroma. 471e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// See http://en.wikipedia.org/wiki/YCbCr#JPEG_conversion paragraph, and its 481e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// difference with http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion 491e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// #define USE_YUVj 501e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif 5188fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora 52a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 53a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// YUV -> RGB conversion 54a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 559aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#if defined(__cplusplus) || defined(c_plusplus) 569aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldextern "C" { 579aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#endif 589aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 599aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldenum { YUV_FIX = 16, // fixed-point precision 600406ce1417f76f2034833414dcecc9f56253640cVikas Arora YUV_HALF = 1 << (YUV_FIX - 1), 610406ce1417f76f2034833414dcecc9f56253640cVikas Arora YUV_MASK = (256 << YUV_FIX) - 1, 629aea642eefa7a641ab8b89d953251939221d2719Eric Hassold YUV_RANGE_MIN = -227, // min value of r/g/b output 639aea642eefa7a641ab8b89d953251939221d2719Eric Hassold YUV_RANGE_MAX = 256 + 226 // max value of r/g/b output 649aea642eefa7a641ab8b89d953251939221d2719Eric Hassold}; 650406ce1417f76f2034833414dcecc9f56253640cVikas Arora 660406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef WEBP_YUV_USE_TABLE 670406ce1417f76f2034833414dcecc9f56253640cVikas Arora 689aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldextern int16_t VP8kVToR[256], VP8kUToB[256]; 699aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldextern int32_t VP8kVToG[256], VP8kUToG[256]; 709aea642eefa7a641ab8b89d953251939221d2719Eric Hassoldextern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; 71466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Aroraextern uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN]; 729aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 73a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v, 74a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const rgb) { 759aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const int r_off = VP8kVToR[v]; 769aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 779aea642eefa7a641ab8b89d953251939221d2719Eric Hassold const int b_off = VP8kUToB[u]; 789aea642eefa7a641ab8b89d953251939221d2719Eric Hassold rgb[0] = VP8kClip[y + r_off - YUV_RANGE_MIN]; 799aea642eefa7a641ab8b89d953251939221d2719Eric Hassold rgb[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; 809aea642eefa7a641ab8b89d953251939221d2719Eric Hassold rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN]; 819aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 829aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 830406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v, 840406ce1417f76f2034833414dcecc9f56253640cVikas Arora uint8_t* const bgr) { 850406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int r_off = VP8kVToR[v]; 860406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 870406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int b_off = VP8kUToB[u]; 880406ce1417f76f2034833414dcecc9f56253640cVikas Arora bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN]; 890406ce1417f76f2034833414dcecc9f56253640cVikas Arora bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; 900406ce1417f76f2034833414dcecc9f56253640cVikas Arora bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN]; 910406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 920406ce1417f76f2034833414dcecc9f56253640cVikas Arora 93a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v, 94a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const rgb) { 95466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const int r_off = VP8kVToR[v]; 96466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 97466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const int b_off = VP8kUToB[u]; 981e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const uint8_t rg = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) | 991e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5)); 1001e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const uint8_t gb = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) | 1011e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3)); 1021e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifdef WEBP_SWAP_16BIT_CSP 1031e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora rgb[0] = gb; 1041e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora rgb[1] = rg; 10588fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora#else 1061e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora rgb[0] = rg; 1071e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora rgb[1] = gb; 10888fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora#endif 109466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 110466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 111a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v, 112466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora uint8_t* const argb) { 113466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const int r_off = VP8kVToR[v]; 114466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 115466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora const int b_off = VP8kUToB[u]; 1161e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const uint8_t rg = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) | 1171e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]); 1181e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const uint8_t ba = (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4) | 0x0f; 1191e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifdef WEBP_SWAP_16BIT_CSP 1201e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora argb[0] = ba; 1211e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora argb[1] = rg; 12288fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora#else 1231e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora argb[0] = rg; 1241e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora argb[1] = ba; 12588fe2b83c4b9232cd08729556fd0485d6a6a92cdVikas Arora#endif 1269aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 1279aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 1280406ce1417f76f2034833414dcecc9f56253640cVikas Arora#else // Table-free version (slower on x86) 1290406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1300406ce1417f76f2034833414dcecc9f56253640cVikas Arora// These constants are 16b fixed-point version of ITU-R BT.601 constants 1310406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kYScale 76309 // 1.164 = 255 / 219 1320406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kVToR 104597 // 1.596 = 255 / 112 * 0.701 1330406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kUToG 25674 // 0.391 = 255 / 112 * 0.886 * 0.114 / 0.587 1340406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kVToG 53278 // 0.813 = 255 / 112 * 0.701 * 0.299 / 0.587 1350406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kUToB 132201 // 2.018 = 255 / 112 * 0.886 1360406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kRCst (-kYScale * 16 - kVToR * 128 + YUV_HALF) 1370406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kGCst (-kYScale * 16 + kUToG * 128 + kVToG * 128 + YUV_HALF) 1380406ce1417f76f2034833414dcecc9f56253640cVikas Arora#define kBCst (-kYScale * 16 - kUToB * 128 + YUV_HALF) 1390406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1400406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE uint8_t VP8Clip8(int v) { 1410406ce1417f76f2034833414dcecc9f56253640cVikas Arora return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> YUV_FIX) 1420406ce1417f76f2034833414dcecc9f56253640cVikas Arora : (v < 0) ? 0u : 255u; 1430406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1440406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1450406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE uint8_t VP8ClipN(int v, int N) { // clip to N bits 1460406ce1417f76f2034833414dcecc9f56253640cVikas Arora return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> (YUV_FIX + (8 - N))) 1470406ce1417f76f2034833414dcecc9f56253640cVikas Arora : (v < 0) ? 0u : (255u >> (8 - N)); 1480406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1490406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1500406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE int VP8YUVToR(int y, int v) { 1510406ce1417f76f2034833414dcecc9f56253640cVikas Arora return kYScale * y + kVToR * v + kRCst; 1520406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1530406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1540406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE int VP8YUVToG(int y, int u, int v) { 1550406ce1417f76f2034833414dcecc9f56253640cVikas Arora return kYScale * y - kUToG * u - kVToG * v + kGCst; 1560406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1570406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1580406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE int VP8YUVToB(int y, int u) { 1590406ce1417f76f2034833414dcecc9f56253640cVikas Arora return kYScale * y + kUToB * u + kBCst; 1600406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1610406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1620406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v, 1630406ce1417f76f2034833414dcecc9f56253640cVikas Arora uint8_t* const rgb) { 1640406ce1417f76f2034833414dcecc9f56253640cVikas Arora rgb[0] = VP8Clip8(VP8YUVToR(y, v)); 1650406ce1417f76f2034833414dcecc9f56253640cVikas Arora rgb[1] = VP8Clip8(VP8YUVToG(y, u, v)); 1660406ce1417f76f2034833414dcecc9f56253640cVikas Arora rgb[2] = VP8Clip8(VP8YUVToB(y, u)); 1670406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1680406ce1417f76f2034833414dcecc9f56253640cVikas Arora 169a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v, 170a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const bgr) { 1710406ce1417f76f2034833414dcecc9f56253640cVikas Arora bgr[0] = VP8Clip8(VP8YUVToB(y, u)); 1720406ce1417f76f2034833414dcecc9f56253640cVikas Arora bgr[1] = VP8Clip8(VP8YUVToG(y, u, v)); 1730406ce1417f76f2034833414dcecc9f56253640cVikas Arora bgr[2] = VP8Clip8(VP8YUVToR(y, v)); 1740406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1750406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1760406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v, 1770406ce1417f76f2034833414dcecc9f56253640cVikas Arora uint8_t* const rgb) { 1780406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int r = VP8Clip8(VP8YUVToR(y, u)); 1790406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int g = VP8ClipN(VP8YUVToG(y, u, v), 6); 1800406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int b = VP8ClipN(VP8YUVToB(y, v), 5); 1810406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint8_t rg = (r & 0xf8) | (g >> 3); 1820406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint8_t gb = (g << 5) | b; 1830406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef WEBP_SWAP_16BIT_CSP 1840406ce1417f76f2034833414dcecc9f56253640cVikas Arora rgb[0] = gb; 1850406ce1417f76f2034833414dcecc9f56253640cVikas Arora rgb[1] = rg; 1860406ce1417f76f2034833414dcecc9f56253640cVikas Arora#else 1870406ce1417f76f2034833414dcecc9f56253640cVikas Arora rgb[0] = rg; 1880406ce1417f76f2034833414dcecc9f56253640cVikas Arora rgb[1] = gb; 1890406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 1900406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 1910406ce1417f76f2034833414dcecc9f56253640cVikas Arora 1920406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v, 1930406ce1417f76f2034833414dcecc9f56253640cVikas Arora uint8_t* const argb) { 1940406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int r = VP8Clip8(VP8YUVToR(y, u)); 1950406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int g = VP8ClipN(VP8YUVToG(y, u, v), 4); 1960406ce1417f76f2034833414dcecc9f56253640cVikas Arora const int b = VP8Clip8(VP8YUVToB(y, v)); 1970406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint8_t rg = (r & 0xf0) | g; 1980406ce1417f76f2034833414dcecc9f56253640cVikas Arora const uint8_t ba = b | 0x0f; // overwrite the lower 4 bits 1990406ce1417f76f2034833414dcecc9f56253640cVikas Arora#ifdef WEBP_SWAP_16BIT_CSP 2000406ce1417f76f2034833414dcecc9f56253640cVikas Arora argb[0] = ba; 2010406ce1417f76f2034833414dcecc9f56253640cVikas Arora argb[1] = rg; 2020406ce1417f76f2034833414dcecc9f56253640cVikas Arora#else 2030406ce1417f76f2034833414dcecc9f56253640cVikas Arora argb[0] = rg; 2040406ce1417f76f2034833414dcecc9f56253640cVikas Arora argb[1] = ba; 2050406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif 2060406ce1417f76f2034833414dcecc9f56253640cVikas Arora} 2070406ce1417f76f2034833414dcecc9f56253640cVikas Arora 2080406ce1417f76f2034833414dcecc9f56253640cVikas Arora#endif // WEBP_YUV_USE_TABLE 2090406ce1417f76f2034833414dcecc9f56253640cVikas Arora 2100406ce1417f76f2034833414dcecc9f56253640cVikas Arorastatic WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, 2110406ce1417f76f2034833414dcecc9f56253640cVikas Arora uint8_t* const argb) { 2120406ce1417f76f2034833414dcecc9f56253640cVikas Arora argb[0] = 0xff; 2130406ce1417f76f2034833414dcecc9f56253640cVikas Arora VP8YuvToRgb(y, u, v, argb + 1); 2149aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 2159aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 216a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v, 217a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const bgra) { 2189aea642eefa7a641ab8b89d953251939221d2719Eric Hassold VP8YuvToBgr(y, u, v, bgra); 2199aea642eefa7a641ab8b89d953251939221d2719Eric Hassold bgra[3] = 0xff; 2209aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} 2219aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 222a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v, 223a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora uint8_t* const rgba) { 224466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora VP8YuvToRgb(y, u, v, rgba); 225466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora rgba[3] = 0xff; 226466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora} 227466727975bcc57c0c5597bcd0747a2fe4777b303Vikas Arora 2289aea642eefa7a641ab8b89d953251939221d2719Eric Hassold// Must be called before everything, to initialize the tables. 22903d5e34c70f174c16282b0efdc6bb9473df5f8f1Vikas Aroravoid VP8YUVInit(void); 2309aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 231a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora//------------------------------------------------------------------------------ 232a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora// RGB -> YUV conversion 233a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 234a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int VP8ClipUV(int v) { 2351e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora v = (v + (257 << (YUV_FIX + 2 - 1))) >> (YUV_FIX + 2); 2361e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return ((v & ~0xff) == 0) ? v : (v < 0) ? 0 : 255; 237a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 238a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 2391e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#ifndef USE_YUVj 2401e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 241a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int VP8RGBToY(int r, int g, int b) { 242a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int kRound = (1 << (YUV_FIX - 1)) + (16 << YUV_FIX); 243a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora const int luma = 16839 * r + 33059 * g + 6420 * b; 244a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora return (luma + kRound) >> YUV_FIX; // no need to clip 245a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 246a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 247a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int VP8RGBToU(int r, int g, int b) { 2481e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int u = -9719 * r - 19081 * g + 28800 * b; 2491e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return VP8ClipUV(u); 2501e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 2511e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2521e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic WEBP_INLINE int VP8RGBToV(int r, int g, int b) { 2531e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int v = +28800 * r - 24116 * g - 4684 * b; 2541e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return VP8ClipUV(v); 2551e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 2561e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2571e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#else 2581e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2591e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// This JPEG-YUV colorspace, only for comparison! 2601e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// These are also 16-bit precision coefficients from Rec.601, but with full 2611e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora// [0..255] output range. 2621e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic WEBP_INLINE int VP8RGBToY(int r, int g, int b) { 2631e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int kRound = (1 << (YUV_FIX - 1)); 2641e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int luma = 19595 * r + 38470 * g + 7471 * b; 2651e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return (luma + kRound) >> YUV_FIX; // no need to clip 2661e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora} 2671e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2681e7bf8805bd030c19924a5306837ecd72c295751Vikas Arorastatic WEBP_INLINE int VP8RGBToU(int r, int g, int b) { 2691e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int u = -11058 * r - 21710 * g + 32768 * b; 2701e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return VP8ClipUV(u); 271a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 272a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 273a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arorastatic WEBP_INLINE int VP8RGBToV(int r, int g, int b) { 2741e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora const int v = 32768 * r - 27439 * g - 5329 * b; 2751e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora return VP8ClipUV(v); 276a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora} 277a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora 2781e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora#endif // USE_YUVj 2791e7bf8805bd030c19924a5306837ecd72c295751Vikas Arora 2809aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#if defined(__cplusplus) || defined(c_plusplus) 2819aea642eefa7a641ab8b89d953251939221d2719Eric Hassold} // extern "C" 2829aea642eefa7a641ab8b89d953251939221d2719Eric Hassold#endif 2839aea642eefa7a641ab8b89d953251939221d2719Eric Hassold 284a2415724fb3466168b2af5b08bd94ba732c0e753Vikas Arora#endif /* WEBP_DSP_YUV_H_ */ 285