由于FMX TBITMAP实现具有PixelFormat为仅读取属性,因此我无法像以前那样使用VCL TBITMAP来创建一个空的TBITMAP之后,将其设置为32bits。此示例显示了如何使用fmx rutines getpixel,setPixel:http://members.adug.org.au/2012/101/10/10/05/read-write-image-image-image-bitmap-pixels-/
使用fmx tbitmap.map()方法,我可以访问指向像素数据的指针,但是我不能假设其PixelforMat至32位。
我的目的是以32位的固定格式访问32bits位图,纹理或表面,以便我的2D图形库可以直接与该内存一起在屏幕上工作;无需在像素格式之间进行检查和转换。在图像处理的末尾,它可以复制到任何可见的表面,纹理或图像,以显示形式。
帮助您感谢!
要解决位图的扫描线的像素,您可以使用属性tbitmap.scanlines [0],它为您提供了指向图像的第一行的指针。要了解扫描线是如何用24个位图构造的,您可以看到David Heffernan和Tlama的文章:
如何将扫描线属性用于24位位图?
我已经创建了在Delphi下运行的汇编编程语言函数,并允许您从/到32位/Pixel位映像读取/编写像素(而24位/Pixel位图)。
。这是我的getPixelBmp32()和putpixelbmp32()函数的原型和功能:
type T_RGB_Temp=record {RGB color RECORD type}
Blue, {BLUE component from 0 to 255}
Green, {GREEN component from 0 to 255}
Red, {RED component from 0 to 255}
Mask {ALPHA channel from 0 to 255} :byte;
end;
T_Coord_XY=record {X and Y position RECORD type}
X, {X position}
Y {Y position} :smallint;
end;
T_Dim_XY=record {Width and height of bitmap RECORD type}
DimX, {Width}
DimY {Height} :word;
end;
function GetPixelBMp32(XY:T_Coord_XY;
BMp32_Dim_XY:T_Dim_XY;
ScanLine0:pointer):T_RGB_Temp;
procedure PutPixelBMp32(XY:T_Coord_XY;
BMp32_Dim_XY:T_Dim_XY;
ScanLine0:pointer;Pix:T_RGB_Temp);
给定的bitmap32:用pixelformat =(pf32bit,pfcustom)定义的tbitmap,scanline0参数必须始终为bitmap32.scanline [0];如果scanline0 = nil,什么也不会发生。
bmp32_dim_xy.dimx和bmp32_dim_xy.dimy是给定图像的尺寸;如果您使用类型cast bmp32_dim_xy.dimx:= word(width:smallInt)或bmp32_dim_xy.dimx:= word(height:smallInt),宽度或高度是负面的。
xy.x和xy.y是像素的坐标;它们可能是负面的或大于给定图像的大小,但是在这种情况下,什么都没有发生。
pix.red,pix.green,pix.blue,pix.mask是像素的8位颜色组件。pix是T_RGB_TEMP类型;GetPixelBmp32()的结果也是相同类型的。
位图的扫描线的组织是相反的,就好像记忆中的图像相对于x轴镜像;因此
此外,如果扫描线的字节数不是4的倍数(与dword的对齐),如24位/像素格式中,则在扫描线的末端添加0到3个字节(对齐)(对齐)。
计算24个位图的对齐方式是通过:a::=(tbitmap.width 3)而不是3。
以下是上述函数的定义(32位/像素图像):
procedure PutPixelBMp32(XY:T_Coord_XY;
BMp32_Dim_XY:T_Dim_XY;
ScanLine0:pointer;Pix:T_RGB_Temp); assembler;
{ eax edx ecx are 1°, 2° and 3° parameters.
Can freely modify the eax, ecx, and edx registers. }
asm
push ebx
push esi
push edi
mov ebx,Pix {ebx <- Pix}
mov edi,BMp32_Dim_XY {edi <- edx <- BMp32_Dim_XY}
mov esi,ScanLine0 {esi <- ecx <- ScanLine0}
mov edx,XY {edx <- eax <- XY}
or esi,esi {If ScanLine0=Nil, ...}
je @@00 {... Exit}
movsx eax,di {eax <- DimX}
shr edi,16
movsx edi,di {edi <- DimY}
movsx ecx,dx {ecx <- X}
shr edx,16
movsx edx,dx {edx <- Y}
or eax,eax {If DimX<0, ...}
js @@00 {... Exit}
cmp ecx,eax {If X<0 or if X>=DimX, ...}
jae @@00 {... Exit}
or edi,edi {If DimY<0, ...}
js @@00 {... Exit}
cmp edx,edi {If Y<0 or if Y>=DimY, ...}
jae @@00 {... Exit}
lea ecx,[4*ecx] {ecx <- X position in byte}
lea esi,[esi+ecx] {Update source pointer and free ecx}
lea eax,[4*eax] {eax <- scanline size in byte}
mul edx {eax <- Y * (scanline size in byte)}
sub esi,eax {esi <- Pixel write target pointer}
mov [esi],ebx {bl <- Blue; bh <- Green; byte2(ebx) <- Red; byte3(ebx) <- Mask}
@@00:pop edi
pop esi
pop ebx
end;
function GetPixelBMp32(XY:T_Coord_XY;
BMp32_Dim_XY:T_Dim_XY;
ScanLine0:pointer):T_RGB_Temp; assembler;
{ eax edx ecx are 1°, 2° and 3° parameters.
Can freely modify the eax, ecx, and edx registers. }
asm
push esi
push edi
mov edi,BMp32_Dim_XY {edi <- edx <- BMp32_Dim_XY}
mov esi,ScanLine0 {esi <- ecx <- ScanLine0}
mov edx,XY {edx <- eax <- XY}
xor eax,eax {Inizializza @Result a 0}
or esi,esi {If ScanLine0=Nil, ...}
je @@00 {... Exit}
movsx eax,di {eax <- DimX}
shr edi,16
movsx edi,di {edi <- DimY}
movsx ecx,dx {ecx <- X}
shr edx,16
movsx edx,dx {edx <- Y}
or eax,eax {If DimX<0, ...}
js @@00 {... Exit}
cmp ecx,eax {If X<0 or if X>=DimX, ...}
jae @@00 {... Exit}
or edi,edi {If DimY<0, ...}
js @@00 {... Exit}
cmp edx,edi {If Y<0 or if Y>=DimY, ...}
jae @@00 {... Exit}
lea ecx,[4*ecx] {ecx <- X position in byte}
lea esi,[esi+ecx] {Update source pointer and free ecx}
lea eax,[4*eax] {eax <- scanline size in byte}
mul edx {eax <- Y * (scanline size in byte)}
sub esi,eax {esi <- Pixel write target pointer}
mov eax,[esi] {al <- Blue; ah <- Green; byte2(eax) <- Red; byte3(eax) <- Mask}
@@00:pop edi
pop esi
end;
以下是已经定义了参数类型的函数的定义(24位/像素图像):
procedure PutPixelBMp24(XY:T_Coord_XY;
BMp24_Dim_XY:T_Dim_XY;
ScanLine0:pointer;Pix:T_RGB_Temp); assembler;
{ eax edx ecx are 1°, 2° and 3° parameters.
Can freely modify the eax, ecx, and edx registers. }
asm
push ebx
push esi
push edi
mov ebx,Pix {ebx <- Pix}
mov edi,BMp24_Dim_XY {edi <- edx <- BMp24_Dim_XY}
mov esi,ScanLine0 {esi <- ecx <- ScanLine0}
mov edx,XY {edx <- eax <- XY}
or esi,esi {If ScanLine0=Nil, ...}
je @@00 {... Exit}
movsx eax,di {eax <- DimX}
shr edi,16
movsx edi,di {edi <- DimY}
movsx ecx,dx {ecx <- X}
shr edx,16
movsx edx,dx {edx <- Y}
or eax,eax {If DimX<0, ...}
js @@00 {... Exit}
cmp ecx,eax {If X<0 or if X>=DimX, ...}
jae @@00 {... Exit}
or edi,edi {If DimY<0, ...}
js @@00 {... Exit}
cmp edx,edi {If Y<0 or if Y>=DimY, ...}
jae @@00 {... Exit}
lea ecx,[ecx+2*ecx]{ecx <- X position in byte}
lea esi,[esi+ecx] {Update source pointer and free ecx}
lea eax,[eax+2*eax]{eax <- scanline size in byte}
add eax,3 {Process in eax ...}
and eax,0FFFFFFFCH {... The dword aligned scanline size in byte}
mul edx {eax <- Y * (dword aligned scanline size in byte)}
sub esi,eax {esi <- Pixel write target pointer}
mov [esi],bx {bl <- Blue; bh <- Green}
shr ebx,8 {bh <- Red}
mov [esi+2],bh {bh <- Red}
@@00:pop edi
pop esi
pop ebx
end;
function GetPixelBMp24(XY:T_Coord_XY;
BMp24_Dim_XY:T_Dim_XY;
ScanLine0:pointer):T_RGB_Temp; assembler;
{ eax edx ecx are 1°, 2° and 3° parameters.
Can freely modify the eax, ecx, and edx registers. }
asm
push esi
push edi
mov edi,BMp24_Dim_XY {edi <- edx <- BMp24_Dim_XY}
mov esi,ScanLine0 {esi <- ecx <- ScanLine0}
mov edx,XY {edx <- eax <- XY}
xor eax,eax {Inizializza @Result a 0}
or esi,esi {If ScanLine0=Nil, ...}
je @@00 {... Exit}
movsx eax,di {eax <- DimX}
shr edi,16
movsx edi,di {edi <- DimY}
movsx ecx,dx {ecx <- X}
shr edx,16
movsx edx,dx {edx <- Y}
or eax,eax {If DimX<0, ...}
js @@00 {... Exit}
cmp ecx,eax {If X<0 or if X>=DimX, ...}
jae @@00 {... Exit}
or edi,edi {If DimY<0, ...}
js @@00 {... Exit}
cmp edx,edi {If Y<0 or if Y>=DimY, ...}
jae @@00 {... Exit}
lea ecx,[ecx+2*ecx]{ecx <- X position in byte}
lea esi,[esi+ecx] {Update source pointer and free ecx}
lea eax,[eax+2*eax]{eax <- scanline size in byte}
add eax,3 {Process in eax ...}
and eax,0FFFFFFFCH {... The dword aligned scanline size in byte}
mul edx {eax <- Y * (dword aligned scanline size in byte)}
sub esi,eax {esi <- Pixel write target pointer}
mov ax,[esi+1] {al -> Green; ah -> Red}
shl eax,8 {B2 -> Red; B1 -> Green}
mov al,[esi] {B0 -> Blue}
@@00:pop edi
pop esi
end;
如果您需要更高的传输速度,则是简化版本,但没有检查传入参数的正确性,getPixelBmp32()和putpixelbmp32()函数:
procedure PutPixelBMp32(XY:T_Coord_XY;
BMp24_Dim_XY:T_Dim_XY;
ScanLine0:pointer;Pix:T_RGB_Temp); assembler;
{ eax edx ecx are 1°, 2° and 3° parameters.
Can freely modify the eax, ecx, and edx registers. }
asm
push ebx
push esi
mov ebx,Pix {ebx <- Pix}
mov esi,ScanLine0 {esi <- ecx <- ScanLine0}
mov eax,XY {eax <- eax <- XY}
mov edx,BMp32_Dim_XY {edx <- edx <- BMp32_Dim_XY}
movzx edx,dx {edx <- DimX}
movzx ecx,ax {ecx <- X}
shr eax,16
movzx eax,ax {eax <- Y}
lea ecx,[4*ecx] {ecx <- X position in byte}
lea esi,[esi+ecx] {Update source pointer and free ecx}
lea edx,[4*edx] {edx <- scanline size in byte}
mul edx {eax <- Y * (scanline size in byte)}
sub esi,eax {esi <- Pixel write target pointer}
mov [esi],ebx {bl <- Blue; bh <- Green; byte2(ebx) <- Red; byte3(ebx) <- Mask}
pop esi
pop ebx
end;
function GetPixelBMp32(XY:T_Coord_XY;
BMp24_Dim_XY:T_Dim_XY;
ScanLine0:pointer):T_RGB_Temp; assembler;
{ eax edx ecx are 1°, 2° and 3° parameters.
Can freely modify the eax, ecx, and edx registers. }
asm
push esi
mov esi,ScanLine0 {esi <- ecx <- ScanLine0}
mov eax,XY {eax <- eax <- XY}
mov edx,BMp32_Dim_XY {edx <- edx <- BMp32_Dim_XY}
movzx edx,dx {edx <- DimX}
movzx ecx,ax {ecx <- X}
shr eax,16
movzx eax,ax {eax <- Y}
lea ecx,[4*ecx] {ecx <- X position in byte}
lea esi,[esi+ecx] {Update source pointer and free ecx}
lea edx,[4*edx] {edx <- scanline size in byte}
mul edx {edx <- Y * (scanline size in byte)}
sub esi,eax {esi <- Pixel write target pointer}
mov eax,[esi] {al <- Blue; ah <- Green; byte2(eax) <- Red; byte3(eax) <- Mask}
pop esi
end;