2 #include "color_conv_table.h"
5 const int FRACTION_BITS
= 16;
6 const int FRACTION_SCALE
= 1<<16;
8 const int TV_Y_RANGE
= 219;
9 const int TV_Y_MIN
= 16;
11 const int PC_Y_RANGE
= 255;
12 const int PC_Y_MIN
= 0;
14 inline int clip(int value
, int upper_bound
)
16 value
&= ~(value
>>31);//value = value > 0 ? value : 0
17 return value
^((value
^upper_bound
)&((upper_bound
-value
)>>31));//value = value < upper_bound ? value : upper_bound
20 #define FLOAT_TO_FIXED(f, SCALE) int((f)*(SCALE)+0.5)
22 #define DEFINE_RGB2YUV_FUNC(func, Y_RANGE_LOWER, Y_RANGE, double_cyb, double_cyg, double_cyr, double_cu, double_cv, YUV_POS) \
23 DWORD func(int r8, int g8, int b8)\
25 const int c2y_cyb = int(double_cyb*Y_RANGE/255*FRACTION_SCALE+0.5);\
26 const int c2y_cyg = int(double_cyg*Y_RANGE/255*FRACTION_SCALE+0.5);\
27 const int c2y_cyr = int(double_cyr*Y_RANGE/255*FRACTION_SCALE+0.5);\
28 const int c2y_cu = int(1.0/double_cu*1024+0.5);/*Fix me: BT.601 uv range should be 16~240? */\
29 const int c2y_cv = int(1.0/double_cv*1024+0.5);\
30 const int cy_cy = int(255.0/Y_RANGE*FRACTION_SCALE+0.5);\
32 int y = (c2y_cyr*r8 + c2y_cyg*g8 + c2y_cyb*b8 + Y_RANGE_LOWER*FRACTION_SCALE + FRACTION_SCALE/2) >> FRACTION_BITS;\
33 int scaled_y = (y-Y_RANGE_LOWER) * cy_cy;\
34 int u = ((((b8<<FRACTION_BITS) - scaled_y) >> 10) * c2y_cu + 128*FRACTION_SCALE + FRACTION_SCALE/2) >> FRACTION_BITS;\
35 int v = ((((r8<<FRACTION_BITS) - scaled_y) >> 10) * c2y_cv + 128*FRACTION_SCALE + FRACTION_SCALE/2) >> FRACTION_BITS;\
39 return (y<<YUV_POS.y) | (u<<YUV_POS.u) | (v<<YUV_POS.v);\
42 #define DEFINE_YUV2RGB_FUNC(func, Y_RANGE_LOWER, Y_RANGE, double_BU, double_GU, double_GV, double_RV) \
43 DWORD func(int y, int u, int v)\
45 const int y2c_cbu = int(double_BU*FRACTION_SCALE+0.5);\
46 const int y2c_cgu = int(double_GU*FRACTION_SCALE+0.5);\
47 const int y2c_cgv = int(double_GV*FRACTION_SCALE+0.5);\
48 const int y2c_crv = int(double_RV*FRACTION_SCALE+0.5);\
49 const int cy_cy = int(255.0/Y_RANGE*FRACTION_SCALE+0.5);\
51 int scaled_y = (y - Y_RANGE_LOWER) * cy_cy;\
52 int b = (scaled_y + y2c_cbu*(u-128) + FRACTION_SCALE/2) >> FRACTION_BITS;\
53 int g = (scaled_y - y2c_cgu*(u-128) - y2c_cgv*(v-128) + FRACTION_SCALE/2) >> FRACTION_BITS;\
54 int r = (scaled_y + y2c_crv*(v-128) + FRACTION_SCALE/2) >> FRACTION_BITS;\
58 return (r<<16) | (g<<8) | b;\
61 #define DEFINE_PREMUL_ARGB2AYUV_FUNC(func, Y_RANGE_LOWER, Y_RANGE, double_cyb, double_cyg, double_cyr, double_cu, double_cv, YUV_POS) \
62 DWORD func(int a8, int r8, int g8, int b8)\
64 const int c2y_cyb = int(double_cyb*Y_RANGE/255*FRACTION_SCALE+0.5);\
65 const int c2y_cyg = int(double_cyg*Y_RANGE/255*FRACTION_SCALE+0.5);\
66 const int c2y_cyr = int(double_cyr*Y_RANGE/255*FRACTION_SCALE+0.5);\
67 const int c2y_cu = int(1.0/double_cu*1024+0.5);\
68 const int c2y_cv = int(1.0/double_cv*1024+0.5);\
69 const int cy_cy = int(255.0/Y_RANGE*FRACTION_SCALE+0.5);\
71 int a = (256-a8)<<(FRACTION_BITS-8);\
72 int tmp = c2y_cyr*r8 + c2y_cyg*g8 + c2y_cyb*b8 + FRACTION_SCALE/2;\
73 int y = (tmp + a*Y_RANGE_LOWER) >> FRACTION_BITS;\
74 int scaled_y = (tmp>>FRACTION_BITS) * cy_cy;\
75 int u = ((((b8<<FRACTION_BITS) - scaled_y) >> 10) * c2y_cu + a*128 + FRACTION_SCALE/2) >> FRACTION_BITS;\
76 int v = ((((r8<<FRACTION_BITS) - scaled_y) >> 10) * c2y_cv + a*128 + FRACTION_SCALE/2) >> FRACTION_BITS;\
80 return (a8<<24) | (y<<YUV_POS.y) | (u<<YUV_POS.u) | (v<<YUV_POS.v);\
83 #define DEFINE_RGB2Y_FUNC(func, Y_RANGE_LOWER, Y_RANGE, double_cyb, double_cyg, double_cyr, double_cu, double_cv) \
84 DWORD func(int r8, int g8, int b8)\
86 const int c2y_cyb = int(double_cyb*Y_RANGE/255*FRACTION_SCALE+0.5);\
87 const int c2y_cyg = int(double_cyg*Y_RANGE/255*FRACTION_SCALE+0.5);\
88 const int c2y_cyr = int(double_cyr*Y_RANGE/255*FRACTION_SCALE+0.5);\
89 const int c2y_cu = int(1.0/double_cu*1024+0.5);\
90 const int c2y_cv = int(1.0/double_cv*1024+0.5);\
91 const int cy_cy = int(255.0/Y_RANGE*FRACTION_SCALE+0.5);\
93 return (c2y_cyr*r8 + c2y_cyg*g8 + c2y_cyb*b8 + Y_RANGE_LOWER*FRACTION_SCALE + FRACTION_SCALE/2) >> FRACTION_BITS;\
97 DWORD
RGBToYUV_TV_BT601(int r8
, int g8
, int b8
);
98 DWORD
RGBToYUV_PC_BT601(int r8
, int g8
, int b8
);
99 DWORD
RGBToYUV_TV_BT709(int r8
, int g8
, int b8
);
100 DWORD
RGBToYUV_PC_BT709(int r8
, int g8
, int b8
);
102 DWORD
RGBToUYV_TV_BT601(int r8
, int g8
, int b8
);
103 DWORD
RGBToUYV_PC_BT601(int r8
, int g8
, int b8
);
104 DWORD
RGBToUYV_TV_BT709(int r8
, int g8
, int b8
);
105 DWORD
RGBToUYV_PC_BT709(int r8
, int g8
, int b8
);
107 DWORD
PREMUL_ARGB2AYUV_TV_BT601(int a8
, int r8
, int g8
, int b8
);
108 DWORD
PREMUL_ARGB2AYUV_PC_BT601(int a8
, int r8
, int g8
, int b8
);
109 DWORD
PREMUL_ARGB2AYUV_TV_BT709(int a8
, int r8
, int g8
, int b8
);
110 DWORD
PREMUL_ARGB2AYUV_PC_BT709(int a8
, int r8
, int g8
, int b8
);
112 DWORD
RGBToY_TV_BT601(int r8
, int g8
, int b8
);
113 DWORD
RGBToY_PC_BT601(int r8
, int g8
, int b8
);
114 DWORD
RGBToY_TV_BT709(int r8
, int g8
, int b8
);
115 DWORD
RGBToY_PC_BT709(int r8
, int g8
, int b8
);
117 DWORD
YUVToRGB_TV_BT601(int y
, int u
, int v
);
118 DWORD
YUVToRGB_PC_BT601(int y
, int u
, int v
);
119 DWORD
YUVToRGB_TV_BT709(int y
, int u
, int v
);
120 DWORD
YUVToRGB_PC_BT709(int y
, int u
, int v
);
122 typedef ColorConvTable::YuvMatrixType YuvMatrixType
;
123 typedef ColorConvTable::YuvRangeType YuvRangeType
;
128 ConvFunc(YuvMatrixType yuv_type
, YuvRangeType range
){ InitConvFunc(yuv_type
, range
); }
129 bool InitConvFunc(YuvMatrixType yuv_type
, YuvRangeType range
);
131 typedef DWORD (*R8G8B8ToYuvFunc
)(int r8
, int g8
, int b8
);
132 typedef DWORD (*PreMulArgbToAyuvFunc
)(int a8
, int r8
, int g8
, int b8
);
133 typedef R8G8B8ToYuvFunc R8G8B8ToY
;
134 typedef R8G8B8ToYuvFunc Y8U8V8ToRGBFunc
;
136 R8G8B8ToYuvFunc r8g8b8_to_yuv_func
;
137 R8G8B8ToYuvFunc r8g8b8_to_uyv_func
;
138 PreMulArgbToAyuvFunc pre_mul_argb_to_ayuv_func
;
139 R8G8B8ToY r8g8b8_to_y_func
;
140 Y8U8V8ToRGBFunc y8u8v8_to_rgb_func
;
142 YuvMatrixType _yuv_type
;
143 YuvRangeType _range_type
;
146 ConvFunc
s_default_conv_set(ColorConvTable::BT601
, ColorConvTable::RANGE_TV
);
148 bool ConvFunc::InitConvFunc(YuvMatrixType yuv_type
, YuvRangeType range
)
152 if ( yuv_type
==ColorConvTable::BT601
&& range
==ColorConvTable::RANGE_TV
)
154 r8g8b8_to_yuv_func
= RGBToYUV_TV_BT601
;
155 r8g8b8_to_uyv_func
= RGBToUYV_TV_BT601
;
156 pre_mul_argb_to_ayuv_func
= PREMUL_ARGB2AYUV_TV_BT601
;
157 r8g8b8_to_y_func
= RGBToY_TV_BT601
;
158 y8u8v8_to_rgb_func
= YUVToRGB_TV_BT601
;
160 _yuv_type
= yuv_type
;
163 else if ( yuv_type
==ColorConvTable::BT709
&& range
==ColorConvTable::RANGE_TV
)
165 r8g8b8_to_yuv_func
= RGBToYUV_TV_BT709
;
166 r8g8b8_to_uyv_func
= RGBToUYV_TV_BT709
;
167 pre_mul_argb_to_ayuv_func
= PREMUL_ARGB2AYUV_TV_BT709
;
168 r8g8b8_to_y_func
= RGBToY_TV_BT709
;
169 y8u8v8_to_rgb_func
= YUVToRGB_TV_BT709
;
171 _yuv_type
= yuv_type
;
174 else if ( yuv_type
==ColorConvTable::BT601
&& range
==ColorConvTable::RANGE_PC
)
176 r8g8b8_to_yuv_func
= RGBToYUV_PC_BT601
;
177 r8g8b8_to_uyv_func
= RGBToUYV_PC_BT601
;
178 pre_mul_argb_to_ayuv_func
= PREMUL_ARGB2AYUV_PC_BT601
;
179 r8g8b8_to_y_func
= RGBToY_PC_BT601
;
180 y8u8v8_to_rgb_func
= YUVToRGB_PC_BT601
;
182 _yuv_type
= yuv_type
;
185 else if ( yuv_type
==ColorConvTable::BT709
&& range
==ColorConvTable::RANGE_PC
)
187 r8g8b8_to_yuv_func
= RGBToYUV_PC_BT709
;
188 r8g8b8_to_uyv_func
= RGBToUYV_PC_BT709
;
189 pre_mul_argb_to_ayuv_func
= PREMUL_ARGB2AYUV_PC_BT709
;
190 r8g8b8_to_y_func
= RGBToY_PC_BT709
;
191 y8u8v8_to_rgb_func
= YUVToRGB_PC_BT709
;
193 _yuv_type
= yuv_type
;
198 r8g8b8_to_yuv_func
= RGBToYUV_TV_BT601
;
199 r8g8b8_to_uyv_func
= RGBToUYV_TV_BT601
;
200 pre_mul_argb_to_ayuv_func
= PREMUL_ARGB2AYUV_TV_BT601
;
201 r8g8b8_to_y_func
= RGBToY_TV_BT601
;
202 y8u8v8_to_rgb_func
= YUVToRGB_TV_BT601
;
204 _yuv_type
= ColorConvTable::BT601
;
205 _range_type
= ColorConvTable::RANGE_TV
;
211 ColorConvTable::YuvMatrixType
ColorConvTable::GetDefaultYUVType()
213 return s_default_conv_set
._yuv_type
;
216 ColorConvTable::YuvRangeType
ColorConvTable::GetDefaultRangeType()
218 return s_default_conv_set
._range_type
;
221 void ColorConvTable::SetDefaultConvType( YuvMatrixType yuv_type
, YuvRangeType range
)
223 if( s_default_conv_set
._yuv_type
!= yuv_type
|| s_default_conv_set
._range_type
!= range
)
225 s_default_conv_set
.InitConvFunc(yuv_type
, range
);
229 DWORD
ColorConvTable::Argb2Auyv( DWORD argb
)
231 int r
= (argb
& 0x00ff0000) >> 16;
232 int g
= (argb
& 0x0000ff00) >> 8;
233 int b
= (argb
& 0x000000ff);
234 return (argb
& 0xff000000) | s_default_conv_set
.r8g8b8_to_uyv_func(r
, g
, b
);
237 DWORD
ColorConvTable::Argb2Ayuv( DWORD argb
)
239 int r
= (argb
& 0x00ff0000) >> 16;
240 int g
= (argb
& 0x0000ff00) >> 8;
241 int b
= (argb
& 0x000000ff);
242 return (argb
& 0xff000000) | s_default_conv_set
.r8g8b8_to_yuv_func(r
, g
, b
);
245 DWORD
ColorConvTable::Ayuv2Auyv( DWORD ayuv
)
247 int y
= (ayuv
& 0x00ff0000) >> 8;
248 int u
= (ayuv
& 0x0000ff00) << 8;
249 return (ayuv
& 0xff0000ff)| u
| y
;
252 DWORD
ColorConvTable::PreMulArgb2Ayuv( int a8
, int r8
, int g8
, int b8
)
254 return s_default_conv_set
.pre_mul_argb_to_ayuv_func(a8
, r8
, g8
, b8
);
257 DWORD
ColorConvTable::Rgb2Y( int r8
, int g8
, int b8
)
259 return s_default_conv_set
.r8g8b8_to_y_func(r8
, g8
, b8
);
262 DWORD
ColorConvTable::Ayuv2Argb_TV_BT601( DWORD ayuv
)
264 int y
= (ayuv
& 0x00ff0000) >> 16;
265 int u
= (ayuv
& 0x0000ff00) >> 8;
266 int v
= (ayuv
& 0x000000ff);
267 return (ayuv
& 0xff000000) | YUVToRGB_TV_BT601(y
, u
, v
);
270 DWORD
ColorConvTable::Ayuv2Argb_TV_BT709( DWORD ayuv
)
272 int y
= (ayuv
& 0x00ff0000) >> 16;
273 int u
= (ayuv
& 0x0000ff00) >> 8;
274 int v
= (ayuv
& 0x000000ff);
275 return (ayuv
& 0xff000000) | YUVToRGB_TV_BT709(y
, u
, v
);
278 DWORD
ColorConvTable::Ayuv2Argb( DWORD ayuv
)
280 int y
= (ayuv
& 0x00ff0000) >> 16;
281 int u
= (ayuv
& 0x0000ff00) >> 8;
282 int v
= (ayuv
& 0x000000ff);
283 return (ayuv
& 0xff000000) | s_default_conv_set
.y8u8v8_to_rgb_func(y
, u
, v
);
286 DWORD
ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT601( int a8
, int y8
, int u8
, int v8
)
288 return (a8
<<24) | YUVToRGB_TV_BT601(y8
, u8
, v8
);
291 DWORD
ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT601( int a8
, int y8
, int u8
, int v8
)
293 return (a8
<<24) | YUVToRGB_PC_BT601(y8
, u8
, v8
);
296 DWORD
ColorConvTable::A8Y8U8V8_To_ARGB_TV_BT709( int a8
, int y8
, int u8
, int v8
)
298 return (a8
<<24) | YUVToRGB_TV_BT709(y8
, u8
, v8
);
301 DWORD
ColorConvTable::A8Y8U8V8_To_ARGB_PC_BT709( int a8
, int y8
, int u8
, int v8
)
303 return (a8
<<24) | YUVToRGB_PC_BT709(y8
, u8
, v8
);
306 DWORD
ColorConvTable::A8Y8U8V8_PC_To_TV( int a8
, int y8
, int u8
, int v8
)
308 const int FRACTION_SCALE
= 1<<16;
309 const int YUV_MIN
= 16;
310 const int cy
= int(219.0/255*FRACTION_SCALE
+0.5);
311 const int cuv
= int(224.0/255*FRACTION_SCALE
+0.5);/*Fixme: the RGBToYUVs we used doesnot seem to stretch chroma correctly*/
312 y8
= ((y8
*cy
)>>16) + YUV_MIN
;
313 u8
= ((u8
*cuv
)>>16) + YUV_MIN
;
314 v8
= ((v8
*cuv
)>>16) + YUV_MIN
;
315 return (a8
<<24) | (y8
<<16) | (u8
<<8) | v8
;
318 DWORD
ColorConvTable::A8Y8U8V8_TV_To_PC( int a8
, int y8
, int u8
, int v8
)
320 const int FRACTION_SCALE
= 1<<16;
321 const int YUV_MIN
= 16;
322 const int cy
= int(255/219.0*FRACTION_SCALE
+0.5);
323 const int cuv
= int(255/224.0*FRACTION_SCALE
+0.5);/*Fixme: the RGBToYUVs we used doesnot seem to stretch chroma correctly*/
324 y8
= ((y8
-YUV_MIN
)*cy
)>>16;
325 u8
= ((u8
-YUV_MIN
)*cuv
)>>16;
326 v8
= ((v8
-YUV_MIN
)*cuv
)>>16;
327 return (a8
<<24) | (y8
<<16) | (u8
<<8) | v8
;
336 const YuvPos POS_YUV
= {16, 8, 0};
337 const YuvPos POS_UYV
= {8, 16, 0};
340 DEFINE_RGB2YUV_FUNC(RGBToYUV_TV_BT601
, 16, 219, 0.114, 0.587, 0.299, 2.018, 1.596, POS_YUV
)
341 DEFINE_RGB2YUV_FUNC(RGBToYUV_PC_BT601
, 0, 255, 0.114, 0.587, 0.299, 2.018, 1.596, POS_YUV
)
342 DEFINE_RGB2YUV_FUNC(RGBToYUV_TV_BT709
, 16, 219, 0.0722, 0.7152, 0.2126, 2.113, 1.793, POS_YUV
)
343 DEFINE_RGB2YUV_FUNC(RGBToYUV_PC_BT709
, 0, 255, 0.0722, 0.7152, 0.2126, 2.113, 1.793, POS_YUV
)
346 DEFINE_RGB2YUV_FUNC(RGBToUYV_TV_BT601
, 16, 219, 0.114, 0.587, 0.299, 2.018, 1.596, POS_UYV
)
347 DEFINE_RGB2YUV_FUNC(RGBToUYV_PC_BT601
, 0, 255, 0.114, 0.587, 0.299, 2.018, 1.596, POS_UYV
)
348 DEFINE_RGB2YUV_FUNC(RGBToUYV_TV_BT709
, 16, 219, 0.0722, 0.7152, 0.2126, 2.113, 1.793, POS_UYV
)
349 DEFINE_RGB2YUV_FUNC(RGBToUYV_PC_BT709
, 0, 255, 0.0722, 0.7152, 0.2126, 2.113, 1.793, POS_UYV
)
352 DEFINE_YUV2RGB_FUNC(YUVToRGB_TV_BT601
, 16, 219, 2.018, 0.391, 0.813, 1.596)
353 DEFINE_YUV2RGB_FUNC(YUVToRGB_PC_BT601
, 0, 255, 2.018, 0.391, 0.813, 1.596)
354 DEFINE_YUV2RGB_FUNC(YUVToRGB_TV_BT709
, 16, 219, 2.113, 0.213, 0.533, 1.793)
355 DEFINE_YUV2RGB_FUNC(YUVToRGB_PC_BT709
, 0, 255, 2.113, 0.213, 0.533, 1.793)
358 DEFINE_PREMUL_ARGB2AYUV_FUNC(PREMUL_ARGB2AYUV_TV_BT601
, 16, 219, 0.114, 0.587, 0.299, 2.018, 1.596, POS_YUV
)
359 DEFINE_PREMUL_ARGB2AYUV_FUNC(PREMUL_ARGB2AYUV_PC_BT601
, 0, 255, 0.114, 0.587, 0.299, 2.018, 1.596, POS_YUV
)
360 DEFINE_PREMUL_ARGB2AYUV_FUNC(PREMUL_ARGB2AYUV_TV_BT709
, 16, 219, 0.0722, 0.7152, 0.2126, 2.113, 1.793, POS_YUV
)
361 DEFINE_PREMUL_ARGB2AYUV_FUNC(PREMUL_ARGB2AYUV_PC_BT709
, 0, 255, 0.0722, 0.7152, 0.2126, 2.113, 1.793, POS_YUV
)
364 DEFINE_RGB2Y_FUNC(RGBToY_TV_BT601
, 16, 219, 0.114, 0.587, 0.299, 2.018, 1.596)
365 DEFINE_RGB2Y_FUNC(RGBToY_PC_BT601
, 0, 255, 0.114, 0.587, 0.299, 2.018, 1.596)
366 DEFINE_RGB2Y_FUNC(RGBToY_TV_BT709
, 16, 219, 0.0722, 0.7152, 0.2126, 2.113, 1.793)
367 DEFINE_RGB2Y_FUNC(RGBToY_PC_BT709
, 0, 255, 0.0722, 0.7152, 0.2126, 2.113, 1.793)