improve delays created by vicon drawing locks, reset_cache segv fix, gang track toolt...
[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:  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;
149         }
150         switch( color_range ) {
151         default:
152         case BC_COLORS_JPEG: mpeg = 0;  break;
153         case BC_COLORS_MPEG: mpeg = 1;  break;
154         }
155         init(kr, kb, mpeg);
156 }
157
158 void YUV::init(double Kr, double Kb, int mpeg)
159 {
160         this->mpeg   = 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;
165         this->ymin8  = ymin;
166         this->ymax8  = ymax;
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;
181         this->Kr = Kr;
182         this->Kg = 1. - Kr - Kb;
183         this->Kb = Kb;
184         double R_to_Y = Kr;
185         double G_to_Y = Kg;
186         double B_to_Y = Kb;
187         double R_to_U = -0.5*Kr/(1-Kb);
188         double G_to_U = -0.5*Kg/(1-Kb);
189         double B_to_U =  0.5;
190         double R_to_V =  0.5;
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);
197
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;
211         
212         init_tables(0x100,
213                 rtoy8, rtou8, rtov8,
214                 gtoy8, gtou8, gtov8,
215                 btoy8, btou8, btov8,
216                 ytab8, vtor8, vtog8, utog8, utob8);
217         init_tables(0x10000,
218                 rtoy16, rtou16, rtov16,
219                 gtoy16, gtou16, gtov16,
220                 btoy16, btou16, btov16,
221                 ytab16, vtor16, vtog16, utog16, utob16); 
222         init_tables(0x100,
223                 vtor8f, vtog8f, utog8f, utob8f);
224         init_tables(0x10000,
225                 vtor16f, vtog16f, utog16f, utob16f);
226
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;
236
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;
247 }
248
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,
253                 int *ytab,
254                 int *vtor, int *vtog,
255                 int *utog, int *utob)
256 {
257 // rgb->yuv
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;
266         }
267
268 // yuv->rgb
269         int y0  = ymin8 * len/0x100,  y1 = (ymax8+1) * len/0x100 - 1;
270         s = (double)0xffffff / (y1 - y0);
271         int y = 0, iy = 0;
272         while( y < y0 ) ytab[y++] = 0;
273         while( y < y1 ) ytab[y++] = s*iy++;
274         while( y < len ) ytab[y++] = 0xffffff;
275
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;
283         while( uv < uv0 ) {
284                 vtor[uv] = vr0;  vtog[uv] = vg0;
285                 utog[uv] = ug0;  utob[uv] = ub0;
286                 ++uv;
287         }
288         while( uv < uv1 ) {
289                 vtor[uv] = iuv * v2r;  vtog[uv] = iuv * v2g;
290                 utog[uv] = iuv * u2g;  utob[uv] = iuv * u2b;
291                 ++uv;  ++iuv;
292         }
293         int vr1 = v2r * iuv, vg1 = v2g * iuv;
294         int ug1 = u2g * iuv, ub1 = u2b * iuv;
295         while( uv < len ) {
296                 vtor[uv] = vr1;  vtog[uv] = vg1;
297                 utog[uv] = ug1;  utob[uv] = ub1;
298                 ++uv;
299         }
300 }
301
302 void YUV::init_tables(int len,
303                 float *vtorf, float *vtogf, float *utogf, float *utobf)
304 {
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;
311         }
312 }
313
314 YUV::~YUV()
315 {
316         delete [] tab;
317         delete [] tabf;
318 }
319