在red
的SharpDx BGRA偏移为16]
(color >> 16) & 255
请参见here。
但是在.NET中,red
的ARGB偏移也是16:
private const int ARGBRedShift = 16;
我很困惑,对吗?
此(如.NET):
public int PackeColorToArgb()
{
int value = B;
value |= G << 8;
value |= R << 16;
value |= A << 24;
return (int)value;
}
或此(例如SharpDx):
public int PackeColorToArgb()
{
int value = A;
value |= B << 8;
value |= G << 16;
value |= R << 24;
return (int)value;
}
对于.Net 0xFFFF0000
,是Argb Red
,但是对于SharpDx,这是Bgra Red
。什么是对的?
将BGRA和ARGB颜色打包为int的正确方法
这取决于您要在哪里使用int
。但是对于您提供的两个示例,您将以完全相同的方式将字节值打包为整数值。他们都是“正确的”。只是名称不同而已,同一事物可以有许多不同的名称。
重要的是,您的第二个代码示例(对于SharpDx来说应该是“正确的”)对于要查询的颜色格式是not正确的。您可以在引用的源代码中看到正确的内容,同时按A,B,G和R,LSB的顺序将字节打包到MSB时,组件的正确顺序实际上是BGRA(同样,从LSB到MSB)。
您的第二个代码示例应该看起来像第一个。
长版…
从您注意到的两个源代码参考中可以看到,实际格式为identical。也就是说,每个API的格式都以相同的顺序在每个32位整数中存储每个颜色分量的字节值:蓝色的最低8位,然后是绿色,红色,最高8位为alpha。 。
问题是,对于[[naming]]这样的格式没有统一的标准。在.NET的上下文中,它们按大端顺序列出颜色成分(这可能有点讽刺意味,因为很多Windows生态系统都基于小端顺序硬件,但请参阅下文)。即最重要的字节排在最前面:“ ARGB”。我将此名称称为“ big-endian顺序”,只是因为该名称与一种以big-endian模式运行的计算机上的内存中以4字节的顺序存储32位整数的情况相一致。名称中组件缩写的顺序与在该上下文中出现的顺序相同。另一方面,在SharpDx的上下文中,名称与您在little-endian硬件上看到的字节顺序一致。蓝色字节将首先出现在内存中,然后是绿色,红色,最后是字母。
事实是,这两者都是任意的。虽然现在大多数主流PC都在低端模式下运行,这可能会支持SharpDx命名方案(该格式继承自DirectX环境),但这些API都可以在大端硬件上找到,尤其是.NET Core越来越受欢迎。而且在很多情况下,使用API的程序员甚至都不在乎字节的顺序。对于必须处理单个字节的代码,这仍然很重要,但是很多时候,更多的是知道正在使用的工具使用哪种格式写入位图,然后确保已为API指定了正确的格式。
所有这些,我怀疑差异的主要原因与大端与小端无关,而更多与负责API的人员之间的基本哲学差异有关。事实是,即使在big-endian硬件上,像素(其组件以BGRA顺序显示在内存中)的SharpDx格式也将是
“ BGRA”
。因为位图格式不会因为硬件的字节顺序模式不同而改变。像素是not整数。这只是一个字节序列。所不同的是,移位值将必须不同,即取反,以便对于确实将像素视为单个32位整数的代码,它可以正确访问各个组件。相反,在我看来,.NET设计人员已经认识到,其API的用户大部分时间将使用较高级别的颜色(例如,设置笔或画笔的颜色),而不是像素级别的颜色。位图,因此按照常规顺序命名像素格式更有意义。另一方面,在SharpDx中,人们处理低级像素数据的频率更高,在这种情况下,具有能反映像素的实际字节顺序的名称的名称更为合理。实际上,您所引用的.NET代码不涉及位图数据。关于
“ ARGB”
命名法,Color
结构一次只能处理单个int
值。从概念上讲,我们想象数字采用大端数字格式(即使是十进制,即最重要的数字在前),因此ARGB更具可读性。另一方面,在.NET涉及像素格式的字节顺序的区域中,您会发现命名可以追溯到代表实际的字节顺序,例如WPF引入的PixelFormats
列表。清澈见底吧? :)PixelFormats