4 * Copyright (C) 1997-2011 Adam Williams <broadcast at earthling dot net>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #ifndef __BCCOLORS_H__
23 #define __BCCOLORS_H__
25 // Duplicate filename in guicast
27 #include "bccolors.inc"
36 Digital YCbCr is derived from analog RGB as follows:
37 RGB are 0..1 (gamma corrected supposedly),
39 Y Py = Kr * R + Kg * G + Kb * B
40 U Pb = - 0.5*Kr/(1-Kb)*R - 0.5*Kg/(1-Kb)*G + 0.5*B
41 V Pr = 0.5*R - 0.5*Kg/(1-Kr)*G - 0.5*Kb/(1-Kr)*B
43 R = Py + Pr * 2*(1-Kr)
44 G = Py - Pr * 2*Kr*(1-Kr)/Kg - Pb * 2*Kb*(1-Kb)/Kg
45 B = Py + Pb * 2*(1-Kb)
47 bt601, white vector= Kr=0.299,Kg=0.587,Kb=0.114
48 Py = + 0.299000*R + 0.587000*G + 0.114000*B
49 Pb = - 0.168736*R - 0.331264*G + 0.500000*B
50 Pr = + 0.500000*R - 0.418698*G - 0.081312*B
53 G = Py - 0.714136*Pr - 0.344136*Pb
56 equations zeroed at (0,128,128), range (255,255,255)
58 Y = 0 + 0.299000*R + 0.587000*G + 0.114000*B
59 Cb = 128 - 0.168736*R - 0.331264*G + 0.500000*B
60 Cr = 128 + 0.500000*R - 0.418698*G - 0.081312*B
62 R = Y + 1.402000*(Cr-128)
63 G = Y - 0.714136*(Cr-128) - 0.344136*(Cb-128)
64 B = Y + 1.772000*(Cb-128)
66 equations zeroed at (16,128,128), range (219,224,224)
67 Y,Cb,Cr = (16,128,128) + (219*Py,224*Pb,224*Pr)
70 Y = 16 + 0.256788*R + 0.504129*G + 0.097906*B
71 Cb = 128 - 0.148227*R - 0.290992*G + 0.439216*B
72 Cr = 128 + 0.439216*R - 0.367789*G - 0.071426*B
74 R = (Y-16)*1.164384 + 1.596027*(Cr-128)
75 G = (Y-16)*1.164384 - 0.812968*(Cr-128) - 0.391762*(Cb-128)
76 B = (Y-16)*1.164384 + 2.017232*(Cb-128)
78 bt.709, white vector= Kr=0.2126,Kg=0.7152,Kb=0.0722
79 Py = + 0.212600*R + 0.715200*G + 0.072200*B
80 Pb = - 0.114572*R - 0.385428*G + 0.500000*B
81 Pr = + 0.500000*R - 0.454153*G - 0.045847*B
83 equations zeroed at (0,128,128), range (255,255,255)
85 Y = 0 + 0.212600*R + 0.715200*G + 0.072200*B
86 Cb = 128 - 0.114572*R - 0.385428*G + 0.500000*B
87 Cr = 128 + 0.500000*R - 0.454153*G - 0.045847*B
89 R = Y + 1.574800*(Cr-128)
90 G = Y - 0.468124*(Cr-128) - 0.187324*(Cb-128)
91 B = Y + 1.855600*(Cb-128)
93 equations zeroed at (16,128,128), range (219,224,224)
94 Y,Cb,Cr = (16,128,128) + (219*Py,224*Pb,224*Pr)
95 Y = 16 + 0.182586*R + 0.614231*G + 0.062007*B
96 Cb = 128 - 0.100644*R - 0.338572*G + 0.439216*B
97 Cr = 128 + 0.439216*R - 0.398942*G - 0.040276*B
99 R = (Y-16)*1.164384 + 1.792741*(Cr-128)
100 G = (Y-16)*1.164384 - 0.532909*(Cr-128) - 0.213249*(Cb-128)
101 B = (Y-16)*1.164384 + 2.112402*(Cb-128)
104 // white vector normalized, so:
107 #define BT601_NTSC_Kr 0.299
108 #define BT601_NTSC_Kb 0.114
110 #define BT601_PAL_Kr 0.299
111 #define BT601_PAL_Kb 0.114
113 #define BT709_Kr 0.2126
114 #define BT709_Kb 0.0722
116 #define BT2020_Kr 0.2627
117 #define BT2020_Kb 0.0593
121 int mpeg, yzero, uvzero;
122 int ymin8, ymax8, ymin16, ymax16;
123 int uvmin8, uvmax8, uvmin16, uvmax16;
125 float yminf, ymaxf, yrangef;
126 float uvminf, uvmaxf, uvrangef;
127 float r_to_y, g_to_y, b_to_y;
128 float r_to_u, g_to_u, b_to_u;
129 float r_to_v, g_to_v, b_to_v;
130 float v_to_r, v_to_g;
131 float u_to_g, u_to_b;
135 void init(double Kr, double Kb, int mpeg);
136 void init_tables(int len,
137 int *rtoy, int *rtou, int *rtov,
138 int *gtoy, int *gtou, int *gtov,
139 int *btoy, int *btou, int *btov,
140 int *ytab, int *vtor, int *vtog, int *utog, int *utob);
141 void init_tables(int len,
142 float *vtorf, float *vtogf, float *utogf, float *utobf);
144 // dont use pointers,
145 // offsets do not require indirect access
146 #define rtoy16 (tab+0x00000)
147 #define gtoy16 (tab+0x10000)
148 #define btoy16 (tab+0x20000)
149 #define rtou16 (tab+0x30000)
150 #define gtou16 (tab+0x40000)
151 #define btou16 (tab+0x50000)
152 #define rtov16 (tab+0x60000)
153 #define gtov16 (tab+0x70000)
154 #define btov16 (tab+0x80000)
155 #define ytab16 (tab+0x90000)
156 #define vtor16 (tab+0xa0000)
157 #define vtog16 (tab+0xb0000)
158 #define utog16 (tab+0xc0000)
159 #define utob16 (tab+0xd0000)
161 #define rtoy8 (tab+0xe0000)
162 #define gtoy8 (tab+0xe0100)
163 #define btoy8 (tab+0xe0200)
164 #define rtou8 (tab+0xe0300)
165 #define gtou8 (tab+0xe0400)
166 #define btou8 (tab+0xe0500)
167 #define rtov8 (tab+0xe0600)
168 #define gtov8 (tab+0xe0700)
169 #define btov8 (tab+0xe0800)
170 #define ytab8 (tab+0xe0900)
171 #define vtor8 (tab+0xe0a00)
172 #define vtog8 (tab+0xe0b00)
173 #define utog8 (tab+0xe0c00)
174 #define utob8 (tab+0xe0d00)
176 #define vtor16f (tabf+0x00000)
177 #define vtog16f (tabf+0x10000)
178 #define utog16f (tabf+0x20000)
179 #define utob16f (tabf+0x30000)
181 #define vtor8f (tabf+0x40000)
182 #define vtog8f (tabf+0x40100)
183 #define utog8f (tabf+0x40200)
184 #define utob8f (tabf+0x40300)
189 void yuv_set_colors(int color_space, int color_range);
190 inline int is_mpeg() { return mpeg; }
193 static float yuv_to_rgb_matrix[9];
194 static float rgb_to_yuv_matrix[9];
195 static float *const rgb_to_y_vector;
196 inline float get_yminf() { return yminf; }
198 #define YUV_rgb_to_yuv_8(r,g,b, y,u,v) \
199 y = iclip((rtoy8[r] + gtoy8[g] + btoy8[b] + yzero) >> 16, ymin8, ymax8); \
200 u = iclip((rtou8[r] + gtou8[g] + btou8[b] + uvzero) >> 16, uvmin8, uvmax8); \
201 v = iclip((rtov8[r] + gtov8[g] + btov8[b] + uvzero) >> 16, uvmin8, uvmax8)
203 bc_always_inline void rgb_to_yuv_8(int r, int g, int b, int &y, int &u, int &v) {
204 YUV_rgb_to_yuv_8(r,g,b, y,u,v);
206 bc_always_inline void rgb_to_yuv_8(int r, int g, int b, uint8_t &y, uint8_t &u, uint8_t &v) {
207 YUV_rgb_to_yuv_8(r,g,b, y,u,v);
209 bc_always_inline void rgb_to_yuv_8(int &y, int &u, int &v) {
210 int r = y, g = u, b = v; YUV_rgb_to_yuv_8(r, g, b, y, u, v);
213 #define YUV_rgb_to_yuv_16(r,g,b, y,u,v) \
214 y = iclip((rtoy16[r] + gtoy16[g] + btoy16[b] + yzero) >> 8, ymin16, ymax16); \
215 u = iclip((rtou16[r] + gtou16[g] + btou16[b] + uvzero) >> 8, uvmin16, uvmax16); \
216 v = iclip((rtov16[r] + gtov16[g] + btov16[b] + uvzero) >> 8, uvmin16, uvmax16)
218 bc_always_inline void rgb_to_yuv_16(int r, int g, int b, int &y, int &u, int &v) {
219 YUV_rgb_to_yuv_16(r,g,b, y,u,v);
221 bc_always_inline void rgb_to_yuv_16(int r, int g, int b, uint16_t &y, uint16_t &u, uint16_t &v) {
222 YUV_rgb_to_yuv_16(r,g,b, y,u,v);
224 bc_always_inline void rgb_to_yuv_16(int &y, int &u, int &v) {
225 int r = y, g = u, b = v;
226 YUV_rgb_to_yuv_16(r, g, b, y, u, v);
229 bc_always_inline void rgb_to_yuv_f(float r, float g, float b, float &y, float &u, float &v) {
230 y = r * r_to_y + g * g_to_y + b * b_to_y + yminf;
231 u = r * r_to_u + g * g_to_u + b * b_to_u;
232 v = r * r_to_v + g * g_to_v + b * b_to_v;
234 bc_always_inline void rgb_to_yuv_f(float r, float g, float b, uint8_t &y, uint8_t &u, uint8_t &v) {
235 int ir = iclip(r*0x100, 0, 0xff);
236 int ig = iclip(g*0x100, 0, 0xff);
237 int ib = iclip(b*0x100, 0, 0xff);
238 rgb_to_yuv_8(ir,ig,ib, y,u,v);
240 bc_always_inline void rgb_to_yuv_f(float r, float g, float b, uint16_t &y, uint16_t &u, uint16_t &v) {
241 int ir = iclip(r*0x10000, 0, 0xffff);
242 int ig = iclip(g*0x10000, 0, 0xffff);
243 int ib = iclip(b*0x10000, 0, 0xffff);
244 rgb_to_yuv_16(ir,ig,ib, y,u,v);
247 #define YUV_yuv_to_rgb_8(r,g,b, y,u,v) \
248 r = iclip((ytab8[y] + vtor8[v]) >> 16, 0, 0xff); \
249 g = iclip((ytab8[y] + utog8[u] + vtog8[v]) >> 16, 0, 0xff); \
250 b = iclip((ytab8[y] + utob8[u]) >> 16, 0, 0xff)
252 bc_always_inline void yuv_to_rgb_8(int &r, int &g, int &b, int y, int u, int v) {
253 YUV_yuv_to_rgb_8(r,g,b, y,u,v);
255 bc_always_inline void yuv_to_rgb_8(uint8_t &r, uint8_t &g, uint8_t &b, int y, int u, int v) {
256 YUV_yuv_to_rgb_8(r,g,b, y,u,v);
258 bc_always_inline void yuv_to_rgb_8(int &r, int &g, int &b) {
259 int y = r, u = g, v = b; YUV_yuv_to_rgb_8(r,g,b, y,u,v);
261 bc_always_inline void yuv_to_rgb_8(float &r, float &g, float &b, int y, int u, int v) {
262 int ir, ig, ib; yuv_to_rgb_8(ir,ig,ib, y,u,v);
263 float s = 1/255.f; r = s*ir; g = s*ig; b = s*ib;
266 #define YUV_yuv_to_rgb_16(r,g,b, y,u,v) \
267 r = iclip((ytab16[y] + vtor16[v]) >> 8, 0, 0xffff); \
268 g = iclip((ytab16[y] + utog16[u] + vtog16[v]) >> 8, 0, 0xffff); \
269 b = iclip((ytab16[y] + utob16[u]) >> 8, 0, 0xffff)
271 bc_always_inline void yuv_to_rgb_16(int &r, int &g, int &b, int y, int u, int v) {
272 YUV_yuv_to_rgb_16(r,g,b, y,u,v);
274 bc_always_inline void yuv_to_rgb_16(uint16_t &r, uint16_t &g, uint16_t &b, int y, int u, int v) {
275 YUV_yuv_to_rgb_16(r,g,b, y,u,v);
277 bc_always_inline void yuv_to_rgb_16(int &r, int &g, int &b) {
278 int y = r, u = g, v = b; YUV_yuv_to_rgb_16(r,g,b, y,u,v);
280 bc_always_inline void yuv_to_rgb_16(float &r, float &g, float &b, int y, int u, int v) {
281 int ir, ig, ib; YUV_yuv_to_rgb_16(ir,ig,ib, y,u,v);
282 float s = 1/65535.f; r = s*ir; g = s*ig; b = s*ib;
285 bc_always_inline void yuv_to_rgb_f(float &r, float &g, float &b, float y, float u, float v) {
286 y = (y-yminf) / yrangef;
288 g = y + u_to_g * u + v_to_g * v;
291 bc_always_inline void yuv_to_rgb_f(float &r, float &g, float &b, uint8_t &y, uint8_t &u, uint8_t &v) {
292 yuv_to_rgb_8(r,g,b, y,u,v);
294 bc_always_inline void yuv_to_rgb_f(float &r, float &g, float &b, uint16_t &y, uint16_t &u, uint16_t &v) {
295 yuv_to_rgb_16(r,g,b, y,u,v);
298 bc_always_inline int rgb_to_y_8(int r, int g, int b) {
299 return (rtoy8[r] + gtoy8[g] + btoy8[b] + yzero) >> 16;
301 bc_always_inline int rgb_to_y_16(int r, int g, int b) {
302 return (rtoy16[r] + gtoy16[g] + btoy16[b] + yzero) >> 8;
304 bc_always_inline float rgb_to_y_f(float r, float g, float b) {
305 return r * r_to_y + g * g_to_y + b * b_to_y + yminf;
308 // For easier programming. Doesn't do anything.
309 // unused cases in macro expansions, mismatched argument types
310 inline void yuv_to_rgb_8(float &r, float &g, float &b, float y, float u, float v) {}
311 inline void yuv_to_rgb_16(float &r, float &g, float &b, float y, float u, float v) {}
312 inline void yuv_to_rgb_f(int &r, int &g, int &b, int y, int u, int v) {}
313 inline void yuv_to_rgb_f(uint8_t &r, uint8_t &g, uint8_t &b, int&y, int u, int v) {}
314 inline void yuv_to_rgb_f(uint16_t &r, uint16_t &g, uint16_t &b, int y, int u, int v) {}
316 inline void rgb_to_yuv_8(float r, float g, float b, float &y, float &u, float &v) {}
317 inline void rgb_to_yuv_16(float r, float g, float b, float &y, float &u, float &v) {}
318 inline void rgb_to_yuv_f(int r, int g, int b, int &y, int &u, int &v) {}
319 inline void rgb_to_yuv_f(uint8_t r, uint8_t g, uint8_t b, int &y, int &u, int &v) {}
320 inline void rgb_to_yuv_f(uint16_t r, uint16_t g, uint16_t b, int &y, int &u, int &v) {}
330 // All units are 0 - 1
331 static int rgb_to_hsv(float r, float g, float b, float &h, float &s, float &v);
332 static int hsv_to_rgb(float &r, float &g, float &b, float h, float s, float v);
334 // YUV units are 0 - max. HSV units are 0 - 1
335 static int yuv_to_hsv(int y, int u, int v, float &h, float &s, float &va, int max);
336 static int hsv_to_yuv(int &y, int &u, int &v, float h, float s, float va, int max);
337 // Dummies for macros
338 static int yuv_to_hsv(float y, float u, float v, float &h, float &s, float &va, float max) { return 0; };
339 static int hsv_to_yuv(float &y, float &u, float &v, float h, float s, float va, float max) { return 0; };