使用C++进行 LAB 转换

LAB conversion using C++

本文关键字:转换 LAB 进行 C++ 使用      更新时间:2023-10-16

我正在使用这个函数将图像的RGB颜色转换为LAB空间。我不明白第 13、14 和 15 行,因为它们使用特定的符号 (>>) 和十六进制数字:

void RGB2LAB(
    const vector<uint> &             ubuff,
    vector<double>&                 lvec,
    vector<double>&                 avec,
    vector<double>&                 bvec)
{
    int sz = int(ubuff.size());
    lvec.resize(sz);
    avec.resize(sz);
    bvec.resize(sz);
    for( int j = 0; j < sz; j++ )
    {
        int sR = (ubuff[j]>> 16) & 0xFF;   //<----
        int sG = (ubuff[j] >>  8) & 0xFF;  //<----
        int sB = (ubuff[j]  ) & 0xFF;      //<----
        //------------------------
        // sRGB to XYZ conversion
        // (D65 illuminant assumption)
        //------------------------
        double R = sR/255.0;
        double G = sG/255.0;
        double B = sB/255.0;
        double r, g, b;
        if(R <= 0.04045)    r = R/12.92;
        else                r = pow((R+0.055)/1.055,2.4);
        if(G <= 0.04045)    g = G/12.92;
        else                g = pow((G+0.055)/1.055,2.4);
        if(B <= 0.04045)    b = B/12.92;
        else                b = pow((B+0.055)/1.055,2.4);
        double X = r*0.4124564 + g*0.3575761 + b*0.1804375;
        double Y = r*0.2126729 + g*0.7151522 + b*0.0721750;
        double Z = r*0.0193339 + g*0.1191920 + b*0.9503041;
        //------------------------
        // XYZ to LAB conversion
        //------------------------
        double epsilon = 0.008856;  //actual CIE standard
        double kappa   = 903.3;     //actual CIE standard
        double Xr = 0.950456;   //reference white
        double Yr = 1.0;        //reference white
        double Zr = 1.088754;   //reference white
        double xr = X/Xr;
        double yr = Y/Yr;
        double zr = Z/Zr;
        double fx, fy, fz;
        if(xr > epsilon)    fx = pow(xr, 1.0/3.0);
        else                fx = (kappa*xr + 16.0)/116.0;
        if(yr > epsilon)    fy = pow(yr, 1.0/3.0);
        else                fy = (kappa*yr + 16.0)/116.0;
        if(zr > epsilon)    fz = pow(zr, 1.0/3.0);
        else                fz = (kappa*zr + 16.0)/116.0;
        lvec[j] = 116.0*fy-16.0;
        avec[j] = 500.0*(fx-fy);
        bvec[j] = 200.0*(fy-fz);
    }


}

这些符号的真正含义和收入是什么? 它们是转换的强制性要求吗?

让我们分解一下:

ubuffuint -s 的向量。每个uint由 32 位(可能是 64 位,但对于此解释并不重要)或 4 个字节组成。

因此,单个值,例如 ubuff[j]在内存中将如下所示:

|-- Byte1 --|-- Byte2 --|-- Byte3 --|-- Byte4 --|

现在我们已经解决了这个问题,让我们谈谈运算符>>。这是右移运算符,它的作用是将内存中的位向右旋转。例如:

ubuff[j] >> 8 // ==> |-- ByteX --|-- Byte1 --|-- Byte2 --|-- Byte3 --|

请注意所有位如何向右移动 8 个位置(正好是一个字节)。左侧的新字节根据原始最高有效位(最左侧位)使用 0 或 1 填充。

现在让我们谈谈&运算符。它对位执行按位 AND 操作。例如:

(ubuff[j] >> 8) & 0xFF // ==> |-- ByteX --|-- Byte1 --|-- Byte2 --|-- Byte3 --|
                       // AND |-- 0x00  --|-- 0x00  --|-- 0x00  --|-- 0xFF  --|
                       // RES |-- 0x00  --|-- 0x00  --|-- 0x00  --|-- Byte3 --|

所以,我们实际上只剩下原始ubuff[j] Byte3

其他表达式也是如此:

int sR = (ubuff[j] >> 16) & 0xFF; // ==> Byte2
int sG = (ubuff[j] >>  8) & 0xFF; // ==> Byte3
int sB = (ubuff[j]      ) & 0xFF; // ==> Byte4