<!-- [if gte mso 9]><xml>
<w:WordDocument>
<w:View>Normal</w:View>
<w:Zoom>0</w:Zoom>
<w:PunctuationKerning/>
<w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing>
<w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery>
<w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery>
<w:ValidateAgainstSchemas/>
<w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid>
<w:IgnoreMixedContent>false</w:IgnoreMixedContent>
<w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText>
<w:Compatibility>
<w:SpaceForUL/>
<w:BalanceSingleByteDoubleByteWidth/>
<w:DoNotLeaveBackslashAlone/>
<w:ULTrailSpace/>
<w:DoNotExpandShiftReturn/>
<w:AdjustLineHeightInTable/>
<w:BreakWrappedTables/>
<w:SnapToGridInCell/>
<w:WrapTextWithPunct/>
<w:UseAsianBreakRules/>
<w:DontGrowAutofit/>
<w:UseFELayout/>
</w:Compatibility>
<w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel>
</w:WordDocument>
</xml><![endif]--><!-- [if gte mso 9]><xml>
<w:LatentStyles DefLockedState="false" LatentStyleCount="156">
</w:LatentStyles>
</xml><![endif]--><!-- [if !mso]>
<
classid="clsid:38481807-CA0E-42D2-BF39-B33AF135CC4D" id=ieooui>
</object>
<mce:style><!--
st1\:*{behavior:url(#ieooui) }
-->
<!-- [endif]-->
<!-- [if gte mso 10]>
<mce:style><!--
/* Style Definitions */
table.MsoNormalTable
{mso-style-name:普通表格;
mso-tstyle-rowband-size:0;
mso-tstyle-colband-size:0;
mso-style-noshow:yes;
mso-style-parent:"";
mso-padding-alt:0cm 5.4pt 0cm 5.4pt;
mso-para-margin:0cm;
mso-para-margin-bottom:.0001pt;
mso-pagination:widow-orphan;
font-size:10.0pt;
font-family:"Times New Roman";
mso-ansi-language:#0400;
mso-fareast-language:#0400;
mso-bidi-language:#0400;}
-->
<!-- [endif]-->
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;
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[i];
pDst := BmpDst.ScanLine[i];
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[i];
pDst := BmpDst.ScanLine[i];
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
pmullw
mm1, 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
pmullw
mm3, 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
pmullw
mm5, 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
倍
对于图像处理的优化有两个比较重要的点:
<!-- [if !supportLists]-->1、
<!-- [endif]-->尽量用位移代替乘除。
<!-- [if !supportLists]-->2、
<!-- [endif]-->一次能够同时处理多个像素,利用
MMX
指令可以做到这一点。
最后是代码:
https://files.getdropbox.com/u/524963/AlphaBlend16_565.rar
分享到:
相关推荐
在计算机图形学中,Alpha混合(Alpha Blending)是一种用于实现图像或像素的半透明效果的技术。这种技术广泛应用于2D和3D图形渲染、游戏开发、图像编辑软件等领域。在C语言中实现Alpha混合算法,可以让我们更好地...
Alpha通道技术是通过8位灰度通道实现的,利用256个灰度级别来记录图像中各像素点的透明度信息,其中黑色代表全透明,白色代表不透明,灰色代表不同程度的半透明。这种技术允许用户通过调整Alpha值(介于0到1之间)来...
Alpha混合是一种将两个或多个具有不同透明度(Alpha通道)的图像进行合成的方法。在2D图形中,我们通常有一个前景图像和一个背景图像,Alpha通道是一个额外的灰度图像,用于表示每个像素的透明程度。灰度值越高,...
在计算机图形学领域,Alpha混合(Alpha Blending)是一种重要的技术,用于实现图像或像素的透明和半透明效果。在DirectX编程中,它被广泛应用于游戏开发、图像处理和其他实时渲染应用。本文将深入探讨Alpha混合的...
了解RGB颜色和Alpha混合的概念,以及如何在易语言中实现这一功能,有助于提升程序员在图像处理领域的技能。通过深入研究提供的源码,不仅可以学习到颜色混合的原理,还能掌握易语言的编程技巧,这对于开发涉及图形...
在本文中,我们将深入探讨如何在Visual Studio 2008 (VS2008)环境下使用DirectX 2009(DX2009)实现Win32应用程序中的Alpha混合技术,以创建一个飞机模型的混合效果。Alpha混合是一种图形处理技术,用于将两个或多个...
本文将深入探讨DX9中的Alpha混合纹理,以及如何通过原代码实现这一功能。 首先,我们要理解Alpha通道的概念。在RGB颜色模型中,Alpha通道负责表示颜色的透明度,0表示完全透明,255表示完全不透明。在纹理中,每个...
在DirectX 9中,Alpha混合(Alpha Blending)是一种重要的图形渲染技术,它允许我们创建半透明或透明效果,使图像元素能够彼此混合,从而产生丰富的视觉效果。这个压缩包"dx9_alpha_blending_material.zip"显然是为...
Alpha混合是图形处理中的一个关键步骤,它涉及到图像层之间的透明度控制,使得多层图像能够平滑地融合在一起,创造出深度感和复杂的视觉效果。本文主要介绍了一种针对嵌入式GPU的Alpha混合单元的设计与实现方法。 ...
4. **splatshader.psh**:这可能是一个像素着色器(Pixel Shader)文件,用于定义如何在GPU上处理每个像素的颜色和Alpha值,以实现纹理混合。着色器通常包含数学和逻辑运算,用于计算最终的颜色输出。 5. **...
在Python的OpenCV库中,图像处理功能非常丰富,其中包括为图像添加边框以及实现图像混合。这两个功能在视觉效果的创建、图像编辑和动画制作中都有广泛应用。 **图像边框的实现** 图像边框的添加是通过`cv2....
透明通道混合可能涉及到的算法包括Alpha blending,这是一种基于Alpha值的像素混合方式,通过将两个图像的像素值和Alpha值进行加权平均来实现混合效果。 "与字节混合"可能是指将图像的像素数据与单个字节进行操作,...
Alpha混合允许我们在渲染图像时实现半透明效果,使得不同颜色之间能够自然地融合,创造出深度感和真实感。本示例是为了解决初学者在使用OpenGL进行Alpha混合时遇到的常见问题而设计的。 在OpenGL中,Alpha通道通常...
用alpha混合,为a.png替换一张新的背景(背景图自选); 2.1:图像缩放 实现一个图像缩放函数,可以对输入图像进行任意倍数的缩放; 采用双线性插值进行重采样; X,Y方向的缩放倍数参函数参数的形式传入; 可以只考虑...
而Alpha混合则是RGB颜色模型的一个扩展,引入了透明度的概念,使得图像可以有不同程度的不透明度,即所谓的“半透明”效果。 易语言,作为一款中国本土开发的、面向初学者的编程语言,提供了对RGB和Alpha混合的支持...
OpenCV是一个广泛使用的开源库,提供了丰富的函数来处理图像和进行图像合成,如图像读取、图像转换、滤波操作以及混合函数等。 为了实现图像合成,我们需要遵循以下步骤: 1. 读取图像:使用OpenCV的imread函数加载...
在易语言中实现RGB颜色的Alpha混合,主要是通过对两个颜色的R、G、B分量进行线性插值运算,并结合Alpha值来计算出混合后颜色的分量。这种技术在计算机图形学中被称为Alpha blending。其基本公式可以表示为: ```...
`表示源图像将按照阿尔法通道覆盖目标图像,这是一种最常见的混合模式。`bf.BlendFlags = 0;`保持默认设置,`bf.AlphaFormat = 0;`表示阿尔法值存储在源颜色的最后一个字节中。`bf.SourceConstantAlpha`是一个0到255...
在本项目中,我们将深入探讨如何使用OpenCV库在C++环境中实现初级图像混合。OpenCV,全称为Open Source Computer Vision Library,是一个广泛应用于图像处理和计算机视觉领域的开源库。它提供了丰富的函数和结构,...
10. **图像合成**:结合多个图像生成新的图像,如图像拼接、 alpha 混合等。 11. **JAVA图像处理库**:如OpenCV的JAVA接口,它可以提供更高级的图像处理功能,如对象识别、人脸识别等。 在"CODE"文件夹中,你可能...