【问题标题】:Delphi TBitmap - why are Pixels and ScanLine different?Delphi TBitmap - 为什么像素和扫描线不同?
【发布时间】:2014-04-13 00:35:34
【问题描述】:

在使用 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 似乎在某种程度上与内存中的不一样,但这没有任何意义。

欢迎提出任何建议。 ;)

【问题讨论】:

    标签: delphi bitmap pixels scanline


    【解决方案1】:

    32 位像素数据为$AARRGGBB 格式。您正在设置蓝色组件,而不是红色组件。使用$FF0000 而不是$0000FF。或者更好的是,使用RGB() 函数。

    【讨论】:

    • SetPixel() 使用 0x00bbggrr 格式,而实际像素数据相反。
    • 啊,这就解释了。我在 ScanLine 上有一些使用 clRed 的自定义填充功能,但如果我理解正确,我不应该再使用这些 TColor 值。有时我觉得自己老了……叹息。
    【解决方案2】:

    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 documentation 说:

    位图最多有 2^32 种颜色。如果 BITMAPINFOHEADER 的 biCompression 成员为 BI_RGB,则 BITMAPINFO 的 bmiColors 成员为 NULL。位图数组中的每个 DWORD 代表一个像素的蓝色、绿色和红色的相对强度。蓝色的值是最低有效的 8 位,然后是绿色和红色各 8 位。每个 DWORD 中的高字节没有被使用。

    所以事实上这个文本是不正确和过时的。每个DWORD 中的高字节实际上是alpha 通道,如果使用的话。

    【讨论】:

    • 感谢您解释大卫。听起来他们需要稍微更新帮助文件。 ;)
    • 是的,它需要改进。我想在这里更详细地解释一下。
    猜你喜欢
    • 1970-01-01
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-08
    • 1970-01-01
    • 2020-07-24
    • 1970-01-01
    相关资源
    最近更新 更多