4 * Copyright (C) 2008 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
36 int HSV::rgb_to_hsv(float r, float g, float b, float &h, float &s, float &v)
38 float min = ((r < g) ? r : g) < b ? ((r < g) ? r : g) : b;
39 float max = ((r > g) ? r : g) > b ? ((r > g) ? r : g) : b;
40 float delta = max - min;
41 if( max != 0 && delta != 0 ) {
44 h = r == max ? (g - b) / delta : // between yellow & magenta
45 g == max ? 2 + (b - r) / delta : // between cyan & yellow
46 4 + (r - g) / delta; // between magenta & cyan
47 if( (h*=60) < 0 ) h += 360; // degrees
50 h = 0; s = 0; v = max;
56 int HSV::hsv_to_rgb(float &r, float &g, float &b, float h, float s, float v)
58 if( s == 0 ) { // achromatic (grey)
63 h /= 60; // sector 0 to 5
65 float f = h - i; // factorial part of h
66 float p = v * (1 - s);
67 float q = v * (1 - s * f);
68 float t = v * (1 - s * (1 - f));
71 case 0: r = v; g = t; b = p; break;
72 case 1: r = q; g = v; b = p; break;
73 case 2: r = p; g = v; b = t; break;
74 case 3: r = p; g = q; b = v; break;
75 case 4: r = t; g = p; b = v; break;
76 default: r = v; g = p; b = q; break;
81 int HSV::yuv_to_hsv(int y, int u, int v, float &h, float &s, float &va, int max)
88 // YUV::yuv.yuv_to_rgb_16(r_i, g_i, b_i, y, u, v);
92 YUV::yuv.yuv_to_rgb_8(r_i, g_i, b_i, y, u, v);
99 HSV::rgb_to_hsv(r, g, b, h2, s2, v2);
101 h = h2; s = s2; va = v2;
105 int HSV::hsv_to_yuv(int &y, int &u, int &v, float h, float s, float va, int max)
109 HSV::hsv_to_rgb(r, g, b, h, s, va);
113 r_i = (int)CLIP(r, 0, max);
114 g_i = (int)CLIP(g, 0, max);
115 b_i = (int)CLIP(b, 0, max);
119 // YUV::yuv.rgb_to_yuv_16(r_i, g_i, b_i, y2, u2, v2);
121 YUV::yuv.rgb_to_yuv_8(r_i, g_i, b_i, y2, u2, v2);
123 y = y2; u = u2; v = v2;
129 float YUV::yuv_to_rgb_matrix[9];
130 float YUV::rgb_to_yuv_matrix[9];
131 float *const YUV::rgb_to_y_vector = YUV::rgb_to_yuv_matrix;
135 this->tab = new int[0xe0e00];
136 this->tabf = new float[0x40400];
137 yuv_set_colors(0, 0);
140 void YUV::yuv_set_colors(int color_space, int color_range)
144 switch( color_space ) {
146 case BC_COLORS_BT601_NTSC: kr = BT601_NTSC_Kr; kb = BT601_NTSC_Kb; break;
147 case BC_COLORS_BT601_PAL: kr = BT601_PAL_Kr; kb = BT601_PAL_Kb; break;
148 case BC_COLORS_BT709: kr = BT709_Kr; kb = BT709_Kb; break;
149 case BC_COLORS_BT2020_NCL:
150 case BC_COLORS_BT2020_CL: kr = BT2020_Kr; kb = BT2020_Kb; break;
152 switch( color_range ) {
154 case BC_COLORS_JPEG: mpeg = 0; break;
155 case BC_COLORS_MPEG: mpeg = 1; break;
160 void YUV::init(double Kr, double Kb, int mpeg)
163 int ymin = !mpeg? 0 : 16;
164 int ymax = !mpeg? 255 : 235;
165 int uvmin = !mpeg? 0 : 16;
166 int uvmax = !mpeg? 255 : 240;
169 this->ymin16 = ymin*0x100;
170 this->ymax16 = (ymax+1)*0x100 - 1;
171 this->yzero = 0x10000 * ymin;
172 this->uvmin8 = uvmin;
173 this->uvmax8 = uvmax;
174 this->uvmin16 = uvmin*0x100;
175 this->uvmax16 = (uvmax+1)*0x100 - 1;
176 this->uvzero = 0x800000;
177 this->yminf = ymin / 256.;
178 this->ymaxf = (ymax+1) / 256.;
179 this->yrangef = ymaxf - yminf;
180 this->uvminf = uvmin / 256.;
181 this->uvmaxf = (uvmax+1) / 256.;
182 this->uvrangef = uvmaxf - uvminf;
184 this->Kg = 1. - Kr - Kb;
189 double R_to_U = -0.5*Kr/(1-Kb);
190 double G_to_U = -0.5*Kg/(1-Kb);
193 double G_to_V = -0.5*Kg/(1-Kr);
194 double B_to_V = -0.5*Kb/(1-Kr);
195 double V_to_R = 2.0*(1-Kr);
196 double V_to_G = -2.0*Kr*(1-Kr)/Kg;
197 double U_to_G = -2.0*Kb*(1-Kb)/Kg;
198 double U_to_B = 2.0*(1-Kb);
200 this->r_to_y = yrangef * R_to_Y;
201 this->g_to_y = yrangef * G_to_Y;
202 this->b_to_y = yrangef * B_to_Y;
203 this->r_to_u = uvrangef * R_to_U;
204 this->g_to_u = uvrangef * G_to_U;
205 this->b_to_u = uvrangef * B_to_U;
206 this->r_to_v = uvrangef * R_to_V;
207 this->g_to_v = uvrangef * G_to_V;
208 this->b_to_v = uvrangef * B_to_V;
209 this->v_to_r = V_to_R / uvrangef;
210 this->v_to_g = V_to_G / uvrangef;
211 this->u_to_g = U_to_G / uvrangef;
212 this->u_to_b = U_to_B / uvrangef;
218 ytab8, vtor8, vtog8, utog8, utob8);
220 rtoy16, rtou16, rtov16,
221 gtoy16, gtou16, gtov16,
222 btoy16, btou16, btov16,
223 ytab16, vtor16, vtog16, utog16, utob16);
225 vtor8f, vtog8f, utog8f, utob8f);
227 vtor16f, vtog16f, utog16f, utob16f);
229 rgb_to_yuv_matrix[0] = r_to_y;
230 rgb_to_yuv_matrix[1] = g_to_y;
231 rgb_to_yuv_matrix[2] = b_to_y;
232 rgb_to_yuv_matrix[3] = r_to_u;
233 rgb_to_yuv_matrix[4] = g_to_u;
234 rgb_to_yuv_matrix[5] = b_to_u;
235 rgb_to_yuv_matrix[6] = r_to_v;
236 rgb_to_yuv_matrix[7] = g_to_v;
237 rgb_to_yuv_matrix[8] = b_to_v;
239 float yscale = 1.f / yrangef;
240 yuv_to_rgb_matrix[0] = yscale;
241 yuv_to_rgb_matrix[1] = 0;
242 yuv_to_rgb_matrix[2] = v_to_r;
243 yuv_to_rgb_matrix[3] = yscale;
244 yuv_to_rgb_matrix[4] = u_to_g;
245 yuv_to_rgb_matrix[5] = v_to_g;
246 yuv_to_rgb_matrix[6] = yscale;
247 yuv_to_rgb_matrix[7] = u_to_b;
248 yuv_to_rgb_matrix[8] = 0;
251 void YUV::init_tables(int len,
252 int *rtoy, int *rtou, int *rtov,
253 int *gtoy, int *gtou, int *gtov,
254 int *btoy, int *btou, int *btov,
256 int *vtor, int *vtog,
257 int *utog, int *utob)
260 double s = (double)0xffffff / len;
261 double r2y = s*r_to_y, g2y = s*g_to_y, b2y = s*b_to_y;
262 double r2u = s*r_to_u, g2u = s*g_to_u, b2u = s*b_to_u;
263 double r2v = s*r_to_v, g2v = s*g_to_v, b2v = s*b_to_v;
264 for( int rgb=0; rgb<len; ++rgb ) {
265 rtoy[rgb] = r2y*rgb; rtou[rgb] = r2u*rgb; rtov[rgb] = r2v*rgb;
266 gtoy[rgb] = g2y*rgb; gtou[rgb] = g2u*rgb; gtov[rgb] = g2v*rgb;
267 btoy[rgb] = b2y*rgb; btou[rgb] = b2u*rgb; btov[rgb] = b2v*rgb;
271 int y0 = ymin8 * len/0x100, y1 = (ymax8+1) * len/0x100 - 1;
272 s = (double)0xffffff / (y1 - y0);
274 while( y < y0 ) ytab[y++] = 0;
275 while( y < y1 ) ytab[y++] = s*iy++;
276 while( y < len ) ytab[y++] = 0xffffff;
278 int uv0 = uvmin8 * len/0x100, uv1 = (uvmax8+1) * len/0x100 - 1;
279 s = (double)0xffffff / (uv1 - uv0);
280 double v2r = s*v_to_r, v2g = s*v_to_g;
281 double u2g = s*u_to_g, u2b = s*u_to_b;
282 int uv = 0, iuv = uv0 - len/2;
283 int vr0 = v2r * iuv, vg0 = v2g * iuv;
284 int ug0 = u2g * iuv, ub0 = u2b * iuv;
286 vtor[uv] = vr0; vtog[uv] = vg0;
287 utog[uv] = ug0; utob[uv] = ub0;
291 vtor[uv] = iuv * v2r; vtog[uv] = iuv * v2g;
292 utog[uv] = iuv * u2g; utob[uv] = iuv * u2b;
295 int vr1 = v2r * iuv, vg1 = v2g * iuv;
296 int ug1 = u2g * iuv, ub1 = u2b * iuv;
298 vtor[uv] = vr1; vtog[uv] = vg1;
299 utog[uv] = ug1; utob[uv] = ub1;
304 void YUV::init_tables(int len,
305 float *vtorf, float *vtogf, float *utogf, float *utobf)
307 int len1 = len-1, len2 = len/2;
308 for( int i=0,k=-len2; i<len; ++i,++k ) {
309 vtorf[i] = (v_to_r * k)/len1;
310 vtogf[i] = (v_to_g * k)/len1;
311 utogf[i] = (u_to_g * k)/len1;
312 utobf[i] = (u_to_b * k)/len1;