全自动油炸机厂家
免费服务热线

Free service

hotline

010-00000000
全自动油炸机厂家
热门搜索:
技术资讯
当前位置:首页 > 技术资讯

16位图像Alpha混合的实现 软件编程OS 免费猫

发布时间:2020-02-17 12:56:34 阅读: 来源:全自动油炸机厂家

16位图像Alpha混合的实现 - 软件编程/OS - 电子工程网

下面是 16 位 565 格式的混合算法的实现,首先用最简单的方式实现,即逐个像素的处理:

// 一次处理一个像素,比较简单,但速度较慢

procedure AlphaBlend656(BmpDst, BmpSrc: TBitmap; Alpha: Byte);

var

i, j, W, H: Integer;

pSrc, pDst: PWord;

wSR, wSG, wSB: Word;

wDR, wDG, wDB: Word;

begin

// 确定高宽

if BmpDst.Width BmpSrc.Width then

W := BmpSrc.Width

else

W := BmpDst.Width;

if BmpDst.Height BmpSrc.Height then

H := BmpSrc.Height

else

H := BmpDst.Height;

for i := 0 to H - 1do

begin

pSrc := BmpSrc.ScanLine;

pDst := BmpDst.ScanLine;

for j := 0 to W - 1 do

begin

// D := A * (S - D) / 255 + D

wSR := (pSrc^ shr 11);

wSG := (pSrc^ shr 5) and $3F;

wSB := pSrc^ and $1F;

wDR := (pDst^ shr 11);

wDG := (pDst^ shr 5) and $3F;

wDB := pDst^ and $1F;

pDst^ := (((Alpha * (wSR - wDR) shr 8) + wDR) shl 11) or

(((Alpha * (wSG - wDG) shr 8) + wDG) shl 5) or

((Alpha * (wSB - wDB) shr 8) + wDB);

Inc(pSrc);

Inc(pDst);

end;

end;

end;

实现起来很简单,但速度比较慢,其实存在着一次处理两个像素的算法,下面是代码:

// 一次处理两个像素 , 所以速度是 AlphaBlend656 的 2 倍

procedure AlphaBlend656Fast(BmpDst, BmpSrc: TBitmap; Alpha: Byte);

var

i, j, W, H: Integer;

pSrc, pDst: PWord;

dwSR, dwSG, dwSB: LongWord;

dwDR, dwDG, dwDB: LongWord;

dwAdd64 : LongWord;

dwAlphaOver4 : LongWord;

odd: Boolean;

begin

// 确定高宽

if BmpDst.Width BmpSrc.Width then

W := BmpSrc.Width

else

W := BmpDst.Width;

if BmpDst.Height BmpSrc.Height then

H := BmpSrc.Height

else

H := BmpDst.Height;

dwAdd64 := 64 or ( 64 shl 16 );

dwAlphaOver4 := ( Alpha shr 2 ) or ( ( Alpha shr 2 ) shl 16 );

if (W and $01) = 1 then

begin

odd := True;

W := (W - 1) shr 1;

end

else begin

odd := False;

W := W shr 1;

end;

for i := 0 to H - 1 do

begin

pSrc := BmpSrc.ScanLine;

pDst := BmpDst.ScanLine;

for j := 0 to W - 1 do

begin

// D := A * (S - D) / 255 + D

dwSR := (PLongWord(pSrc)^ shr 11) and $001F001F;

dwSG := (PLongWord(pSrc)^ shr 5) and $003F003F;

dwSB := PLongWord(pSrc)^ and $001F001F;

dwDR := (PLongWord(pDst)^ shr 11) and $001F001F;

dwDG := (PLongWord(pDst)^ shr 5) and $003F003F;

dwDB := PLongWord(pDst)^ and $001F001F;

PLongWord(pDst)^ := ((((Alpha * (dwSR + dwAdd64 - dwDR)) shr 8) + dwDR - dwAlphaOver4) and $001F001F) shl 11 or

((((Alpha * (dwSG + dwAdd64 - dwDG)) shr 8) + dwDG - dwAlphaOver4 ) and $003F003F) shl 5 or

(((Alpha * (dwSB + dwAdd64 - dwDB)) shr 8) + dwDB - dwAlphaOver4 ) and $001F001F;

Inc(pSrc, 2);

Inc(pDst, 2);

end;

if odd then

begin

dwSR := (pSrc^ shr 11);

dwSG := (pSrc^ shr 5) and $3F;

dwSB := pSrc^ and $1F;

dwDR := (pDst^ shr 11);

dwDG := (pDst^ shr 5) and $3F;

dwDB := pDst^ and $1F;

pDst^ := Word((((Alpha * (dwSR - dwDR) shr 8) + dwDR) shl 11) or

(((Alpha * (dwSG - dwDG) shr 8) + dwDG) shl 5) or

((Alpha * (dwSB - dwDB) shr 8) + dwDB));

Inc(pSrc);

Inc(pDst);

end;

end;

end;

不过这还不够快,基本 MMX 指令的实现可以一次处理 4 个像素,下面是代码:

// 利用 MMX 优化指令,一次可以处理 4 个像素,因此速度应该是 AlphaBlend656 的 4 倍

procedure AlphaBlend656MMX(BmpDst, BmpSrc: TBitmap; Alpha: Byte);

