1
2/**//************************************************************************/
3/**//* 普通模式的alpha混合 */
4/**//************************************************************************/
5void NormalAlphaBlend(
6 unsigned long* lpDst, // 目标缓冲
7 unsigned long iDstX, // 目标位置
8 unsigned long iDstY, // 目标位置
9 unsigned long iDstPitch, // 目标缓冲的pitch
10 unsigned long* lpSrc, // 原色彩缓冲
11 unsigned long iSrcX, // 原色彩位置
12 unsigned long iSrcY, // 原色彩位置
13 unsigned long iSrcW, // 原缓冲的尺寸
14 unsigned long iSrcH, // 原缓冲的尺寸
15 unsigned long iSrcPitch // 原色彩pitch
16 )
17{
18 // 需要是4的倍数
19 unsigned long *lpLinearDstBp=(iDstX)+(iDstY*iDstPitch/sizeof(DWORD))+lpDst; //base pointer for linear destination
20 unsigned long *lpLinearSrcBp=(iSrcX)+(iSrcY*iSrcPitch/sizeof(DWORD))+lpSrc; //base pointer for linear source
21
22 __asm{
23 mov esi,lpLinearSrcBp; // 移入源像素缓冲地址
24
25 mov edi,lpLinearDstBp; // 移入目标像素缓冲地址
26
27 mov ecx,iSrcH; // 下面两步操作是移入原缓冲的高度和宽度
28
29 mov ebx,iSrcW;
30
31MainLoop:
32 pxor mm2,mm2 // 把MM2清0
33
34 movd mm0,[esi] // 把Source像素取到mm0低32bit
35
36 movd mm1,[edi] // 把32 bit Dest像素取到mm1低32bit
37
38 punpcklbw mm0,mm2 // Source:8 bit到16 bit以容纳结果,32bit expand to 64 bit
39
40 punpcklbw mm1,mm2 // Dest:8 bit到16 bit以容纳结果.32bit expand to 64 bit
41
42 movq mm3,mm0 // 因为要用Src的Alpha值
43
44 punpckhwd mm3,mm3 // 高字移动到双字
45
46 punpckhdq mm3,mm3 // 双字移动到四字,现在有八个像素的Alpha了!
47
48 movd edx,mm3
49
50 cmp edx,0x00ff00ff; // 判断alpha值是否为255
51
52 je CopySrc; // 如果为255 那么拷贝源像素,不做alpha处理
53
54 test edx,0xffffffff; // 如果alpha为0 ,那么会影响寄存器的标志位,ZF=1
55
56 jz BeginPixel; // ZF=1,转至标号处执,如果alpha为0 那么读取下一个像素
57
58 //R(C)=alpha*R(B)/255+(255-alpha)/255*R(A) = ((R(B)-R(A))*alpha+R(A)*255)/255
59 // 显示颜色 = 源颜色 × alpha / 255 + 背景颜色 × (255 - alpha) / 255
60
61 psubusw mm0,mm1 // Source-Dest,饱和减,小于0为0
62
63 pmullw mm0,mm3 // Alpha * (Source-Overlay)
64
65 psllw mm1,8 // 左移动8位 目标*255
66
67 paddusw mm1,mm0 // 饱和加到原图象D=S-Alpha*(S-O),(Overlay-Source)>0 部分
68
69 psrlw mm1,8 // 右移动8位 混合结果/255
70
71 packuswb mm1,mm1 // 紧缩到低32bit
72
73 movd [edi],mm1 // 保存结果
74
75 jmp BeginPixel
76
77CopySrc:
78 packuswb mm0, mm0 // 紧缩到低
79
80 movd [edi],mm0; // 将源像素移动到目标像素中
81
82BeginPixel:
83 add edi,4; // 目标像素向前移动4个像素
84
85 add esi,4; // 源像素向前移动4个像素
86
87 sub ebx,1; // 宽度减4
88
89 test ebx,0xFFFFFFFF; // check if only 0 pixels left
90
91 jz NextLine; // 如果只有0个像素,跳转到NextLine处理
92
93 jmp MainLoop; // 跳转到开始处,重新计算
94
95NextLine:
96 dec ecx;
97
98 jz Done; // 处理完成
99
100 mov esi,lpLinearSrcBp; // src
101
102 mov edi,lpLinearDstBp; // dst
103
104 add esi,iSrcPitch; // inc src ptr by 1 line
105
106 add edi,iDstPitch; // inc dst ptr by 1 line
107
108 mov ebx,iSrcW; // ebx=span width to copy
109
110 mov lpLinearSrcBp,esi; // save new src base ptr
111
112 mov lpLinearDstBp,edi; // save new dst base ptr
113
114 jmp MainLoop; // start the next span
115Done:
116 emms // 必要的!Empty MMX Status
117 }
118
说明: 上面的代码参考过网上的示例,经过自己的修改! 如果效率不好的地方 请多多指教!