|
图片太大。。。截一部分贴上来
桌面widget,自己写alphablend(MMX的),好吧,其实是粘贴别人的,关于mmx的alphablend网上一抓一大把。。我自己呢,MMX还没有完全搞懂。
来吧,代码。。
- void Widget_HTC_Weather::AlphaBlend32(UINT* pDstBmp, UINT* pSrcBmp, int bit_w, int bit_h, int rc_x, int rc_y, int rc_w, int rc_h, int x, int y, int sw, int sh, int blendalpha)
- {
-     // alpha异常
-     if (blendalpha < 0 || blendalpha > 255) return;
-     // rect尺寸为0或负
-     if (rc_w <= 0) return;
-     if (rc_h <= 0) return;
-     // 越界
-     if (x >= sw) return;
-     if (y >= sh) return;
-     if (rc_w + rc_x - 1 < 0) return;
-     if (rc_h + rc_y - 1 < 0) return;
-     if (x < 0)
-     {
-         rc_x -= x;
-         rc_w += x;
-         x = 0;
-     }
-     if (y < 0)
-     {
-         rc_y -= y;
-         rc_h += y;
-         y = 0;
-     }
-     if (rc_x >= bit_w) return;
-     if (rc_y >= bit_h) return;
-     // 修正边界
-     if (rc_x < 0)
-     {
-         rc_w += rc_x;
-         rc_x = 0;
-     }
-     if (rc_y < 0)
-     {
-         rc_h += rc_y;
-         rc_y = 0;
-     }
-     if (rc_x + rc_w > bit_w) rc_w = bit_w - rc_x;
-     if (rc_y + rc_h > bit_h) rc_h = bit_h - rc_y;
-     if (x + rc_w > sw) rc_w = sw - x;
-     if (y + rc_h > sh) rc_h = sh - y;
-     const int nextLineOffset_src = (bit_w - rc_w) * 4;    // 混合完一行像素后,通过加上该值,便可直接定位到下行起始像素
-     const int nextLineOffset_dst = (sw - rc_w) * 4;
-     pDstBmp += y * sw + x;
-     pSrcBmp += rc_y * bit_w + rc_x;
-     const int ff = 0xff;
-     __asm
-     {
-         mov            edi, pDstBmp        ; 目的像素
-             mov            esi, pSrcBmp        ; 源像素
-             xor            ebx, ebx            ; 已混合的高度
-             mov            ecx, rc_w            ; 要混合的宽度
- BLEND_BEGIN:
-         cmp            dword ptr[esi], 0x00FFFFFF; 如果alpha为0,则跳过混合部分
-             jna            BLEND_END
-             mov            eax, blendalpha        ; 获取blend alpha
-             mov            edx, dword ptr[esi]
-             shr            edx, 24                ; edx 获取源像素 alpha
-             imul        eax, edx
-             ;cwd
-             mov            edx, 0
-             idiv        ff
-             shl            eax, 24
-             mov            edx, eax
-             mov            eax, dword ptr[esi]
-             and            eax, 0x00ffffff
-             or            eax, edx
-             movd        mm0, [edi]            ; 把目的像素值移入mm0寄存器的低32位
-             ;movd        mm1, [esi]            ; 把源像素值移入mm1寄存器的低32位
-             movd        mm1, eax
-             ; Core Begin
-             pxor        mm2, mm2            ; 把MM2清0
-             punpcklbw    mm0, mm2            ; src:8 bit到16 bit以容纳结果,32bit expand to 64 bit
-             punpcklbw    mm1, mm2            ; dst:8 bit到16 bit以容纳结果.32bit expand to 64 bit
-             movq        mm3, mm1            ; 因为要用dst的Alpha值
-             punpckhwd    mm3, mm3            ; 高字移动到双字
-             punpckhdq    mm3, mm3            ; 双字移动到四字,现在有八个像素的Alpha了!
-             movq        mm4, mm0            ; mm4 = dst
-             movq        mm5, mm1            ; mm5 = src
-             psubusw        mm4, mm1            ; dst-src,饱和减,小于0为0
-             psubusw        mm5, mm0            ; src-dst,饱和减,小于0为0
-             pmullw        mm4, mm3            ; Alpha * (src-dst)
-             pmullw        mm5, mm3            ; Alpha * (dst-src)
-             psrlw        mm4, 8                ; 除以256,now mm4 get the result,(src-dst)<0 部分
-             psrlw        mm5, 8                ; 除以256,now mm5 get the result,(dst-src)>0 部分
-             paddusw        mm0, mm5            ; 饱和加到原图象:D=Alpha*(O-S)+S,(src-dst)<0 部分
-             psubusw        mm0, mm4            ; 饱和加到原图象D=S-Alpha*(S-O),(dst-src)>0 部分
-             packuswb    mm0, mm0            ; 紧缩到低32bit
-             ; Core End
-             ;movd        eax, mm0
-             ;and            eax, 0x00ffffff
-             ;mov            edx, dword ptr[edi]
-             ;and            edx, 0xff000000
-             ;or            eax, edx
-             movd        [edi], mm0            ; 混合结果写进目的像素
-             ;mov            dword ptr[edi], eax
- BLEND_END:
-         add            edi, 4
-             add            esi, 4
-             ;loop        BLEND_BEGIN                ; 循环
-             dec            ecx
-             cmp            ecx, 0                ; rc_w <= 0 跳出循环
-             jg            BLEND_BEGIN
-             add            esi, nextLineOffset_src    ; 加上偏移量,使定位到下行起始处
-             add            edi, nextLineOffset_dst
-             inc            ebx
-             mov            ecx, rc_w
-             cmp            ebx, rc_h                ; 若ebx小于rc_h,则转移到上面继续混合
-             jb            BLEND_BEGIN
-             EMMS                                ; 因为从mm0到mm7,这些寄存器是“借用”浮点寄存器的低64位,所以每次在用完MMX指令后一定要用EMMS指令将寄存器清空
-     }
- }
复制代码
问题。。。在图片上。。。原本不贴 太阳那幅图,正常。但是贴上太阳,图像整体变成半透明了,咋办哇?
我看到 颜色 dst,src的混合计算公式
结果色 = dst * (1-src.alpha) + src * src.alpha
那么,其实我有个疑问。。 结果色.alpha怎么算。。
上面的公式 通常默认 dst.alpha = 1.0 (255)的,但是我想混两个不透明色,而不是把透明色混到不透明色上,怎么办?
问题叙述完毕,上图中。。。。 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
|