`
javasogo
  • 浏览: 1835045 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

16位图像Alpha混合的实现

阅读更多

<!-- [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混合算法代码(c语言)

    在计算机图形学中,Alpha混合(Alpha Blending)是一种用于实现图像或像素的半透明效果的技术。这种技术广泛应用于2D和3D图形渲染、游戏开发、图像编辑软件等领域。在C语言中实现Alpha混合算法,可以让我们更好地...

    基于FPGA的Alpha半透明图像叠加算法硬件实现.pdf

    Alpha通道技术是通过8位灰度通道实现的,利用256个灰度级别来记录图像中各像素点的透明度信息,其中黑色代表全透明,白色代表不透明,灰色代表不同程度的半透明。这种技术允许用户通过调整Alpha值(介于0到1之间)来...

    duff-porter_alpha混合_Thomas!_

    Alpha混合是一种将两个或多个具有不同透明度(Alpha通道)的图像进行合成的方法。在2D图形中,我们通常有一个前景图像和一个背景图像,Alpha通道是一个额外的灰度图像,用于表示每个像素的透明程度。灰度值越高,...

    AlphaBlend_alpha混合_Alpha_Direct3D_

    在计算机图形学领域,Alpha混合(Alpha Blending)是一种重要的技术,用于实现图像或像素的透明和半透明效果。在DirectX编程中,它被广泛应用于游戏开发、图像处理和其他实时渲染应用。本文将深入探讨Alpha混合的...

    RGB颜色Alpha混合.rar

    了解RGB颜色和Alpha混合的概念,以及如何在易语言中实现这一功能,有助于提升程序员在图像处理领域的技能。通过深入研究提供的源码,不仅可以学习到颜色混合的原理,还能掌握易语言的编程技巧,这对于开发涉及图形...

    VS2008下的win32Alpha混合的例子

    在本文中,我们将深入探讨如何在Visual Studio 2008 (VS2008)环境下使用DirectX 2009(DX2009)实现Win32应用程序中的Alpha混合技术,以创建一个飞机模型的混合效果。Alpha混合是一种图形处理技术,用于将两个或多个...

    dx9 alpha混合纹理

    本文将深入探讨DX9中的Alpha混合纹理,以及如何通过原代码实现这一功能。 首先,我们要理解Alpha通道的概念。在RGB颜色模型中,Alpha通道负责表示颜色的透明度,0表示完全透明,255表示完全不透明。在纹理中,每个...

    dx9_alpha_blending_material.zip_Alpha_alpha混合_direct Alpha_direc

    在DirectX 9中,Alpha混合(Alpha Blending)是一种重要的图形渲染技术,它允许我们创建半透明或透明效果,使图像元素能够彼此混合,从而产生丰富的视觉效果。这个压缩包"dx9_alpha_blending_material.zip"显然是为...

    嵌入式图形处理器Alpha混合单元设计与实现.pdf

    Alpha混合是图形处理中的一个关键步骤,它涉及到图像层之间的透明度控制,使得多层图像能够平滑地融合在一起,创造出深度感和复杂的视觉效果。本文主要介绍了一种针对嵌入式GPU的Alpha混合单元的设计与实现方法。 ...

    3D地表多纹理按Alpha通道混合

    4. **splatshader.psh**:这可能是一个像素着色器(Pixel Shader)文件,用于定义如何在GPU上处理每个像素的颜色和Alpha值,以实现纹理混合。着色器通常包含数学和逻辑运算,用于计算最终的颜色输出。 5. **...

    python opencv 图像边框(填充)添加及图像混合的实现方法(末尾实现类似幻灯片渐变的效果)

    在Python的OpenCV库中,图像处理功能非常丰富,其中包括为图像添加边框以及实现图像混合。这两个功能在视觉效果的创建、图像编辑和动画制作中都有广泛应用。 **图像边框的实现** 图像边框的添加是通过`cv2....

    易语言图像透明混合模块

    透明通道混合可能涉及到的算法包括Alpha blending,这是一种基于Alpha值的像素混合方式,通过将两个图像的像素值和Alpha值进行加权平均来实现混合效果。 "与字节混合"可能是指将图像的像素数据与单个字节进行操作,...

    OpenGL_Alpha.rar_Alpha_gl 混合_opengl alpha

    Alpha混合允许我们在渲染图像时实现半透明效果,使得不同颜色之间能够自然地融合,创造出深度感和真实感。本示例是为了解决初学者在使用OpenGL进行Alpha混合时遇到的常见问题而设计的。 在OpenGL中,Alpha通道通常...

    山东大学数字图像处理实验1-3

    用alpha混合,为a.png替换一张新的背景(背景图自选); 2.1:图像缩放 实现一个图像缩放函数,可以对输入图像进行任意倍数的缩放; 采用双线性插值进行重采样; X,Y方向的缩放倍数参函数参数的形式传入; 可以只考虑...

    易语言RGB颜色Alpha混合源码.zip

    而Alpha混合则是RGB颜色模型的一个扩展,引入了透明度的概念,使得图像可以有不同程度的不透明度,即所谓的“半透明”效果。 易语言,作为一款中国本土开发的、面向初学者的编程语言,提供了对RGB和Alpha混合的支持...

    数字图像处理 图像合成

    OpenCV是一个广泛使用的开源库,提供了丰富的函数来处理图像和进行图像合成,如图像读取、图像转换、滤波操作以及混合函数等。 为了实现图像合成,我们需要遵循以下步骤: 1. 读取图像:使用OpenCV的imread函数加载...

    易语言RGB颜色Alpha混合源码

    在易语言中实现RGB颜色的Alpha混合,主要是通过对两个颜色的R、G、B分量进行线性插值运算,并结合Alpha值来计算出混合后颜色的分量。这种技术在计算机图形学中被称为Alpha blending。其基本公式可以表示为: ```...

    位图透明绘制, alpha混合 完整示例代码

    `表示源图像将按照阿尔法通道覆盖目标图像,这是一种最常见的混合模式。`bf.BlendFlags = 0;`保持默认设置,`bf.AlphaFormat = 0;`表示阿尔法值存储在源颜色的最后一个字节中。`bf.SourceConstantAlpha`是一个0到255...

    OpenCV实现初级图像混合(C++实现).zip

    在本项目中,我们将深入探讨如何使用OpenCV库在C++环境中实现初级图像混合。OpenCV,全称为Open Source Computer Vision Library,是一个广泛应用于图像处理和计算机视觉领域的开源库。它提供了丰富的函数和结构,...

    数字图像处理:JAVA语言实现

    10. **图像合成**:结合多个图像生成新的图像,如图像拼接、 alpha 混合等。 11. **JAVA图像处理库**:如OpenCV的JAVA接口,它可以提供更高级的图像处理功能,如对象识别、人脸识别等。 在"CODE"文件夹中,你可能...

Global site tag (gtag.js) - Google Analytics