32 MMX Alpha混合算法

32 MMX Alpha混合算法
  1
  2 /**/ /************************************************************************/
  3 /**/ /* 普通模式的alpha混合       */
  4 /**/ /************************************************************************/
  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 {
 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



  说明: 上面的代码参考过网上的示例,经过自己的修改! 如果效率不好的地方 请多多指教!

你可能感兴趣的:(32 MMX Alpha混合算法)