Increase ParseScript cache from 30 to 90 seconds
[xy_vsfilter.git] / src / subpic / color_conv_table.cpp
blob8a5bcd638c8913547f73249f975ef42b44d03f6c
1 #include "stdafx.h"
2 #include "color_conv_table.h"
3 #include <string.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;\
37 u = clip(u, 255); \
38 v = clip(v, 255); \
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;\
55 b = clip(b, 255); \
56 g = clip(g, 255); \
57 r = clip(r, 255); \
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;\
78 u = clip(u, 255); \
79 v = clip(v, 255); \
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;
125 class ConvFunc
127 public:
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)
150 bool result = true;
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;
161 _range_type = range;
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;
172 _range_type = range;
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;
183 _range_type = range;
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;
194 _range_type = range;
196 else
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;
208 return result;
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;
330 struct YuvPos
332 int y;
333 int u;
334 int v;
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)