287cc9f86036292e9ed59e5f91a9893ff07a36b2
[goodguy/cinelerra.git] / cinelerra-5.1 / guicast / bccolors.C
1
2 /*
3  * CINELERRA
4  * Copyright (C) 2008 Adam Williams <broadcast at earthling dot net>
5  *
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.
10  *
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.
15  *
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
19  *
20  */
21
22 #include "bccolors.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26
27 HSV::HSV()
28 {
29 }
30
31
32 HSV::~HSV()
33 {
34 }
35
36 int HSV::rgb_to_hsv(float r, float g, float b, float &h, float &s, float &v)
37 {
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 ) {
42                 v = max;
43                 s = delta / max;
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
48         }
49         else { // r = g = b
50                 h = 0;  s = 0;  v = max;
51         }
52
53         return 0;
54 }
55
56 int HSV::hsv_to_rgb(float &r, float &g, float &b, float h, float s, float v)
57 {
58         if( s == 0 ) { // achromatic (grey)
59                 r = g = b = v;
60                 return 0;
61         }
62
63         h /= 60;                        // sector 0 to 5
64         int i = (int)h;
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));
69
70         switch(i) {
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;
77         }
78         return 0;
79 }
80
81 int HSV::yuv_to_hsv(int y, int u, int v, float &h, float &s, float &va, int max)
82 {
83         float r, g, b;
84         int r_i, g_i, b_i;
85
86 //      if(max == 0xffff)
87 //      {
88 //              YUV::yuv.yuv_to_rgb_16(r_i, g_i, b_i, y, u, v);
89 //      }
90 //      else
91         {
92                 YUV::yuv.yuv_to_rgb_8(r_i, g_i, b_i, y, u, v);
93         }
94         r = (float)r_i / max;
95         g = (float)g_i / max;
96         b = (float)b_i / max;
97
98         float h2, s2, v2;
99         HSV::rgb_to_hsv(r, g, b, h2, s2, v2);
100
101         h = h2;  s = s2;  va = v2;
102         return 0;
103 }
104
105 int HSV::hsv_to_yuv(int &y, int &u, int &v, float h, float s, float va, int max)
106 {
107         float r, g, b;
108         int r_i, g_i, b_i;
109         HSV::hsv_to_rgb(r, g, b, h, s, va);
110         r = r * max + 0.5;
111         g = g * max + 0.5;
112         b = b * max + 0.5;
113         r_i = (int)CLIP(r, 0, max);
114         g_i = (int)CLIP(g, 0, max);
115         b_i = (int)CLIP(b, 0, max);
116
117         int y2, u2, v2;
118 //      if(max == 0xffff)
119 //              YUV::yuv.rgb_to_yuv_16(r_i, g_i, b_i, y2, u2, v2);
120 //      else
121                 YUV::yuv.rgb_to_yuv_8(r_i, g_i, b_i, y2, u2, v2);
122
123         y = y2;  u = u2;  v = v2;
124         return 0;
125 }
126
127
128 YUV YUV::yuv;
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;
132
133 YUV::YUV()
134 {
135         this->tab = new int[0xe0e00];
136         this->tabf = new float[0x40400];
137         yuv_set_colors(0, 0);
138 }
139
140 void YUV::yuv_set_colors(int color_space, int color_range)
141 {
142         double kr, kb;
143         int mpeg;
144         switch( color_space ) {
145         default:
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;
151         }
152         switch( color_range ) {
153         default:
154         case BC_COLORS_JPEG: mpeg = 0;  break;
155         case BC_COLORS_MPEG: mpeg = 1;  break;
156         }
157         init(kr, kb, mpeg);
158 }
159
160 void YUV::init(double Kr, double Kb, int mpeg)
161 {
162         this->mpeg   = 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;
167         this->ymin8  = ymin;
168         this->ymax8  = ymax;
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;
183         this->Kr = Kr;
184         this->Kg = 1. - Kr - Kb;
185         this->Kb = Kb;
186         double R_to_Y = Kr;
187         double G_to_Y = Kg;
188         double B_to_Y = Kb;
189         double R_to_U = -0.5*Kr/(1-Kb);
190         double G_to_U = -0.5*Kg/(1-Kb);
191         double B_to_U =  0.5;
192         double R_to_V =  0.5;
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);
199
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;
213         
214         init_tables(0x100,
215                 rtoy8, rtou8, rtov8,
216                 gtoy8, gtou8, gtov8,
217                 btoy8, btou8, btov8,
218                 ytab8, vtor8, vtog8, utog8, utob8);
219         init_tables(0x10000,
220                 rtoy16, rtou16, rtov16,
221                 gtoy16, gtou16, gtov16,
222                 btoy16, btou16, btov16,
223                 ytab16, vtor16, vtog16, utog16, utob16); 
224         init_tables(0x100,
225                 vtor8f, vtog8f, utog8f, utob8f);
226         init_tables(0x10000,
227                 vtor16f, vtog16f, utog16f, utob16f);
228
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;
238
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;
249 }
250
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,
255                 int *ytab,
256                 int *vtor, int *vtog,
257                 int *utog, int *utob)
258 {
259 // rgb->yuv
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;
268         }
269
270 // yuv->rgb
271         int y0  = ymin8 * len/0x100,  y1 = (ymax8+1) * len/0x100 - 1;
272         s = (double)0xffffff / (y1 - y0);
273         int y = 0, iy = 0;
274         while( y < y0 ) ytab[y++] = 0;
275         while( y < y1 ) ytab[y++] = s*iy++;
276         while( y < len ) ytab[y++] = 0xffffff;
277
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;
285         while( uv < uv0 ) {
286                 vtor[uv] = vr0;  vtog[uv] = vg0;
287                 utog[uv] = ug0;  utob[uv] = ub0;
288                 ++uv;
289         }
290         while( uv < uv1 ) {
291                 vtor[uv] = iuv * v2r;  vtog[uv] = iuv * v2g;
292                 utog[uv] = iuv * u2g;  utob[uv] = iuv * u2b;
293                 ++uv;  ++iuv;
294         }
295         int vr1 = v2r * iuv, vg1 = v2g * iuv;
296         int ug1 = u2g * iuv, ub1 = u2b * iuv;
297         while( uv < len ) {
298                 vtor[uv] = vr1;  vtog[uv] = vg1;
299                 utog[uv] = ug1;  utob[uv] = ub1;
300                 ++uv;
301         }
302 }
303
304 void YUV::init_tables(int len,
305                 float *vtorf, float *vtogf, float *utogf, float *utobf)
306 {
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;
313         }
314 }
315
316 YUV::~YUV()
317 {
318         delete [] tab;
319         delete [] tabf;
320 }
321