What's wrong with this RGB to XYZ color space conversion algorithm?

后端 未结 6 1237
无人及你
无人及你 2020-12-29 06:35

My goal is to convert an RGB pixel into CIELab color space for some special calculations only possible in CIELab. For this, I must convert RGB to XYZ first, which is the rea

6条回答
  •  [愿得一人]
    2020-12-29 07:32

    As they said:

    var_R = ( R / 255 )  ->  var_R = ( R / 255.0 ) or var_R = ( R * 0.003922 ) 
    var_G = ( G / 255 )  ->  var_G = ( G / 255.0 ) or var_G = ( G * 0.003922 )
    var_B = ( B / 255 )  ->  var_B = ( B / 255.0 ) or var_B = ( B * 0.003922 )
    

    This is because of implicit conversion. Despite the fact that var_R, var_G and var_B variables are float type, the / operator sees two integers R, G, B and 255. it has to divide and returns an integer.

    In order to get a float type value you can do a CAST or convert at least one of the variables into float type adding of a decimal point as follows:

    var_B = ( B / 255.0f)

    Another example of RGB2LAB and LAB2RGB conversion (bear in mind that is CIE Lab D65):

    void RGB2LAB(uint8_t R, uint8_t G, uint8_t B, float *l, float *a, float *b) {
        float RGB[3], XYZ[3];
    
        RGB[0] = R * 0.003922;
        RGB[1] = G * 0.003922;
        RGB[2] = B * 0.003922;
    
        RGB[0] = (RGB[0] > 0.04045) ? pow(((RGB[0] + 0.055)/1.055), 2.4) : RGB[0] / 12.92;
        RGB[1] = (RGB[1] > 0.04045) ? pow(((RGB[1] + 0.055)/1.055), 2.4) : RGB[1] / 12.92;
        RGB[2] = (RGB[2] > 0.04045) ? pow(((RGB[2] + 0.055)/1.055), 2.4) : RGB[2] / 12.92;
    
        XYZ[0] = 0.412424  * RGB[0] + 0.357579 * RGB[1] + 0.180464  * RGB[2];
        XYZ[1] = 0.212656  * RGB[0] + 0.715158 * RGB[1] + 0.0721856 * RGB[2];
        XYZ[2] = 0.0193324 * RGB[0] + 0.119193 * RGB[1] + 0.950444  * RGB[2];
    
        *l = 116 * ( ( XYZ[1] / 1.000000) > 0.008856 ? pow(XYZ[1] / 1.000000, 0.333333) : 7.787 * XYZ[1] / 1.000000 + 0.137931) - 16;
        *a = 500 * ( ((XYZ[0] / 0.950467) > 0.008856 ? pow(XYZ[0] / 0.950467, 0.333333) : 7.787 * XYZ[0] / 0.950467 + 0.137931) - ((XYZ[1] / 1.000000) > 0.008856 ? pow(XYZ[1] / 1.000000, 0.333333) : 7.787 * XYZ[1] / 1.000000 + 0.137931) );
        *b = 200 * ( ((XYZ[1] / 1.000000) > 0.008856 ? pow(XYZ[1] / 1.000000, 0.333333) : 7.787 * XYZ[1] / 1.000000 + 0.137931) - ((XYZ[2] / 1.088969) > 0.008856 ? pow(XYZ[2] / 1.088969, 0.333333) : 7.787 * XYZ[2] / 1.088969 + 0.137931) );
    }
    
    void LAB2RGB(float L, float A, float B, uint8_t *r, uint8_t *g, uint8_t *b) {
        float XYZ[3], RGB[3];
    
        XYZ[1] = (L + 16 ) / 116;
        XYZ[0] = A / 500 + XYZ[1];
        XYZ[2] = XYZ[1] - B / 200;
    
        XYZ[1] = (XYZ[1]*XYZ[1]*XYZ[1] > 0.008856) ? XYZ[1]*XYZ[1]*XYZ[1] : (XYZ[1] - (16 / 116)) / 7.787;
        XYZ[0] = (XYZ[0]*XYZ[0]*XYZ[0] > 0.008856) ? XYZ[0]*XYZ[0]*XYZ[0] : (XYZ[0] - (16 / 116)) / 7.787;
        XYZ[2] = (XYZ[2]*XYZ[2]*XYZ[2] > 0.008856) ? XYZ[2]*XYZ[2]*XYZ[2] : (XYZ[2] - (16 / 116)) / 7.787;
    
        RGB[0] = 0.950467 * XYZ[0] *  3.2406 + 1.000000 * XYZ[1] * -1.5372 + 1.088969 * XYZ[2] * -0.4986;
        RGB[1] = 0.950467 * XYZ[0] * -0.9689 + 1.000000 * XYZ[1] *  1.8758 + 1.088969 * XYZ[2] *  0.0415;
        RGB[2] = 0.950467 * XYZ[0] *  0.0557 + 1.000000 * XYZ[1] * -0.2040 + 1.088969 * XYZ[2] *  1.0570;
    
        *r = (255 * ( (RGB[0] > 0.0031308) ? 1.055 * (pow(RGB[0], (1/2.4)) - 0.055) : RGB[0] * 12.92 ));
        *g = (255 * ( (RGB[1] > 0.0031308) ? 1.055 * (pow(RGB[1], (1/2.4)) - 0.055) : RGB[1] * 12.92 ));
        *b = (255 * ( (RGB[2] > 0.0031308) ? 1.055 * (pow(RGB[2], (1/2.4)) - 0.055) : RGB[2] * 12.92 ));
    }
    

提交回复
热议问题