由于FMX TBitmap实现将PixelFormat设置为只读属性,因此我不能像以前使用VCL TBitmap那样,在创建空的TBitmap之后将其设置为32位。此示例说明如何使用FMX rutines GetPixel,SetPixel:http://members.adug.org.au/2012/10/05/read-write-image-bitmap-pixels-in-delphi-xe3/访问独立于PixelFormat的像素
使用FMX TBitmap.Map()方法,我可以访问指向像素数据的指针,但我不能假定它的PixelFormat为32位。
我的目的是访问32位位图、纹理或32位固定格式的表面,这样我的2D图形库就可以直接在屏幕外使用这些内存;而不需要每次都在像素格式之间进行检查和转换。在图像处理结束时,它可以复制到任何可见的表面、纹理或图像上,以便在表格中显示。
感谢您的帮助!
1条答案
按热度按时间zkure5ic1#
若要定位位图扫描线的像素,可以使用属性TBitMap.ScanLine[0],该属性提供指向图像第一行的指针。要了解扫描线是如何在24位位图中构造的,您可以查看David Heffernan和TLama在以下位置的文章:
How to use ScanLine property for 24-bit bitmaps?
我已经创建了在Delphi下运行的汇编语言函数,允许您从/向32位/像素位图读取/写入像素(对于24位/像素位图,还有2个以上)。
下面是我的GetPixelBMp32()和PutPixelBMp32()函数的原型和功能:
给定使用PixelFormat=(pf32Bit,pfCustom)定义的BitMap32:TBitMap,ScanLine0参数必须始终为BitMap32.ScanLine[0];如果ScanLine0=Nil,则不会发生任何情况。
BMp32_Dim_XY.DimX和BMp32_Dim_XY.DimY是给定图像的尺寸;如果使用类型强制转换BMp32_Dim_XY.DimX:=Word(Width:SmallInt)或BMp32_Dim_XY.DimX:=Word(Height:SmallInt),并且宽度或高度为负值,则不会发生任何事情。
XY.X和XY.Y是Pixel的坐标;它们可以是负数,也可以大于给定图像的大小,但在这种情况下,不会发生任何事情。
Pix.Red、Pix.Green、Pix.Blue、Pix.MASK是像素的8位颜色分量。PIX是T_RGB_TEMP类型的;GetPixelBMp32()的结果也是相同类型的。
位图扫描线的组织顺序是相反的,就好像内存中的图像是相对于X轴镜像的;因此,在内存中,TBitMap.ScanLine[0]之后的所有扫描线都位于较低的地址位置,就好像TBitMap.ScanLine[0]是最后一个扫描线,而不是第一个扫描线。
此外,如果扫描线的字节数不是4的倍数(对齐到DWord),如在24位/像素格式中,则在扫描线的末尾添加0到3个字节(对齐)。
24位位图的对齐方式为:A:=(TBitMap.Width+3),而不是3。
以下是上述函数(32位/像素图像)的定义:
下面是已经定义了参数类型的函数的定义(24位/像素图像):
如果您需要更高的传输速度,以下是GetPixelBMp32()和PutPixelBMp32()函数的简化版本,但不检查传入参数的正确性: