• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
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 
VP8YuvToRgb(uint8_t y,uint8_t u,uint8_t v,uint8_t * const rgb)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 
VP8YuvToRgb565(uint8_t y,uint8_t u,uint8_t v,uint8_t * const rgb)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 
VP8YuvToArgb(uint8_t y,uint8_t u,uint8_t v,uint8_t * const argb)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 
VP8YuvToRgba4444(uint8_t y,uint8_t u,uint8_t v,uint8_t * const argb)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 
VP8YuvToBgr(uint8_t y,uint8_t u,uint8_t v,uint8_t * const bgr)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 
VP8YuvToBgra(uint8_t y,uint8_t u,uint8_t v,uint8_t * const bgra)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 
VP8YuvToRgba(uint8_t y,uint8_t u,uint8_t v,uint8_t * const rgba)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 
VP8ClipUV(int v)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 
VP8RGBToY(int r,int g,int b)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 
VP8RGBToU(int r,int g,int b)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 
VP8RGBToV(int r,int g,int b)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.
VP8RGBToY(int r,int g,int b)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 
VP8RGBToU(int r,int g,int b)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 
VP8RGBToV(int r,int g,int b)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