为什么像素和扫描线是不同的



当使用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个比特,这是你正在使用的格式。它们还可以用于存储基于调色板的位图,其中每个像素包含一个颜色表的索引。

您所指的两种访问像素数据的方法是TCanvasPixels属性和TBitmapScanLine属性。

TCanvasPixels属性是GDI GetPixelSetPixel函数的包装器。这些是对COLORREF值进行操作的高级函数。COLORREF的文档说:

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

换句话说,COLORREF值具有固定的像素颜色编码方式。GetPixelSetPixel函数主要处理固定的COLORREF格式和底层原始位图像素数据之间的转换。还要注意,COLORREF不能表示alpha值。COLORREF的格式为$00BBGGRR。

另一方面,TBitmapScanLine属性返回指向底层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()函数更好。

相关内容

  • 没有找到相关文章

最新更新