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: kr = BT601_Kr; kb = BT601_Kb; break;
147 case BC_COLORS_BT709: kr = BT709_Kr; kb = BT709_Kb; break;
148 case BC_COLORS_BT2020: kr = BT2020_Kr; kb = BT2020_Kb; break;
150 switch( color_range ) {
152 case BC_COLORS_JPEG: mpeg = 0; break;
153 case BC_COLORS_MPEG: mpeg = 1; break;
158 void YUV::init(double Kr, double Kb, int mpeg)
161 int ymin = !mpeg? 0 : 16;
162 int ymax = !mpeg? 255 : 235;
163 int uvmin = !mpeg? 0 : 16;
164 int uvmax = !mpeg? 255 : 240;
167 this->ymin16 = ymin*0x100;
168 this->ymax16 = (ymax+1)*0x100 - 1;
169 this->yzero = 0x10000 * ymin;
170 this->uvmin8 = uvmin;
171 this->uvmax8 = uvmax;
172 this->uvmin16 = uvmin*0x100;
173 this->uvmax16 = (uvmax+1)*0x100 - 1;
174 this->uvzero = 0x800000;
175 this->yminf = ymin / 256.;
176 this->ymaxf = (ymax+1) / 256.;
177 this->yrangef = ymaxf - yminf;
178 this->uvminf = uvmin / 256.;
179 this->uvmaxf = (uvmax+1) / 256.;
180 this->uvrangef = uvmaxf - uvminf;
182 this->Kg = 1. - Kr - Kb;
187 double R_to_U = -0.5*Kr/(1-Kb);
188 double G_to_U = -0.5*Kg/(1-Kb);
191 double G_to_V = -0.5*Kg/(1-Kr);
192 double B_to_V = -0.5*Kb/(1-Kr);
193 double V_to_R = 2.0*(1-Kr);
194 double V_to_G = -2.0*Kr*(1-Kr)/Kg;
195 double U_to_G = -2.0*Kb*(1-Kb)/Kg;
196 double U_to_B = 2.0*(1-Kb);
198 this->r_to_y = yrangef * R_to_Y;
199 this->g_to_y = yrangef * G_to_Y;
200 this->b_to_y = yrangef * B_to_Y;
201 this->r_to_u = uvrangef * R_to_U;
202 this->g_to_u = uvrangef * G_to_U;
203 this->b_to_u = uvrangef * B_to_U;
204 this->r_to_v = uvrangef * R_to_V;
205 this->g_to_v = uvrangef * G_to_V;
206 this->b_to_v = uvrangef * B_to_V;
207 this->v_to_r = V_to_R / uvrangef;
208 this->v_to_g = V_to_G / uvrangef;
209 this->u_to_g = U_to_G / uvrangef;
210 this->u_to_b = U_to_B / uvrangef;
216 ytab8, vtor8, vtog8, utog8, utob8);
218 rtoy16, rtou16, rtov16,
219 gtoy16, gtou16, gtov16,
220 btoy16, btou16, btov16,
221 ytab16, vtor16, vtog16, utog16, utob16);
223 vtor8f, vtog8f, utog8f, utob8f);
225 vtor16f, vtog16f, utog16f, utob16f);
227 rgb_to_yuv_matrix[0] = r_to_y;
228 rgb_to_yuv_matrix[1] = g_to_y;
229 rgb_to_yuv_matrix[2] = b_to_y;
230 rgb_to_yuv_matrix[3] = r_to_u;
231 rgb_to_yuv_matrix[4] = g_to_u;
232 rgb_to_yuv_matrix[5] = b_to_u;
233 rgb_to_yuv_matrix[6] = r_to_v;
234 rgb_to_yuv_matrix[7] = g_to_v;
235 rgb_to_yuv_matrix[8] = b_to_v;
237 float yscale = 1.f / yrangef;
238 yuv_to_rgb_matrix[0] = yscale;
239 yuv_to_rgb_matrix[1] = 0;
240 yuv_to_rgb_matrix[2] = v_to_r;
241 yuv_to_rgb_matrix[3] = yscale;
242 yuv_to_rgb_matrix[4] = u_to_g;
243 yuv_to_rgb_matrix[5] = v_to_g;
244 yuv_to_rgb_matrix[6] = yscale;
245 yuv_to_rgb_matrix[7] = u_to_b;
246 yuv_to_rgb_matrix[8] = 0;
249 void YUV::init_tables(int len,
250 int *rtoy, int *rtou, int *rtov,
251 int *gtoy, int *gtou, int *gtov,
252 int *btoy, int *btou, int *btov,
254 int *vtor, int *vtog,
255 int *utog, int *utob)
258 double s = (double)0xffffff / len;
259 double r2y = s*r_to_y, g2y = s*g_to_y, b2y = s*b_to_y;
260 double r2u = s*r_to_u, g2u = s*g_to_u, b2u = s*b_to_u;
261 double r2v = s*r_to_v, g2v = s*g_to_v, b2v = s*b_to_v;
262 for( int rgb=0; rgb<len; ++rgb ) {
263 rtoy[rgb] = r2y*rgb; rtou[rgb] = r2u*rgb; rtov[rgb] = r2v*rgb;
264 gtoy[rgb] = g2y*rgb; gtou[rgb] = g2u*rgb; gtov[rgb] = g2v*rgb;
265 btoy[rgb] = b2y*rgb; btou[rgb] = b2u*rgb; btov[rgb] = b2v*rgb;
269 int y0 = ymin8 * len/0x100, y1 = (ymax8+1) * len/0x100 - 1;
270 s = (double)0xffffff / (y1 - y0);
272 while( y < y0 ) ytab[y++] = 0;
273 while( y < y1 ) ytab[y++] = s*iy++;
274 while( y < len ) ytab[y++] = 0xffffff;
276 int uv0 = uvmin8 * len/0x100, uv1 = (uvmax8+1) * len/0x100 - 1;
277 s = (double)0xffffff / (uv1 - uv0);
278 double v2r = s*v_to_r, v2g = s*v_to_g;
279 double u2g = s*u_to_g, u2b = s*u_to_b;
280 int uv = 0, iuv = uv0 - len/2;
281 int vr0 = v2r * iuv, vg0 = v2g * iuv;
282 int ug0 = u2g * iuv, ub0 = u2b * iuv;
284 vtor[uv] = vr0; vtog[uv] = vg0;
285 utog[uv] = ug0; utob[uv] = ub0;
289 vtor[uv] = iuv * v2r; vtog[uv] = iuv * v2g;
290 utog[uv] = iuv * u2g; utob[uv] = iuv * u2b;
293 int vr1 = v2r * iuv, vg1 = v2g * iuv;
294 int ug1 = u2g * iuv, ub1 = u2b * iuv;
296 vtor[uv] = vr1; vtog[uv] = vg1;
297 utog[uv] = ug1; utob[uv] = ub1;
302 void YUV::init_tables(int len,
303 float *vtorf, float *vtogf, float *utogf, float *utobf)
305 int len1 = len-1, len2 = len/2;
306 for( int i=0,k=-len2; i<len; ++i,++k ) {
307 vtorf[i] = (v_to_r * k)/len1;
308 vtogf[i] = (v_to_g * k)/len1;
309 utogf[i] = (u_to_g * k)/len1;
310 utobf[i] = (u_to_b * k)/len1;