Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(86)

Side by Side Diff: third_party/libwebp/dsp/yuv.h

Issue 12942006: libwebp: update snapshot to v0.3.0-rc6 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/libwebp/dsp/upsampling_sse2.c ('k') | third_party/libwebp/dsp/yuv.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2010 Google Inc. All Rights Reserved. 1 // Copyright 2010 Google Inc. All Rights Reserved.
2 // 2 //
3 // This code is licensed under the same terms as WebM: 3 // This code is licensed under the same terms as WebM:
4 // Software License Agreement: http://www.webmproject.org/license/software/ 4 // Software License Agreement: http://www.webmproject.org/license/software/
5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/ 5 // Additional IP Rights Grant: http://www.webmproject.org/license/additional/
6 // ----------------------------------------------------------------------------- 6 // -----------------------------------------------------------------------------
7 // 7 //
8 // inline YUV<->RGB conversion function 8 // inline YUV<->RGB conversion function
9 // 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 // In the table-lookup version (WEBP_YUV_USE_TABLE), the common factor
23 // "1.164 * (Y-16)" can be handled as an offset in the VP8kClip[] table.
24 // So in this case the formulae should be read as:
25 // R = 1.164 * [Y + 1.371 * (V-128) ] - 18.624
26 // G = 1.164 * [Y - 0.698 * (V-128) - 0.336 * (U-128)] - 18.624
27 // B = 1.164 * [Y + 1.733 * (U-128)] - 18.624
28 // once factorized. Here too, 16bit fixed precision is used.
29 //
10 // Author: Skal (pascal.massimino@gmail.com) 30 // Author: Skal (pascal.massimino@gmail.com)
11 31
12 #ifndef WEBP_DSP_YUV_H_ 32 #ifndef WEBP_DSP_YUV_H_
13 #define WEBP_DSP_YUV_H_ 33 #define WEBP_DSP_YUV_H_
14 34
15 #include "../dec/decode_vp8.h" 35 #include "../dec/decode_vp8.h"
16 36
37 // Define the following to use the LUT-based code:
38 #define WEBP_YUV_USE_TABLE
39
40 #if defined(WEBP_EXPERIMENTAL_FEATURES)
41 // Do NOT activate this feature for real compression. This is only experimental!
42 // This flag is for comparison purpose against JPEG's "YUVj" natural colorspace.
43 // This colorspace is close to Rec.601's Y'CbCr model with the notable
44 // difference of allowing larger range for luma/chroma.
45 // See http://en.wikipedia.org/wiki/YCbCr#JPEG_conversion paragraph, and its
46 // difference with http://en.wikipedia.org/wiki/YCbCr#ITU-R_BT.601_conversion
47 // #define USE_YUVj
48 #endif
49
17 //------------------------------------------------------------------------------ 50 //------------------------------------------------------------------------------
18 // YUV -> RGB conversion 51 // YUV -> RGB conversion
19 52
20 #if defined(__cplusplus) || defined(c_plusplus) 53 #if defined(__cplusplus) || defined(c_plusplus)
21 extern "C" { 54 extern "C" {
22 #endif 55 #endif
23 56
24 enum { YUV_FIX = 16, // fixed-point precision 57 enum { YUV_FIX = 16, // fixed-point precision
58 YUV_HALF = 1 << (YUV_FIX - 1),
59 YUV_MASK = (256 << YUV_FIX) - 1,
25 YUV_RANGE_MIN = -227, // min value of r/g/b output 60 YUV_RANGE_MIN = -227, // min value of r/g/b output
26 YUV_RANGE_MAX = 256 + 226 // max value of r/g/b output 61 YUV_RANGE_MAX = 256 + 226 // max value of r/g/b output
27 }; 62 };
63
64 #ifdef WEBP_YUV_USE_TABLE
65
28 extern int16_t VP8kVToR[256], VP8kUToB[256]; 66 extern int16_t VP8kVToR[256], VP8kUToB[256];
29 extern int32_t VP8kVToG[256], VP8kUToG[256]; 67 extern int32_t VP8kVToG[256], VP8kUToG[256];
30 extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN]; 68 extern uint8_t VP8kClip[YUV_RANGE_MAX - YUV_RANGE_MIN];
31 extern uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN]; 69 extern uint8_t VP8kClip4Bits[YUV_RANGE_MAX - YUV_RANGE_MIN];
32 70
33 static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v, 71 static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v,
34 uint8_t* const rgb) { 72 uint8_t* const rgb) {
35 const int r_off = VP8kVToR[v]; 73 const int r_off = VP8kVToR[v];
36 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 74 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
37 const int b_off = VP8kUToB[u]; 75 const int b_off = VP8kUToB[u];
38 rgb[0] = VP8kClip[y + r_off - YUV_RANGE_MIN]; 76 rgb[0] = VP8kClip[y + r_off - YUV_RANGE_MIN];
39 rgb[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; 77 rgb[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
40 rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN]; 78 rgb[2] = VP8kClip[y + b_off - YUV_RANGE_MIN];
41 } 79 }
42 80
81 static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v,
82 uint8_t* const bgr) {
83 const int r_off = VP8kVToR[v];
84 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
85 const int b_off = VP8kUToB[u];
86 bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN];
87 bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN];
88 bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN];
89 }
90
43 static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v, 91 static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v,
44 uint8_t* const rgb) { 92 uint8_t* const rgb) {
45 const int r_off = VP8kVToR[v]; 93 const int r_off = VP8kVToR[v];
46 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 94 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
47 const int b_off = VP8kUToB[u]; 95 const int b_off = VP8kUToB[u];
48 rgb[0] = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) | 96 const uint8_t rg = ((VP8kClip[y + r_off - YUV_RANGE_MIN] & 0xf8) |
49 (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5)); 97 (VP8kClip[y + g_off - YUV_RANGE_MIN] >> 5));
50 rgb[1] = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) | 98 const uint8_t gb = (((VP8kClip[y + g_off - YUV_RANGE_MIN] << 3) & 0xe0) |
51 (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3)); 99 (VP8kClip[y + b_off - YUV_RANGE_MIN] >> 3));
52 } 100 #ifdef WEBP_SWAP_16BIT_CSP
53 101 rgb[0] = gb;
54 static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v, 102 rgb[1] = rg;
55 uint8_t* const argb) { 103 #else
56 argb[0] = 0xff; 104 rgb[0] = rg;
57 VP8YuvToRgb(y, u, v, argb + 1); 105 rgb[1] = gb;
106 #endif
58 } 107 }
59 108
60 static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v, 109 static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v,
61 uint8_t* const argb) { 110 uint8_t* const argb) {
62 const int r_off = VP8kVToR[v]; 111 const int r_off = VP8kVToR[v];
63 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 112 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX;
64 const int b_off = VP8kUToB[u]; 113 const int b_off = VP8kUToB[u];
65 // Don't update alpha (last 4 bits of argb[1]) 114 const uint8_t rg = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) |
66 argb[0] = ((VP8kClip4Bits[y + r_off - YUV_RANGE_MIN] << 4) | 115 VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]);
67 VP8kClip4Bits[y + g_off - YUV_RANGE_MIN]); 116 const uint8_t ba = (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4) | 0x0f;
68 argb[1] = 0x0f | (VP8kClip4Bits[y + b_off - YUV_RANGE_MIN] << 4); 117 #ifdef WEBP_SWAP_16BIT_CSP
118 argb[0] = ba;
119 argb[1] = rg;
120 #else
121 argb[0] = rg;
122 argb[1] = ba;
123 #endif
124 }
125
126 #else // Table-free version (slower on x86)
127
128 // These constants are 16b fixed-point version of ITU-R BT.601 constants
129 #define kYScale 76309 // 1.164 = 255 / 219
130 #define kVToR 104597 // 1.596 = 255 / 112 * 0.701
131 #define kUToG 25674 // 0.391 = 255 / 112 * 0.886 * 0.114 / 0.587
132 #define kVToG 53278 // 0.813 = 255 / 112 * 0.701 * 0.299 / 0.587
133 #define kUToB 132201 // 2.018 = 255 / 112 * 0.886
134 #define kRCst (-kYScale * 16 - kVToR * 128 + YUV_HALF)
135 #define kGCst (-kYScale * 16 + kUToG * 128 + kVToG * 128 + YUV_HALF)
136 #define kBCst (-kYScale * 16 - kUToB * 128 + YUV_HALF)
137
138 static WEBP_INLINE uint8_t VP8Clip8(int v) {
139 return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> YUV_FIX)
140 : (v < 0) ? 0u : 255u;
141 }
142
143 static WEBP_INLINE uint8_t VP8ClipN(int v, int N) { // clip to N bits
144 return ((v & ~YUV_MASK) == 0) ? (uint8_t)(v >> (YUV_FIX + (8 - N)))
145 : (v < 0) ? 0u : (255u >> (8 - N));
146 }
147
148 static WEBP_INLINE int VP8YUVToR(int y, int v) {
149 return kYScale * y + kVToR * v + kRCst;
150 }
151
152 static WEBP_INLINE int VP8YUVToG(int y, int u, int v) {
153 return kYScale * y - kUToG * u - kVToG * v + kGCst;
154 }
155
156 static WEBP_INLINE int VP8YUVToB(int y, int u) {
157 return kYScale * y + kUToB * u + kBCst;
158 }
159
160 static WEBP_INLINE void VP8YuvToRgb(uint8_t y, uint8_t u, uint8_t v,
161 uint8_t* const rgb) {
162 rgb[0] = VP8Clip8(VP8YUVToR(y, v));
163 rgb[1] = VP8Clip8(VP8YUVToG(y, u, v));
164 rgb[2] = VP8Clip8(VP8YUVToB(y, u));
69 } 165 }
70 166
71 static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v, 167 static WEBP_INLINE void VP8YuvToBgr(uint8_t y, uint8_t u, uint8_t v,
72 uint8_t* const bgr) { 168 uint8_t* const bgr) {
73 const int r_off = VP8kVToR[v]; 169 bgr[0] = VP8Clip8(VP8YUVToB(y, u));
74 const int g_off = (VP8kVToG[v] + VP8kUToG[u]) >> YUV_FIX; 170 bgr[1] = VP8Clip8(VP8YUVToG(y, u, v));
75 const int b_off = VP8kUToB[u]; 171 bgr[2] = VP8Clip8(VP8YUVToR(y, v));
76 bgr[0] = VP8kClip[y + b_off - YUV_RANGE_MIN]; 172 }
77 bgr[1] = VP8kClip[y + g_off - YUV_RANGE_MIN]; 173
78 bgr[2] = VP8kClip[y + r_off - YUV_RANGE_MIN]; 174 static WEBP_INLINE void VP8YuvToRgb565(uint8_t y, uint8_t u, uint8_t v,
175 uint8_t* const rgb) {
176 const int r = VP8Clip8(VP8YUVToR(y, u));
177 const int g = VP8ClipN(VP8YUVToG(y, u, v), 6);
178 const int b = VP8ClipN(VP8YUVToB(y, v), 5);
179 const uint8_t rg = (r & 0xf8) | (g >> 3);
180 const uint8_t gb = (g << 5) | b;
181 #ifdef WEBP_SWAP_16BIT_CSP
182 rgb[0] = gb;
183 rgb[1] = rg;
184 #else
185 rgb[0] = rg;
186 rgb[1] = gb;
187 #endif
188 }
189
190 static WEBP_INLINE void VP8YuvToRgba4444(uint8_t y, uint8_t u, uint8_t v,
191 uint8_t* const argb) {
192 const int r = VP8Clip8(VP8YUVToR(y, u));
193 const int g = VP8ClipN(VP8YUVToG(y, u, v), 4);
194 const int b = VP8Clip8(VP8YUVToB(y, v));
195 const uint8_t rg = (r & 0xf0) | g;
196 const uint8_t ba = b | 0x0f; // overwrite the lower 4 bits
197 #ifdef WEBP_SWAP_16BIT_CSP
198 argb[0] = ba;
199 argb[1] = rg;
200 #else
201 argb[0] = rg;
202 argb[1] = ba;
203 #endif
204 }
205
206 #endif // WEBP_YUV_USE_TABLE
207
208 static WEBP_INLINE void VP8YuvToArgb(uint8_t y, uint8_t u, uint8_t v,
209 uint8_t* const argb) {
210 argb[0] = 0xff;
211 VP8YuvToRgb(y, u, v, argb + 1);
79 } 212 }
80 213
81 static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v, 214 static WEBP_INLINE void VP8YuvToBgra(uint8_t y, uint8_t u, uint8_t v,
82 uint8_t* const bgra) { 215 uint8_t* const bgra) {
83 VP8YuvToBgr(y, u, v, bgra); 216 VP8YuvToBgr(y, u, v, bgra);
84 bgra[3] = 0xff; 217 bgra[3] = 0xff;
85 } 218 }
86 219
87 static WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v, 220 static WEBP_INLINE void VP8YuvToRgba(uint8_t y, uint8_t u, uint8_t v,
88 uint8_t* const rgba) { 221 uint8_t* const rgba) {
89 VP8YuvToRgb(y, u, v, rgba); 222 VP8YuvToRgb(y, u, v, rgba);
90 rgba[3] = 0xff; 223 rgba[3] = 0xff;
91 } 224 }
92 225
93 static WEBP_INLINE uint32_t VP8Clip4Bits(uint8_t c) {
94 const uint32_t v = (c + 8) >> 4;
95 return (v > 15) ? 15 : v;
96 }
97
98 // Must be called before everything, to initialize the tables. 226 // Must be called before everything, to initialize the tables.
99 void VP8YUVInit(void); 227 void VP8YUVInit(void);
100 228
101 //------------------------------------------------------------------------------ 229 //------------------------------------------------------------------------------
102 // RGB -> YUV conversion 230 // RGB -> YUV conversion
103 // The exact naming is Y'CbCr, following the ITU-R BT.601 standard.
104 // More information at: http://en.wikipedia.org/wiki/YCbCr
105 // Y = 0.2569 * R + 0.5044 * G + 0.0979 * B + 16
106 // U = -0.1483 * R - 0.2911 * G + 0.4394 * B + 128
107 // V = 0.4394 * R - 0.3679 * G - 0.0715 * B + 128
108 // We use 16bit fixed point operations.
109 231
110 static WEBP_INLINE int VP8ClipUV(int v) { 232 static WEBP_INLINE int VP8ClipUV(int v) {
111 v = (v + (257 << (YUV_FIX + 2 - 1))) >> (YUV_FIX + 2); 233 v = (v + (257 << (YUV_FIX + 2 - 1))) >> (YUV_FIX + 2);
112 return ((v & ~0xff) == 0) ? v : (v < 0) ? 0 : 255; 234 return ((v & ~0xff) == 0) ? v : (v < 0) ? 0 : 255;
113 } 235 }
114 236
237 #ifndef USE_YUVj
238
115 static WEBP_INLINE int VP8RGBToY(int r, int g, int b) { 239 static WEBP_INLINE int VP8RGBToY(int r, int g, int b) {
116 const int kRound = (1 << (YUV_FIX - 1)) + (16 << YUV_FIX); 240 const int kRound = (1 << (YUV_FIX - 1)) + (16 << YUV_FIX);
117 const int luma = 16839 * r + 33059 * g + 6420 * b; 241 const int luma = 16839 * r + 33059 * g + 6420 * b;
118 return (luma + kRound) >> YUV_FIX; // no need to clip 242 return (luma + kRound) >> YUV_FIX; // no need to clip
119 } 243 }
120 244
121 static WEBP_INLINE int VP8RGBToU(int r, int g, int b) { 245 static WEBP_INLINE int VP8RGBToU(int r, int g, int b) {
122 return VP8ClipUV(-9719 * r - 19081 * g + 28800 * b); 246 const int u = -9719 * r - 19081 * g + 28800 * b;
247 return VP8ClipUV(u);
123 } 248 }
124 249
125 static WEBP_INLINE int VP8RGBToV(int r, int g, int b) { 250 static WEBP_INLINE int VP8RGBToV(int r, int g, int b) {
126 return VP8ClipUV(+28800 * r - 24116 * g - 4684 * b); 251 const int v = +28800 * r - 24116 * g - 4684 * b;
252 return VP8ClipUV(v);
127 } 253 }
128 254
255 #else
256
257 // This JPEG-YUV colorspace, only for comparison!
258 // These are also 16-bit precision coefficients from Rec.601, but with full
259 // [0..255] output range.
260 static WEBP_INLINE int VP8RGBToY(int r, int g, int b) {
261 const int kRound = (1 << (YUV_FIX - 1));
262 const int luma = 19595 * r + 38470 * g + 7471 * b;
263 return (luma + kRound) >> YUV_FIX; // no need to clip
264 }
265
266 static WEBP_INLINE int VP8RGBToU(int r, int g, int b) {
267 const int u = -11058 * r - 21710 * g + 32768 * b;
268 return VP8ClipUV(u);
269 }
270
271 static WEBP_INLINE int VP8RGBToV(int r, int g, int b) {
272 const int v = 32768 * r - 27439 * g - 5329 * b;
273 return VP8ClipUV(v);
274 }
275
276 #endif // USE_YUVj
277
129 #if defined(__cplusplus) || defined(c_plusplus) 278 #if defined(__cplusplus) || defined(c_plusplus)
130 } // extern "C" 279 } // extern "C"
131 #endif 280 #endif
132 281
133 #endif /* WEBP_DSP_YUV_H_ */ 282 #endif /* WEBP_DSP_YUV_H_ */
OLDNEW
« no previous file with comments | « third_party/libwebp/dsp/upsampling_sse2.c ('k') | third_party/libwebp/dsp/yuv.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698