Delphi TBitmap - 为什么 Pixels 和 ScanLine 不同?

标签 delphi bitmap pixel scanline

在使用 32 位 TBitmap 时,我从 Canvas.Pixels 切换到 ScanLine。

然后我将值设置为红色,却发现它显示为蓝色。

知道为什么吗?

以下是代码摘录:

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 与内存中的不一样,但这没有意义。

欢迎任何建议。 ;)

最佳答案

VCL 位图类,TBitmap是 Windows native 设备独立位图 (DIB) 的包装器。这些位图对象可以存储多种不同像素格式的位图。它们可以是单色的,每像素一位,最多每像素 32 位,这是您正在使用的格式。它们还可以用于存储基于调色板的位图,其中每个像素都保存颜色表的索引。

访问您引用的像素数据的两种方法是 Pixels TCanvas的属性(property)和 ScanLine TBitmap的属性(property)。

Pixels TCanvas的属性(property)是 GDI GetPixel 的包装器和 SetPixel 功能。这些是在 COLORREF 上运行的高级函数。值(value)观。 COLORREF 的文档说:

The low-order byte contains a value for the relative intensity of red; the second byte contains a value for green; and the third byte contains a value for blue. The high-order byte must be zero. The maximum value for a single byte is 0xFF.

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

另一方面,ScanLine TBitmap的属性(property)返回一个指向底层 DIB 对象的原始像素数据的指针。您此处使用的数据是 32bpp 像素数据,该数据的约定是以 $AARRGGBB 格式存储。 Windows documentation对于 32bpp 数据说:

The bitmap has a maximum of 2^32 colors. If the biCompression member of the BITMAPINFOHEADER is BI_RGB, the bmiColors member of BITMAPINFO is NULL. Each DWORD in the bitmap array represents the relative intensities of blue, green, and red for a pixel. The value for blue is in the least significant 8 bits, followed by 8 bits each for green and red. The high byte in each DWORD is not used.

所以事实上这段文字是不正确的并且已经过时了。每个 DWORD 中的高字节事实上,如果使用的话,就是 Alpha channel 。

关于Delphi TBitmap - 为什么 Pixels 和 ScanLine 不同?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22291162/

相关文章:

delphi - TRzDirectoryTree设置当前目录

Delphi:GDI+ 和渐变框架/矩形的问题

delphi - 在 Delphi XE 中使用 JCL 没有堆栈跟踪

colors - iOS 5 + GLKView : How to access pixel RGB data for colour-based vertex picking?

python - Numpy 过滤器像素索引

c# - 将图像中的每个像素设置为颜色列表中最接近的匹配项

delphi - 将控制台应用程序与 GUI 应用程序一起使用?

c# - Image 和 Bitmap 类都没有实现自定义相等/哈希码逻辑的原因是什么?

c# - 当图像宽度超过 40,000 时渲染图像失败

c++ - MediaFoundation,位图数组到 mp4