X-Git-Url: http://git.cinelerra-gg.org/git/?a=blobdiff_plain;f=cinelerra-5.1%2Fguicast%2Fbccolors.C;h=e587321d5d347f597e962fe752dccac642d3330f;hb=b55798fc64eee00c6fab3b4763e791befb7275f9;hp=48dcb02aa5acd649c69591311bb056d5b712bf03;hpb=9d832a1fff11b11aaa1108c460690ed05e2bdc05;p=goodguy%2Fhistory.git diff --git a/cinelerra-5.1/guicast/bccolors.C b/cinelerra-5.1/guicast/bccolors.C index 48dcb02a..e587321d 100644 --- a/cinelerra-5.1/guicast/bccolors.C +++ b/cinelerra-5.1/guicast/bccolors.C @@ -22,6 +22,7 @@ #include "bccolors.h" #include +#include 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,196 @@ 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; +float YUV::yuv_to_rgb_matrix[9]; +float YUV::rgb_to_yuv_matrix[9]; +float *const YUV::rgb_to_y_vector = YUV::rgb_to_yuv_matrix; - 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 BC_COLORS_BT601: kr = BT601_Kr; kb = BT601_Kb; break; + case BC_COLORS_BT709: kr = BT709_Kr; kb = BT709_Kb; break; + case BC_COLORS_BT2020: kr = BT2020_Kr; kb = BT2020_Kb; break; } + switch( color_range ) { + default: + case BC_COLORS_JPEG: mpeg = 0; break; + case BC_COLORS_MPEG: 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); + + rgb_to_yuv_matrix[0] = r_to_y; + rgb_to_yuv_matrix[1] = g_to_y; + rgb_to_yuv_matrix[2] = b_to_y; + rgb_to_yuv_matrix[3] = r_to_u; + rgb_to_yuv_matrix[4] = g_to_u; + rgb_to_yuv_matrix[5] = b_to_u; + rgb_to_yuv_matrix[6] = r_to_v; + rgb_to_yuv_matrix[7] = g_to_v; + rgb_to_yuv_matrix[8] = b_to_v; + + float yscale = 1.f / yrangef; + yuv_to_rgb_matrix[0] = yscale; + yuv_to_rgb_matrix[1] = 0; + yuv_to_rgb_matrix[2] = v_to_r; + yuv_to_rgb_matrix[3] = yscale; + yuv_to_rgb_matrix[4] = u_to_g; + yuv_to_rgb_matrix[5] = v_to_g; + yuv_to_rgb_matrix[6] = yscale; + yuv_to_rgb_matrix[7] = u_to_b; + yuv_to_rgb_matrix[8] = 0; +} - 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; rgbrgb + 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