当使用32位TBitmap时,我从画布切换。像素到扫描线。
然后将值设置为红色,结果显示为蓝色。
知道为什么吗?
下面是代码摘录:
procedure TForm1.FormPaint(Sender: TObject);
var
varBitmap: TBitmap;
pLock: PIntegerArray;
iColor: integer;
begin
varBitmap := TBitmap.Create;
varBitmap.PixelFormat := pf32bit;
varBitmap.Width := 800;
varBitmap.Height := 600;
// Set Pixels to Red
varBitmap.Canvas.Pixels[0, 0] := $0000FF;
// Shows $FF0000 (blue)
pLock := varBitmap.ScanLine[0];
iColor := pLock[0];
ShowMessageFmt('%x', [iColor]);
// Set ScanLine to Red
pLock[0] := $0000FF;
// Displays a blue pixel
Canvas.Draw(0, 0, varBitmap);
end;
似乎不知何故TColor与内存中的内容不一样,但这没有意义。
欢迎提出任何建议。div;)
VCL位图类TBitmap
是Windows本机设备独立位图(DIB)的包装器。这些位图对象可以以各种不同的像素格式存储位图。它们可以是单色的,每像素一个比特,最多每像素32个比特,这是你正在使用的格式。它们还可以用于存储基于调色板的位图,其中每个像素包含一个颜色表的索引。
您所指的两种访问像素数据的方法是TCanvas
的Pixels
属性和TBitmap
的ScanLine
属性。
TCanvas
的Pixels
属性是GDI GetPixel
和SetPixel
函数的包装器。这些是对COLORREF
值进行操作的高级函数。COLORREF
的文档说:
低阶字节包含红色的相对强度值;第二个字节包含绿色的值;第三个字节包含蓝色的值。高阶字节必须为零。单个字节的最大值是0xFF。
换句话说,COLORREF
值具有固定的像素颜色编码方式。GetPixel
和SetPixel
函数主要处理固定的COLORREF
格式和底层原始位图像素数据之间的转换。还要注意,COLORREF
不能表示alpha值。COLORREF
的格式为$00BBGGRR。
另一方面,TBitmap
的ScanLine
属性返回指向底层DIB对象的原始像素数据的指针。您在这里使用的数据是32bpp像素数据,该数据的约定是以$AARRGGBB格式存储的。32bpp数据的Windows文档说:
位图最多有2^32种颜色。如果BITMAPINFOHEADER的biccompression成员为BI_RGB, BITMAPINFO的bmiColors成员为NULL。位图数组中的每个DWORD表示一个像素的蓝色、绿色和红色的相对强度。蓝色的值是最低有效的8位,绿色和红色各8位。没有使用每个DWORD中的高字节。
所以事实上这篇文章是不正确和过时的。每个DWORD
中的高字节实际上是alpha通道,如果它被使用的话。
32位像素数据为$AARRGGBB
格式。您正在设置蓝色组件,而不是红色组件。使用$FF0000
代替$0000FF
。或者使用RGB()
函数更好。