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