Alpha 混合的算法很简单,基于下面的公式就可以实现:
D := A * (S - D) / 255 + D
D 是目标图像的像素,
S 是源图像的像素
A 是 Alpha 值, 0 为全透明, 255 为不透明。
下面是 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[i];
pDst := BmpDst.ScanLine[i];
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;
dwAd