Patch from Xavier Thomas:
authorMatt Ebb <matt@mke3.net>
Tue, 30 Mar 2010 23:32:16 +0000 (23:32 +0000)
committerMatt Ebb <matt@mke3.net>
Tue, 30 Mar 2010 23:32:16 +0000 (23:32 +0000)
YCbCr conversion function according to ITU-R BT.601/709 and JFIF

Clarifies color space usage in rgb->ycc conversion, doesn't change existing results.

source/blender/blenlib/BLI_math_color.h
source/blender/blenlib/intern/math_color.c
source/blender/nodes/intern/CMP_nodes/CMP_channelMatte.c
source/blender/nodes/intern/CMP_nodes/CMP_chromaMatte.c
source/blender/nodes/intern/CMP_nodes/CMP_sepcombYCCA.c
source/blender/nodes/intern/CMP_util.c

index 8c84df9c2459435703e3807876c6915300b6e602..72724c1c0f78c3575785d40adc51680ef33e9e51 100644 (file)
@@ -41,20 +41,25 @@ extern "C" {
 #define BLI_PR_NONE            0
 #define BLI_PR_SRGB            1
 #define BLI_PR_REC709  2
+
+/* YCbCr */
+#define BLI_YCC_ITU_BT601      0
+#define BLI_YCC_ITU_BT709      1
+#define BLI_YCC_JFIF_0_255     2
        
 /******************* Conversion to RGB ********************/
 
 void hsv_to_rgb(float h, float s, float v, float *r, float *g, float *b);
 void hex_to_rgb(char *hexcol, float *r, float *g, float *b);
 void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb);
-void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb);
+void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace);
 void xyz_to_rgb(float x, float y, float z, float *r, float *g, float *b, int colorspace);
 void cpack_to_rgb(unsigned int col, float *r, float *g, float *b);
 
 /***************** Conversion from RGB ********************/
 
 void rgb_to_yuv(float r, float g, float b, float *ly, float *lu, float *lv);
-void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr);
+void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace);
 void rgb_to_hsv(float r, float g, float b, float *lh, float *ls, float *lv);
 unsigned int rgb_to_cpack(float r, float g, float b);
 unsigned int hsv_to_cpack(float h, float s, float v);
index a1bb2754d95c7a252071900d9d3e8df36f521886..6aa85d140848ce2301db0a8b27fee6076122c20f 100644 (file)
@@ -109,7 +109,9 @@ void yuv_to_rgb(float y, float u, float v, float *lr, float *lg, float *lb)
        *lb=b;
 }
 
-void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr)
+/* The RGB inputs are supposed gamma corrected and in the range 0 - 1.0f */
+/* Output YCC have a range of 16-235 and 16-240 exepect with JFIF_0_255 where the range is 0-255 */
+void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr, int colorspace)
 {
        float sr,sg, sb;
        float y, cr, cb;
@@ -118,24 +120,53 @@ void rgb_to_ycc(float r, float g, float b, float *ly, float *lcb, float *lcr)
        sg=255.0f*g;
        sb=255.0f*b;
        
-       
-       y=(0.257f*sr)+(0.504f*sg)+(0.098f*sb)+16.0f;
-       cb=(-0.148f*sr)-(0.291f*sg)+(0.439f*sb)+128.0f;
-       cr=(0.439f*sr)-(0.368f*sg)-(0.071f*sb)+128.0f;
+       switch (colorspace) {
+       case BLI_YCC_ITU_BT601 :
+               y=(0.257f*sr)+(0.504f*sg)+(0.098f*sb)+16.0f;
+               cb=(-0.148f*sr)-(0.291f*sg)+(0.439f*sb)+128.0f;
+               cr=(0.439f*sr)-(0.368f*sg)-(0.071f*sb)+128.0f;
+               break;
+       case BLI_YCC_ITU_BT709 :
+               y=(0.183f*sr)+(0.614f*sg)+(0.062f*sb)+16.0f;
+               cb=(-0.101f*sr)-(0.338f*sg)+(0.439f*sb)+128.0f;
+               cr=(0.439f*sr)-(0.399f*sg)-(0.040f*sb)+128.0f;
+               break;
+       case BLI_YCC_JFIF_0_255 :
+               y=(0.299f*sr)+(0.587f*sg)+(0.114f*sb)+16.0f;
+               cb=(-0.16874f*sr)-(0.33126f*sg)+(0.5f*sb)+128.0f;
+               cr=(0.5f*sr)-(0.41869f*sg)-(0.08131f*sb)+128.0f;
+               break;
+       }
        
        *ly=y;
        *lcb=cb;
        *lcr=cr;
 }
 
