yuv colorspace/range + prefs, ffmpeg colorrange probe, x11 direct force colormodel...
[goodguy/history.git] / cinelerra-5.1 / guicast / bccolors.C
index 48dcb02aa5acd649c69591311bb056d5b712bf03..a287fb78c64fa7ee2bb0dedfb34483f160aa8df9 100644 (file)
@@ -22,6 +22,7 @@
 #include "bccolors.h"
 
 #include <stdio.h>
+#include <stdlib.h>
 
 HSV::HSV()
 {
@@ -32,8 +33,6 @@ HSV::~HSV()
 {
 }
 
-YUV YUV::yuv;
-
 int HSV::rgb_to_hsv(float r, float g, float b, float &h, float &s, float &v)
 {
        float min = ((r < g) ? r : g) < b ? ((r < g) ? r : g) : b;
@@ -125,68 +124,171 @@ int HSV::hsv_to_yuv(int &y, int &u, int &v, float h, float s, float va, int max)
        return 0;
 }
 
-YUV::YUV()
-{
-       for(int i = 0; i < 0x100; i++) {
-// compression
-               rtoy_tab_8[i] = (int)(R_TO_Y * 0x100 * i);
-               rtou_tab_8[i] = (int)(R_TO_U * 0x100 * i);
-               rtov_tab_8[i] = (int)(R_TO_V * 0x100 * i);
-
-               gtoy_tab_8[i] = (int)(G_TO_Y * 0x100 * i);
-               gtou_tab_8[i] = (int)(G_TO_U * 0x100 * i);
-               gtov_tab_8[i] = (int)(G_TO_V * 0x100 * i);
-
-               btoy_tab_8[i] = (int)(B_TO_Y * 0x100 * i);
-               btou_tab_8[i] = (int)(B_TO_U * 0x100 * i) + 0x8000;
-               btov_tab_8[i] = (int)(B_TO_V * 0x100 * i) + 0x8000;
-       }
 
-       vtor_8 = &(vtor_tab_8[(0x100) / 2]);
-       vtog_8 = &(vtog_tab_8[(0x100) / 2]);
-       utog_8 = &(utog_tab_8[(0x100) / 2]);
-       utob_8 = &(utob_tab_8[(0x100) / 2]);
+YUV YUV::yuv;
 
-       for(int i = (-0x100) / 2; i < (0x100) / 2; i++) {
-// decompression
-               vtor_8[i] = (int)(V_TO_R * 0x100 * i);
-               vtog_8[i] = (int)(V_TO_G * 0x100 * i);
+YUV::YUV()
+{
+       this->tab = new int[0xe0e00];
+       this->tabf = new float[0x40400];
+       yuv_set_colors(0, 0);
+}
 
-               utog_8[i] = (int)(U_TO_G * 0x100 * i);
-               utob_8[i] = (int)(U_TO_B * 0x100 * i);
+void YUV::yuv_set_colors(int color_space, int color_range)
+{
+       double kr, kb;
+       int mpeg;
+       switch( color_space ) {
+       default:
+       case 0: kr = BT601_Kr;  kb = BT601_Kb;  break;
+       case 1: kr = BT709_Kr;  kb = BT709_Kb;  break;
        }
+       switch( color_range ) {
+       default:
+       case 0: mpeg = 0;  break;
+       case 1: mpeg = 1;  break;
+       }
+       init(kr, kb, mpeg);
+}
 
-       for(int i = 0; i < 0x10000; i++) {
-// compression
-               rtoy_tab_16[i] = (int)(R_TO_Y * 0x100 * i);
-               rtou_tab_16[i] = (int)(R_TO_U * 0x100 * i);
-               rtov_tab_16[i] = (int)(R_TO_V * 0x100 * i);
-
-               gtoy_tab_16[i] = (int)(G_TO_Y * 0x100 * i);
-               gtou_tab_16[i] = (int)(G_TO_U * 0x100 * i);
-               gtov_tab_16[i] = (int)(G_TO_V * 0x100 * i);
+void YUV::init(double Kr, double Kb, int mpeg)
+{
+       this->mpeg   = mpeg;
+       int ymin = !mpeg? 0 : 16;
+       int ymax = !mpeg? 255 : 235;
+       int uvmin = !mpeg? 0 : 16;
+       int uvmax = !mpeg? 255 : 240;
+       this->ymin8  = ymin;
+       this->ymax8  = ymax;
+       this->ymin16 = ymin*0x100;
+       this->ymax16 = (ymax+1)*0x100 - 1;
+       this->yzero  = 0x10000 * ymin;
+       this->uvmin8  = uvmin;
+       this->uvmax8  = uvmax;
+       this->uvmin16 = uvmin*0x100;
+       this->uvmax16 = (uvmax+1)*0x100 - 1;
+       this->uvzero = 0x800000;
+       this->yminf = ymin / 256.;
+       this->ymaxf = (ymax+1) / 256.;
+       this->yrangef = ymaxf - yminf;
+       this->uvminf = uvmin / 256.;
+       this->uvmaxf = (uvmax+1) / 256.;
+       this->uvrangef = uvmaxf - uvminf;
+       this->Kr = Kr;
+       this->Kg = 1. - Kr - Kb;
+       this->Kb = Kb;
+       double R_to_Y = Kr;
+       double G_to_Y = Kg;
+       double B_to_Y = Kb;
+       double R_to_U = -0.5*Kr/(1-Kb);
+       double G_to_U = -0.5*Kg/(1-Kb);
+       double B_to_U =  0.5;
+       double R_to_V =  0.5;
+       double G_to_V = -0.5*Kg/(1-Kr);
+       double B_to_V = -0.5*Kb/(1-Kr);
+       double V_to_R =  2.0*(1-Kr);
+       double V_to_G = -2.0*Kr*(1-Kr)/Kg;
+       double U_to_G = -2.0*Kb*(1-Kb)/Kg;
+       double U_to_B =  2.0*(1-Kb);
+
+       this->r_to_y = yrangef * R_to_Y;
+       this->g_to_y = yrangef * G_to_Y;
+       this->b_to_y = yrangef * B_to_Y;
+       this->r_to_u = uvrangef * R_to_U;
+       this->g_to_u = uvrangef * G_to_U;
+       this->b_to_u = uvrangef * B_to_U;
+       this->r_to_v = uvrangef * R_to_V;
+       this->g_to_v = uvrangef * G_to_V;
+       this->b_to_v = uvrangef * B_to_V;
+       this->v_to_r = V_to_R / uvrangef;
+       this->v_to_g = V_to_G / uvrangef;
+       this->u_to_g = U_to_G / uvrangef;
+       this->u_to_b = U_to_B / uvrangef;
+       
+       init_tables(0x100,
+               rtoy8, rtou8, rtov8,
+               gtoy8, gtou8, gtov8,
+               btoy8, btou8, btov8,
+               ytab8, vtor8, vtog8, utog8, utob8);
+       init_tables(0x10000,
+               rtoy16, rtou16, rtov16,
+               gtoy16, gtou16, gtov16,
+               btoy16, btou16, btov16,
+               ytab16, vtor16, vtog16, utog16, utob16); 
+       init_tables(0x100,
+               vtor8f, vtog8f, utog8f, utob8f);
+       init_tables(0x10000,
+               vtor16f, vtog16f, utog16f, utob16f);
+}
 
-               btoy_tab_16[i] = (int)(B_TO_Y * 0x100 * i);
-               btou_tab_16[i] = (int)(B_TO_U * 0x100 * i) + 0x800000;
-               btov_tab_16[i] = (int)(B_TO_V * 0x100 * i) + 0x800000;
+void YUV::init_tables(int len,
+               int *rtoy, int *rtou, int *rtov,
+               int *gtoy, int *gtou, int *gtov,
+               int *btoy, int *btou, int *btov,
+               int *ytab,
+               int *vtor, int *vtog,
+               int *utog, int *utob)
+{
+// rgb->yuv
+       double s = (double)0xffffff / len;
+       double r2y = s*r_to_y, g2y = s*g_to_y, b2y = s*b_to_y;
+       double r2u = s*r_to_u, g2u = s*g_to_u, b2u = s*b_to_u;
+       double r2v = s*r_to_v, g2v = s*g_to_v, b2v = s*b_to_v;
+       for( int rgb=0; rgb<len; ++rgb ) {
+               rtoy[rgb] = r2y*rgb;  rtou[rgb] = r2u*rgb;  rtov[rgb] = r2v*rgb;
+               gtoy[rgb] = g2y*rgb;  gtou[rgb] = g2u*rgb;  gtov[rgb] = g2v*rgb;
+               btoy[rgb] = b2y*rgb;  btou[rgb] = b2u*rgb;  btov[rgb] = b2v*rgb;
        }
 
-       vtor_16 = &(vtor_tab_16[(0x10000) / 2]);
-       vtog_16 = &(vtog_tab_16[(0x10000) / 2]);
-       utog_16 = &(utog_tab_16[(0x10000) / 2]);
-       utob_16 = &(utob_tab_16[(0x10000) / 2]);
-
-       for(int i = (-0x10000) / 2; i < (0x10000) / 2; i++) {
-// decompression
-               vtor_16[i] = (int)(V_TO_R * 0x100 * i);
-               vtog_16[i] = (int)(V_TO_G * 0x100 * i);
+// yuv->rgb
+       int y0  = ymin8 * len/0x100,  y1 = (ymax8+1) * len/0x100 - 1;
+       s = (double)0xffffff / (y1 - y0);
+       int y = 0, iy = 0;
+       while( y < y0 ) ytab[y++] = 0;
+       while( y < y1 ) ytab[y++] = s*iy++;
+       while( y < len ) ytab[y++] = 0xffffff;
+
+       int uv0 = uvmin8 * len/0x100, uv1 = (uvmax8+1) * len/0x100 - 1;
+       s = (double)0xffffff / (uv1 - uv0);
+       double v2r = s*v_to_r, v2g = s*v_to_g;
+       double u2g = s*u_to_g, u2b = s*u_to_b;
+       int uv = 0, iuv = uv0 - len/2;
+       int vr0 = v2r * iuv, vg0 = v2g * iuv;
+       int ug0 = u2g * iuv, ub0 = u2b * iuv;
+       while( uv < uv0 ) {
+               vtor[uv] = vr0;  vtog[uv] = vg0;
+               utog[uv] = ug0;  utob[uv] = ub0;
+               ++uv;
+       }
+       while( uv < uv1 ) {
+               vtor[uv] = iuv * v2r;  vtog[uv] = iuv * v2g;
+               utog[uv] = iuv * u2g;  utob[uv] = iuv * u2b;
+               ++uv;  ++iuv;
+       }
+       int vr1 = v2r * iuv, vg1 = v2g * iuv;
+       int ug1 = u2g * iuv, ub1 = u2b * iuv;
+       while( uv < len ) {
+               vtor[uv] = vr1;  vtog[uv] = vg1;
+               utog[uv] = ug1;  utob[uv] = ub1;
+               ++uv;
+       }
+}
 
-               utog_16[i] = (int)(U_TO_G * 0x100 * i);
-               utob_16[i] = (int)(U_TO_B * 0x100 * i);
+void YUV::init_tables(int len,
+               float *vtorf, float *vtogf, float *utogf, float *utobf)
+{
+       int len1 = len-1, len2 = len/2;
+       for( int i=0,k=-len2; i<len; ++i,++k ) {
+               vtorf[i] = (v_to_r * k)/len1;
+               vtogf[i] = (v_to_g * k)/len1;
+               utogf[i] = (u_to_g * k)/len1;
+               utobf[i] = (u_to_b * k)/len1;
        }
 }
 
 YUV::~YUV()
 {
+       delete [] tab;
+       delete [] tabf;
 }