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;
132 this->tab = new int[0xe0e00];
133 this->tabf = new float[0x40400];
134 yuv_set_colors(0, 0);
137 void YUV::yuv_set_colors(int color_space, int color_range)
141 switch( color_space ) {
143 case 0: kr = BT601_Kr; kb = BT601_Kb; break;
144 case 1: kr = BT709_Kr; kb = BT709_Kb; break;
146 switch( color_range ) {
148 case 0: mpeg = 0; break;
149 case 1: mpeg = 1; break;
154 void YUV::init(double Kr, double Kb, int mpeg)
157 int ymin = !mpeg? 0 : 16;
158 int ymax = !mpeg? 255 : 235;
159 int uvmin = !mpeg? 0 : 16;
160 int uvmax = !mpeg? 255 : 240;
163 this->ymin16 = ymin*0x100;
164 this->ymax16 = (ymax+1)*0x100 - 1;
165 this->yzero = 0x10000 * ymin;
166 this->uvmin8 = uvmin;
167 this->uvmax8 = uvmax;
168 this->uvmin16 = uvmin*0x100;
169 this->uvmax16 = (uvmax+1)*0x100 - 1;
170 this->uvzero = 0x800000;
171 this->yminf = ymin / 256.;
172 this->ymaxf = (ymax+1) / 256.;
173 this->yrangef = ymaxf - yminf;
174 this->uvminf = uvmin / 256.;
175 this->uvmaxf = (uvmax+1) / 256.;
176 this->uvrangef = uvmaxf - uvminf;
178 this->Kg = 1. - Kr - Kb;
183 double R_to_U = -0.5*Kr/(1-Kb);
184 double G_to_U = -0.5*Kg/(1-Kb);
187 double G_to_V = -0.5*Kg/(1-Kr);
188 double B_to_V = -0.5*Kb/(1-Kr);
189 double V_to_R = 2.0*(1-Kr);
190 double V_to_G = -2.0*Kr*(1-Kr)/Kg;
191 double U_to_G = -2.0*Kb*(1-Kb)/Kg;
192 double U_to_B = 2.0*(1-Kb);
194 this->r_to_y = yrangef * R_to_Y;
195 this->g_to_y = yrangef * G_to_Y;
196 this->b_to_y = yrangef * B_to_Y;
197 this->r_to_u = uvrangef * R_to_U;
198 this->g_to_u = uvrangef * G_to_U;
199 this->b_to_u = uvrangef * B_to_U;
200 this->r_to_v = uvrangef * R_to_V;
201 this->g_to_v = uvrangef * G_to_V;
202 this->b_to_v = uvrangef * B_to_V;
203 this->v_to_r = V_to_R / uvrangef;
204 this->v_to_g = V_to_G / uvrangef;
205 this->u_to_g = U_to_G / uvrangef;
206 this->u_to_b = U_to_B / uvrangef;
212 ytab8, vtor8, vtog8, utog8, utob8);
214 rtoy16, rtou16, rtov16,
215 gtoy16, gtou16, gtov16,
216 btoy16, btou16, btov16,
217 ytab16, vtor16, vtog16, utog16, utob16);
219 vtor8f, vtog8f, utog8f, utob8f);
221 vtor16f, vtog16f, utog16f, utob16f);
224 void YUV::init_tables(int len,
225 int *rtoy, int *rtou, int *rtov,
226 int *gtoy, int *gtou, int *gtov,
227 int *btoy, int *btou, int *btov,
229 int *vtor, int *vtog,
230 int *utog, int *utob)
233 double s = (double)0xffffff / len;
234 double r2y = s*r_to_y, g2y = s*g_to_y, b2y = s*b_to_y;
235 double r2u = s*r_to_u, g2u = s*g_to_u, b2u = s*b_to_u;
236 double r2v = s*r_to_v, g2v = s*g_to_v, b2v = s*b_to_v;
237 for( int rgb=0; rgb<len; ++rgb ) {
238 rtoy[rgb] = r2y*rgb; rtou[rgb] = r2u*rgb; rtov[rgb] = r2v*rgb;
239 gtoy[rgb] = g2y*rgb; gtou[rgb] = g2u*rgb; gtov[rgb] = g2v*rgb;
240 btoy[rgb] = b2y*rgb; btou[rgb] = b2u*rgb; btov[rgb] = b2v*rgb;
244 int y0 = ymin8 * len/0x100, y1 = (ymax8+1) * len/0x100 - 1;
245 s = (double)0xffffff / (y1 - y0);
247 while( y < y0 ) ytab[y++] = 0;
248 while( y < y1 ) ytab[y++] = s*iy++;
249 while( y < len ) ytab[y++] = 0xffffff;
251 int uv0 = uvmin8 * len/0x100, uv1 = (uvmax8+1) * len/0x100 - 1;
252 s = (double)0xffffff / (uv1 - uv0);
253 double v2r = s*v_to_r, v2g = s*v_to_g;
254 double u2g = s*u_to_g, u2b = s*u_to_b;
255 int uv = 0, iuv = uv0 - len/2;
256 int vr0 = v2r * iuv, vg0 = v2g * iuv;
257 int ug0 = u2g * iuv, ub0 = u2b * iuv;
259 vtor[uv] = vr0; vtog[uv] = vg0;
260 utog[uv] = ug0; utob[uv] = ub0;
264 vtor[uv] = iuv * v2r; vtog[uv] = iuv * v2g;
265 utog[uv] = iuv * u2g; utob[uv] = iuv * u2b;
268 int vr1 = v2r * iuv, vg1 = v2g * iuv;
269 int ug1 = u2g * iuv, ub1 = u2b * iuv;
271 vtor[uv] = vr1; vtog[uv] = vg1;
272 utog[uv] = ug1; utob[uv] = ub1;
277 void YUV::init_tables(int len,
278 float *vtorf, float *vtogf, float *utogf, float *utobf)
280 int len1 = len-1, len2 = len/2;
281 for( int i=0,k=-len2; i<len; ++i,++k ) {
282 vtorf[i] = (v_to_r * k)/len1;
283 vtogf[i] = (v_to_g * k)/len1;
284 utogf[i] = (u_to_g * k)/len1;
285 utobf[i] = (u_to_b * k)/len1;