yuv colorspace/range + prefs, ffmpeg colorrange probe, x11 direct force colormodel...
[goodguy/history.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
130 YUV::YUV()
131 {
132         this->tab = new int[0xe0e00];
133         this->tabf = new float[0x40400];
134         yuv_set_colors(0, 0);
135 }
136
137 void YUV::yuv_set_colors(int color_space, int color_range)
138 {
139         double kr, kb;
140         int mpeg;
141         switch( color_space ) {
142         default:
143         case 0: kr = BT601_Kr;  kb = BT601_Kb;  break;
144         case 1: kr = BT709_Kr;  kb = BT709_Kb;  break;
145         }
146         switch( color_range ) {
147         default:
148         case 0: mpeg = 0;  break;
149         case 1: mpeg = 1;  break;
150         }
151         init(kr, kb, mpeg);
152 }
153
154 void YUV::init(double Kr, double Kb, int mpeg)
155 {
156         this->mpeg   = 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;
161         this->ymin8  = ymin;
162         this->ymax8  = ymax;
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;
177         this->Kr = Kr;
178         this->Kg = 1. - Kr - Kb;
179         this->Kb = Kb;
180         double R_to_Y = Kr;
181         double G_to_Y = Kg;
182         double B_to_Y = Kb;
183         double R_to_U = -0.5*Kr/(1-Kb);
184         double G_to_U = -0.5*Kg/(1-Kb);
185         double B_to_U =  0.5;
186         double R_to_V =  0.5;
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);
193
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;
207         
208         init_tables(0x100,
209                 rtoy8, rtou8, rtov8,
210                 gtoy8, gtou8, gtov8,
211                 btoy8, btou8, btov8,
212                 ytab8, vtor8, vtog8, utog8, utob8);
213         init_tables(0x10000,
214                 rtoy16, rtou16, rtov16,
215                 gtoy16, gtou16, gtov16,
216                 btoy16, btou16, btov16,
217                 ytab16, vtor16, vtog16, utog16, utob16); 
218         init_tables(0x100,
219                 vtor8f, vtog8f, utog8f, utob8f);
220         init_tables(0x10000,
221                 vtor16f, vtog16f, utog16f, utob16f);
222 }
223
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,
228                 int *ytab,
229                 int *vtor, int *vtog,
230                 int *utog, int *utob)
231 {
232 // rgb->yuv
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;
241         }
242
243 // yuv->rgb
244         int y0  = ymin8 * len/0x100,  y1 = (ymax8+1) * len/0x100 - 1;
245         s = (double)0xffffff / (y1 - y0);
246         int y = 0, iy = 0;
247         while( y < y0 ) ytab[y++] = 0;
248         while( y < y1 ) ytab[y++] = s*iy++;
249         while( y < len ) ytab[y++] = 0xffffff;
250
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;
258         while( uv < uv0 ) {
259                 vtor[uv] = vr0;  vtog[uv] = vg0;
260                 utog[uv] = ug0;  utob[uv] = ub0;
261                 ++uv;
262         }
263         while( uv < uv1 ) {
264                 vtor[uv] = iuv * v2r;  vtog[uv] = iuv * v2g;
265                 utog[uv] = iuv * u2g;  utob[uv] = iuv * u2b;
266                 ++uv;  ++iuv;
267         }
268         int vr1 = v2r * iuv, vg1 = v2g * iuv;
269         int ug1 = u2g * iuv, ub1 = u2b * iuv;
270         while( uv < len ) {
271                 vtor[uv] = vr1;  vtog[uv] = vg1;
272                 utog[uv] = ug1;  utob[uv] = ub1;
273                 ++uv;
274         }
275 }
276
277 void YUV::init_tables(int len,
278                 float *vtorf, float *vtogf, float *utogf, float *utobf)
279 {
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;
286         }
287 }
288
289 YUV::~YUV()
290 {
291         delete [] tab;
292         delete [] tabf;
293 }
294