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 (at) 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) 50 extern "C" { 51 #endif 52 53 enum { 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 }; 57 extern int16_t VP8kVToR[256], VP8kUToB[256]; 58 extern int32_t VP8kVToG[256], VP8kUToG[256]; 59 extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; 60 extern uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN]; 61 62 static 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 72 static 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 90 static 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 96 static 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 113 static 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 123 static 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 129 static 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. 136 void VP8YUVInit(void); 137 138 //------------------------------------------------------------------------------ 139 // RGB -> YUV conversion 140 141 static 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 148 static 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 154 static 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 159 static 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. 169 static 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 175 static 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 180 static 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