yuv.h revision 4b2196c929b70f2cdc1c2556580d349db89356d8
1// Copyright 2010 Google Inc. All Rights Reserved. 2// 3// This code is licensed under the same terms as WebM: 4// Software License Agreement: http://www.webmproject.org/license/software/ 5// Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 6// ----------------------------------------------------------------------------- 7// 8// inline YUV<->RGB conversion function 9// 10// The exact naming is Y'CbCr, following the ITU-R BT.601 standard. 11// More information at: http://en.wikipedia.org/wiki/YCbCr 12// Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16 13// U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128 14// V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128 15// We use 16bit fixed point operations for RGB->YUV conversion. 16// 17// For the Y'CbCr to RGB conversion, the BT.601 specification reads: 18// R = 1.164 * (Y-16) + 1.596 * (V-128) 19// G = 1.164 * (Y-16) - 0.813 * (V-128) - 0.391 * (U-128) 20// B = 1.164 * (Y-16) + 2.018 * (U-128) 21// where Y is in the [16,235] range, and U/V in the [16,240] range. 22// But the common term 1.164 * (Y-16) can be handled as an offset in the 23// VP8kClip[] table. So the formulae should be read as: 24// R = 1.164 * [Y + 1.371 * (V-128) ] - 18.624 25// G = 1.164 * [Y - 0.698 * (V-128) - 0.336 * (U-128)] - 18.624 26// B = 1.164 * [Y + 1.733 * (U-128)] - 18.624 27// once factorized. Here too, 16bit fixed precision is used. 28// 29// Author: Skal (pascal.massimino@gmail.com) 30 31#ifndef WEBP_DSP_YUV_H_ 32#define WEBP_DSP_YUV_H_ 33 34#include "../dec/decode_vp8.h" 35 36#if defined(WEBP_EXPERIMENTAL_FEATURES) 37// Do NOT activate this feature for real compression. This is only experimental! 38// This flag is for comparison purpose against JPEG's "YUVj" natural colorspace. 39// This colorspace is close to Rec.601's Y'CbCr model with the notable 40// difference of allowing larger range for luma/chroma. 41// See http://en.wikipedia.org/wiki/YCbCr#JPEG_conversion paragraph, and its 42// difference with http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion 43// #define USE_YUVj 44#endif 45 46//------------------------------------------------------------------------------ 47// YUV -> RGB conversion 48 49#if defined(__cplusplus) || defined(c_plusplus) 50extern "C" { 51#endif 52 53enum { YUV_FIX = 16, // fixed-point precision 54 YUV_RANGE_MIN = -227, // min value of r/g/b output 55 YUV_RANGE_MAX = 256 + 226 // max value of r/g/b output 56}; 57extern int16_t VP8kVToR[256], VP8kUToB[256]; 58extern int32_t VP8kVToG[256], VP8kUToG[256]; 59extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; 60extern uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN]; 61 62static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v, 63 uint8_t* const rgb) { 64 const int r_off = VP8kVToR[v]; 65 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 66 const int b_off = VP8kUToB[u]; 67 rgb[0] = VP8kClip[y + r_off - YUV_RANGE_MIN]; 68 rgb[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; 69 rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN]; 70} 71 72static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v, 73 uint8_t* const rgb) { 74 const int r_off = VP8kVToR[v]; 75 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 76 const int b_off = VP8kUToB[u]; 77 const uint8_t rg = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) | 78 (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5)); 79 const uint8_t gb = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) | 80 (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3)); 81#ifdef WEBP_SWAP_16BIT_CSP 82 rgb[0] = gb; 83 rgb[1] = rg; 84#else 85 rgb[0] = rg; 86 rgb[1] = gb; 87#endif 88} 89 90static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, 91 uint8_t* const argb) { 92 argb[0] = 0xff; 93 VP8YuvToRgb(y, u, v, argb + 1); 94} 95 96static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v, 97 uint8_t* const argb) { 98 const int r_off = VP8kVToR[v]; 99 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 100 const int b_off = VP8kUToB[u]; 101 const uint8_t rg = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) | 102 VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]); 103 const uint8_t ba = (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4) | 0x0f; 104#ifdef WEBP_SWAP_16BIT_CSP 105 argb[0] = ba; 106 argb[1] = rg; 107#else 108 argb[0] = rg; 109 argb[1] = ba; 110#endif 111} 112 113static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v, 114 uint8_t* const bgr) { 115 const int r_off = VP8kVToR[v]; 116 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 117 const int b_off = VP8kUToB[u]; 118 bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN]; 119 bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; 120 bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN]; 121} 122 123static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v, 124 uint8_t* const bgra) { 125 VP8YuvToBgr(y, u, v, bgra); 126 bgra[3] = 0xff; 127} 128 129static WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v, 130 uint8_t* const rgba) { 131 VP8YuvToRgb(y, u, v, rgba); 132 rgba[3] = 0xff; 133} 134 135// Must be called before everything, to initialize the tables. 136void VP8YUVInit(void); 137 138//------------------------------------------------------------------------------ 139// RGB -> YUV conversion 140 141static WEBP_INLINE int VP8ClipUV(int v) { 142 v = (v + (257 << (YUV_FIX + 2 - 1))) >> (YUV_FIX + 2); 143 return ((v & ~0xff) == 0) ? v : (v < 0) ? 0 : 255; 144} 145 146#ifndef USE_YUVj 147 148static WEBP_INLINE int VP8RGBToY(int r, int g, int b) { 149 const int kRound = (1 << (YUV_FIX - 1)) + (16 << YUV_FIX); 150 const int luma = 16839 * r + 33059 * g + 6420 * b; 151 return (luma + kRound) >> YUV_FIX; // no need to clip 152} 153 154static WEBP_INLINE int VP8RGBToU(int r, int g, int b) { 155 const int u = -9719 * r - 19081 * g + 28800 * b; 156 return VP8ClipUV(u); 157} 158 159static WEBP_INLINE int VP8RGBToV(int r, int g, int b) { 160 const int v = +28800 * r - 24116 * g - 4684 * b; 161 return VP8ClipUV(v); 162} 163 164#else 165 166// This JPEG-YUV colorspace, only for comparison! 167// These are also 16-bit precision coefficients from Rec.601, but with full 168// [0..255] output range. 169static WEBP_INLINE int VP8RGBToY(int r, int g, int b) { 170 const int kRound = (1 << (YUV_FIX - 1)); 171 const int luma = 19595 * r + 38470 * g + 7471 * b; 172 return (luma + kRound) >> YUV_FIX; // no need to clip 173} 174 175static WEBP_INLINE int VP8RGBToU(int r, int g, int b) { 176 const int u = -11058 * r - 21710 * g + 32768 * b; 177 return VP8ClipUV(u); 178} 179 180static WEBP_INLINE int VP8RGBToV(int r, int g, int b) { 181 const int v = 32768 * r - 27439 * g - 5329 * b; 182 return VP8ClipUV(v); 183} 184 185#endif // USE_YUVj 186 187#if defined(__cplusplus) || defined(c_plusplus) 188} // extern "C" 189#endif 190 191#endif /* WEBP_DSP_YUV_H_ */ 192