为什么这个函数用按位运算符以这种方式转换

本文关键字:转换 运算符 方式 函数 为什么 | 更新日期: 2023-09-27 18:35:09

我正在为一个设备编写一个控制类,直到我需要将 ARGB 颜色转换为其格式。 起初,我写了这个函数(有效):

private static int convertFormat(System.Drawing.Color c)
{
    String all;
    int a = (int)((float)c.A / 31.875);
    if (a == 0)
        a = 1;
    all = a.ToString() + c.B.ToString("X").PadLeft(2, '0') + c.G.ToString("X").PadLeft(2, '0') + c.R.ToString("X").PadLeft(2, '0');
    int num = int.Parse(all, System.Globalization.NumberStyles.AllowHexSpecifier);
    return num;
}

但它太丑了,我想写一个更优雅的解决方案。所以我做了一些 for 来获得正确的值,尝试 0 到 50 之间的所有组合。它奏效了,我最终得到了这个:

private static int convertFormatShifting(System.Drawing.Color c)
{
    int alpha = (int)Math.Round((float)c.A / 31.875);
    int a = Math.Max(alpha,1);
    return (a << 24) | (c.B << 48) | (c.G << 40) | (c.R << 32);
}

哪个有效!

但是现在,我希望有人向我解释为什么这些是正确的转换值。

为什么这个函数用按位运算符以这种方式转换

最不容易混淆的移位值应如下所示:

return (a << 24) | (c.B << 16) | (c.G << 8) | (c.R << 0);
// Of course there's no need to shift by zero  ^^^^^^^^

您的值起作用的原因是移位运算符mod右侧,操作数的位长度在左侧。换句话说,以下所有移位都相互等效:

c.G << 8
c.G << 40
c.G << 72
c.G << 104
...

根据维基百科,RGBA格式遵循以下约定:

semantics alpha | red | green | blue
bits      31-24 |23-16|15 -  8|7 - 0

这类似于您的班次。您正在将位向左移动,并用有点明智的OR将它们连接起来。然后看看你的函数应该返回什么(int内颜色的顺序是什么)。