-void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb)
+
+/* YCC input have a range of 16-235 and 16-240 exepect with JFIF_0_255 where the range is 0-255 */
+/* RGB outputs are in the range 0 - 1.0f */
+void ycc_to_rgb(float y, float cb, float cr, float *lr, float *lg, float *lb, int colorspace)
 {
        float r,g,b;
        
-       r=1.164f*(y-16.0f)+1.596f*(cr-128.0f);
-       g=1.164f*(y-16.0f)-0.813f*(cr-128.0f)-0.392f*(cb-128.0f);
-       b=1.164f*(y-16.0f)+2.017f*(cb-128.0f);
-       
+       switch (colorspace) {
+       case BLI_YCC_ITU_BT601 :
+               r=1.164f*(y-16.0f)+1.596f*(cr-128.0f);
+               g=1.164f*(y-16.0f)-0.813f*(cr-128.0f)-0.392f*(cb-128.0f);
+               b=1.164f*(y-16.0f)+2.017f*(cb-128.0f);
+               break;
+       case BLI_YCC_ITU_BT709 :
+               r=1.164f*(y-16.0f)+1.793f*(cr-128.0f);
+               g=1.164f*(y-16.0f)-0.534f*(cr-128.0f)-0.213f*(cb-128.0f);
+               b=1.164f*(y-16.0f)+2.115f*(cb-128.0f);
+               break;
+       case BLI_YCC_JFIF_0_255 :
+               r=y+1.402f*cr - 179.456f;
+               g=y-0.34414f*cb - 0.71414f*cr + 135.45984f;
+               b=y+1.772f*cb - 226.816f;
+               break;
+       }
        *lr=r/255.0f;
        *lg=g/255.0f;
        *lb=b/255.0f;
index b1fe0a2897b6e0d75336b7249f3cc64034de6bb1..ca7c19cc77837d3c1524d944b4509e2fe2a6b367 100644 (file)
@@ -45,7 +45,7 @@ static bNodeSocketType cmp_node_channel_matte_out[]={
 static void do_normalized_rgba_to_ycca2(bNode *node, float *out, float *in)
 {
        /*normalize to the range 0.0 to 1.0) */
-       rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+       rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
        out[0]=(out[0])/255.0;
        out[1]=(out[1])/255.0;
        out[2]=(out[2])/255.0;
@@ -58,7 +58,7 @@ static void do_normalized_ycca_to_rgba2(bNode *node, float *out, float *in)
        in[0]=in[0]*255.0;
        in[1]=in[1]*255.0;
        in[2]=in[2]*255.0;
-       ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+       ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
        out[3]=in[3];
 }
 
index a8d7ff6b029a0b34a8b38df9cd2790b372025dca..b081880b87bff95226aa617a6c49b2a8ce3b73a5 100644 (file)
@@ -45,7 +45,7 @@ static bNodeSocketType cmp_node_chroma_out[]={
 static void do_rgba_to_ycca_normalized(bNode *node, float *out, float *in)
 {
        /*normalize to the range -1.0 to 1.0) */
-       rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+       rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
        out[0]=((out[0])-16)/255.0;
        out[1]=((out[1])-128)/255.0;
        out[2]=((out[2])-128)/255.0;
@@ -58,7 +58,7 @@ static void do_ycca_to_rgba_normalized(bNode *node, float *out, float *in)
        in[0]=(in[0]*255.0)+16;
        in[1]=(in[1]*255.0)+128;
        in[2]=(in[2]*255.0)+128;
-       ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+       ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
        out[3]=in[3];
 }
 
index e42fafe58e5eec08ccfa554c8502c54924d8222d..7b3dfccab5078d65fdb94a642272fe7e1194aa39 100644 (file)
@@ -47,7 +47,7 @@ static void do_sepycca(bNode *node, float *out, float *in)
 {
        float y, cb, cr;
        
-       rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr);
+       rgb_to_ycc(in[0], in[1], in[2], &y, &cb, &cr, BLI_YCC_ITU_BT601);
        
        /*divided by 255 to normalize for viewing in */
        out[0]= y/255.0;
@@ -62,7 +62,7 @@ static void node_composit_exec_sepycca(void *data, bNode *node, bNodeStack **in,
        if(in[0]->data==NULL) {
                float y, cb, cr;
        
-               rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr);
+               rgb_to_ycc(in[0]->vec[0], in[0]->vec[1], in[0]->vec[2], &y, &cb, &cr, BLI_YCC_ITU_BT601);
        
                /*divided by 255 to normalize for viewing in */
                out[0]->vec[0] = y/255.0;
@@ -136,7 +136,7 @@ static void do_comb_ycca(bNode *node, float *out, float *in1, float *in2, float
        cb=in2[0]*255;
        cr=in3[0]*255;
 
-       ycc_to_rgb(y,cb,cr, &r, &g, &b);
+       ycc_to_rgb(y,cb,cr, &r, &g, &b, BLI_YCC_ITU_BT601);
        
        out[0] = r;
        out[1] = g;
index 6e53e8bb9682137cfe3362acbeb3c871e9b029d1..336694a4788eaaa3bc77a391b769eccea3a50571 100644 (file)
@@ -671,7 +671,7 @@ void do_rgba_to_hsva(bNode *node, float *out, float *in)
 
 void do_rgba_to_ycca(bNode *node, float *out, float *in)
 {
-   rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+   rgb_to_ycc(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
    out[3]=in[3];
 }
 
@@ -689,7 +689,7 @@ void do_hsva_to_rgba(bNode *node, float *out, float *in)
 
 void do_ycca_to_rgba(bNode *node, float *out, float *in)
 {
-   ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2]);
+   ycc_to_rgb(in[0],in[1],in[2], &out[0], &out[1], &out[2], BLI_YCC_ITU_BT601);
    out[3]=in[3];
 }