var

i, j, W, H, Leave: Integer;

pSrc, pDst: PWord;

MaskR, MaskG, MaskB, Alpha64: Int64;

wSR, wSG, wSB: Word;

wDR, wDG, wDB: Word;

begin

// 确定高宽

if BmpDst.Width BmpSrc.Width then

W := BmpSrc.Width

else

W := BmpDst.Width;

if BmpDst.Height BmpSrc.Height then

H := BmpSrc.Height

else

H := BmpDst.Height;

Leave := W and 3; // 剩余的像素

W := W shr 2; // 一次处理 4 个像素,因此取 W 整除 4 的值

// 提取 RGB 通道的掩码

MaskR := $f800f800f800f800;

MaskG := $07e007e007e007e0;

MaskB := $001f001f001f001f;

// Alpha 值扩展到 64 位

Alpha64 := Alpha;

Alpha64 := Alpha64 or (Alpha64 shl 16) or (Alpha64 shl 32) or (Alpha64 shl 48);

for i := 0 to H - 1do

begin

pSrc := BmpSrc.ScanLine;

pDst := BmpDst.ScanLine;

asm

push ecx // 保存寄存器

mov ecx, W // 设宽度

cmp ecx, 0 // 宽度是否为 0

jz @@exit565 // 如果宽度为 0 ,结束

push esi

push edi

mov esi, pSrc // 开始处理

mov edi, pDst

@@blend565_4:

{ mmx 的作用:

mm0: red target value

mm1: red source value

mm2: green target value

mm3: green source value

mm4: blue target value

mm5: blue source value

mm6: original target pixel

mm7: original source pixel

D := A * (S - D) / 255 + D

}

movq mm6, [edi]

movq mm7, [esi]

movq mm0, mm6

pand mm0, MaskR // 提取目标的 R 通道

movq mm1, mm7

pand mm1, MaskR // 提取源的 R 通道

psrlw mm0, 11 // 右移到最低位,便于接下来的计算

psrlw mm1, 11

psubw mm1, mm0 // SrcRed := SrcRed - DestRed

pmullwmm1, Alpha64 // SrcRed := SrcRed * Alpha

psraw mm1, 8 // SrcRed := SrcRed div 8

paddw mm1, mm0 // SrcRed := SrcRed + DestRed

psllw mm1, 11 // 左移回原来的位置,此已经 R 通道混合已经完毕

movq mm2, mm6

pand mm2, MaskG // 提取目标的 G 通道

movq mm3, mm7

pand mm3, MaskG // 提取源的 G 通道

psrlw mm2, 5 // 右移到最低位,便于接下来的计算

psrlw mm3, 5

psubw mm3, mm2 // SrcGreen := SrcGreen - DestGreen

pmullwmm3, Alpha64 // SrcGreen := SrcGreen * Alpha

psraw mm3, 8 // SrcGreen := SrcGreen div 8

paddw mm3, mm2 // SrcGreen := SrcGreen + DestGreen

psllw mm3, 5 // 左移回原来的位置,此已经 G 通道混合已经完毕

movq mm4, mm6

pand mm4, MaskB // 提取目标的 B 通道

movq mm5, mm7

pand mm5, MaskB // 提取源的 B 通道

psubw mm5, mm4 // SrcBlue := SrcBlue - DestBlue

pmullwmm5, Alpha64 // SrcBlue := SrcBlue * Alpha

psraw mm5, 8 // SrcBlue := SrcBlue div 8

paddw mm5, mm4 // SrcBlue := SrcBlue + DestBlue ,此已经 B 通道混合已经完毕

por mm1, mm3 // 合成像素

por mm1, mm5

movq [edi], mm1 // 赋给目标

add esi, 8 // 下 4 个像素

add edi, 8

dec ecx

jnz @@blend565_4

mov pSrc, esi

mov pDst, edi

pop edi

pop esi

emms

@@exit565:

pop ecx

end;

// 处理剩下的像素

for j := 0 to Leave - 1 do

begin

wSR := (pSrc^ shr 11);

wSG := (pSrc^ shr 5) and $3F;

wSB := pSrc^ and $1F;

wDR := (pDst^ shr 11);

wDG := (pDst^ shr 5) and $3F;

wDB := pDst^ and $1F;

pDst^ := (((Alpha * (wSR - wDR) shr 8) + wDR) shl 11) or

(((Alpha * (wSG - wDG) shr 8) + wDG) shl 5) or

((Alpha * (wSB - wDB) shr 8) + wDB);

Inc(pSrc);

Inc(pDst);

end;

end;

end;

下面是这三个函数的速度比较,目标图像是 600*450 的 16 位位图,源图像是 399*532 的 16 位位图,分别进行了 1000 次混合,结果如下:

AlphaBlend656 : 4516

AlphaBlend656Fast : 2562

AlphaBlend656MMX : 1234

没有意外, MMX 版本比普通的快了近 4 倍

对于图像处理的优化有两个比较重要的点:

1、 尽量用位移代替乘除。

2、 一次能够同时处理多个像素,利用 MMX 指令可以做到这一点。

最后是代码:

https://files.getdropbox.com/u/524963/AlphaBlend16_565.rar

宁河县旗袍

旗袍金丝

章鱼兰的种植方法

张衡的故事