为什么Windows GDI使用RGBA格式来表示`COLORREF`而不是BGRA?

7

MSDN states:

当指定明确的RGB颜色时,COLORREF值具有以下十六进制形式:

0x00bbggrr

低位字节包含红色的相对强度值;第二个字节包含绿色值;第三个字节包含蓝色值。高位字节必须为零。单个字节的最大值为0xFF。

来自wingdi.h

#define RGB(r,g,b)          ((COLORREF)((BYTE)(r) | ((BYTE)(g) << 8) | ((BYTE)(b) << 16)))

#define GetRValue(rgb)      ((BYTE)  (rgb) )
#define GetGValue(rgb)      ((BYTE) ((rgb) >> 8))
#define GetBValue(rgb)      ((BYTE) ((rgb) >> 16))

作为小端序的Windows,COLORREF以RGBA格式表示。这看起来很奇怪,因为Windows内部使用的颜色格式不是BGR(A)吗? RGBQUAD结构被定义为
typedef struct tagRGBQUAD {
  BYTE rgbBlue;
  BYTE rgbGreen;
  BYTE rgbRed;
  BYTE rgbReserved;
} RGBQUAD;

这里的 BGRA 和 COLORREF 不同,是一种像素格式。

因为 bitblt 函数需要一个 COLORREF 值的数组,所以每次调用时都会发生从 RGBA 到 BGRA 的额外转换,如果 Windows 使用的是 BGRA 作为其本机格式。

我记不清了,但我在某个地方也读到过 winapi 中使用的像素格式有奇怪的混合。

可以有人解释一下吗?


你的断言是不正确的;宏明显按照0x00bbggrr顺序组装COLORREF。再仔细看一下它们,或者编写一些使用它们的代码并观察结果。 - Clifford
6
Windows使用OS/2格式的BMP文件,而OS/2格式与Windows通常偏好的格式有一些不同。其中一个是您已经注意到的:R和B被翻转了。另一个是OS/2位图是自下而上而不是自上而下的。 - Raymond Chen
@RaymondChen 没错!由于这个原因,我总是不得不在指定位图高度时加上“-”。那么有没有一种方法可以在GDI中进行blit而不经过RGB格式转换呢? - user3810155
您可以将DIB选择到DC中,并直接从中进行blt。GDI将根据需要执行颜色翻转。 - Raymond Chen
BGRA结构实际上意味着颜色格式为ARGB,一个DWORD或4字节int从末尾读取。是这样吗?我正在尝试弄清楚如何在结构体中存储颜色,如果我希望颜色格式(在32位或4字节级别上)为RGBA,则必须将数字以ABGR(反向)的方式存储在结构体中。当整个颜色被读取时,它开始从结构体的末尾读取。 - Zebrafish
那么RGB宏创建了一个0x 00 BB GG RR,而RBGQuad结构是0x 00 RR GG BB,一个是ABGR,另一个是ARGB? - Zebrafish
1个回答

1
COLORREFs的历史可以追溯到像素格式标准化程度较低的年代。当时,许多图形适配器仍然使用调色板而不是全24位或32位颜色,因此即使适配器需要重新排序字节,也不需要进行很多次操作。一些图形适配器甚至将图像存储在单个多通道颜色平面而非单个平面中。那时候没有所谓的“正确”答案。
RGBQUADs源自BMP格式,如Raymond Chen在评论中提到的那样,该格式来自OS/2位图格式。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接