mmx 的32位alpha 混合一直弄不好啊。。
是这样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)
{
// 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;
UINT** pptmp = &pDstBmp;
__asm
{
mov edi, pDstBmp ; 目的像素
mov esi, pSrcBmp ; 源像素
xor ebx, ebx ; 已混合的高度
mov ecx, rc_w ; 要混合的宽度
BLEND_BEGIN:
cmp dword ptr, 0x00FFFFFF ; 如果alpha为0,则跳过混合部分
jna BLEND_END
movd mm0, ; 把目的像素值移入mm0寄存器的低32位
movd mm1, ; 把源像素值移入mm1寄存器的低32位
; 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 , mm0 ; 混合结果写进目的像素
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指令将寄存器清空
}
} UINT* pDstBmp 目标地址
UINT* pSrcBmp 源地址
int bit_w 源位图的尺寸
int bit_h
int rc_x 矩形尺寸(源位图,中的一个矩形区域混合到Dst上)
int rc_y
int rc_w
int rc_h
int x, 混合到目标位图的位置
int y,
int sw, 目标位图的尺寸
int sh,
int blendalpha 透明度
现在是 int blendalpha 透明度 这个参数没有用上,一切都正常,我想加上这个参数比如 blendalpha = 100
源位图选取的矩形在混合的时候透明度会 *100/255自己试了在这个代码里面添汇编指令,总是失败,求教 竟然又自己捣鼓出来了!!!不过还是有疑问哇
const int ff = 0xff;//这一句是添加的
__asm
{
mov edi, pDstBmp ; 目的像素
mov esi, pSrcBmp ; 源像素
xor ebx, ebx ; 已混合的高度
mov ecx, rc_w ; 要混合的宽度
BLEND_BEGIN:
cmp dword ptr, 0x00FFFFFF; 如果alpha为0,则跳过混合部分
jna BLEND_END
;后边是添加的代码
mov eax, blendalpha ; 获取blend alpha
mov edx, dword ptr
shr edx, 24 ; edx 获取源像素 alpha
imul eax, edx
mov edx, 0
idiv ff ;下边说的就是这句
shl eax, 24
mov edx, eax
mov eax, dword ptr
and eax, 0x00ffffff
or eax, edx ;添加完毕
;添加完毕
movd mm0, ; 把目的像素值移入mm0寄存器的低32位
;movd mm1, ; 把源像素值移入mm1寄存器的低32位
movd mm1, eax ;这一句替换上一句
那么,问题来了。。。问题描述在这里
添加的一大串中
idiv ff
ff是我前面定义的 const int 局部变量
我起初
mov edx, 0xff
idiv edx
结果 编译过了,调试的时候 0xC0000095 整数溢出,断点断在 函数调用的地方,但是 idiv 这一句屏蔽掉,一点问题都没有。
这里问题1
我就郁闷了。。。
那么 原因 是不是 这样的?
edx:eax 是被除数 除edx 高位32位得 1低是32位XXXX 这个高位的1 就是溢出的东西?
问题2
那么我不想要多定义 const int ff 这个局部变量怎么办的
双层循环已经占用了ebx ecx,mmx 占用了 ebi esi 那么只剩下 eax edx了吧?。。想不通了。。总之解决了,剩下的就是附加题了 你想调整整个图像的alpha?
如果是这样的,我感觉你的方式有点不对,至少是不好,
在我的实现里面,图像有以下几种效果:
1:缩放
2:调节色调
3:调节亮度
其中,调节色调就能解决你的需求,
调节色调就是对源像素按给出的比例进行缩放:
比如源像素是0xFFFFFFFF,给出的比例是:0xFFFFFF64,那么结果就是0xFFFFFF64,即100/255.0f*255=100
如果源像素是0xC8FFFFFF,给出的比例是:0x64FFFFFF,那么结果就是0x4EFFFF,即100/255.0f*200=78
效果见这张图:
http://img.my.csdn.net/uploads/201209/15/1347677430_4954.jpg
如果你用过D3D,就应该知道这个色调调节就是顶点颜色所实现的效果. 寄存器不够用的话,就用栈吧,我写的一个支持缩放+色调调节+亮度调节的alpha混合函数,仅push了两个寄存器
但很多情况下,只要算法足够精当,都会够用 idiv那一句,我写成 idiv edx 会出错哇,调试会出现整数溢出。。。要不,我也不用申请变量哇。。。
我就是想 给选择的矩形部分加一个透明度 再 混合到 dst上。原图不变,也不是整个图都变透明,只是选的那部分(要进行混合的)
我看楼上的就是用位移代替 除法,反正255 和 256 差不多是吧? 引用第5楼secondsen于2012-10-13 18:03发表的 :
idiv那一句,我写成 idiv edx 会出错哇,调试会出现整数溢出。。。要不,我也不用申请变量哇。。。
我就是想 给选择的矩形部分加一个透明度 再 混合到 dst上。原图不变,也不是整个图都变透明,只是选的那部分(要进行混合的)
我看楼上的就是用位移代替 除法,反正255 和 256 差不多是吧? http://www.rpgchina.net/images/back.gif
我写的那代码有问题,让我删了,
可以用除以256来代替除以255,这个损失是可以接受的,要不然除法指令会慢一些.
你是说,你渲染一个图片的时候,你想调整图片某块区域的透明度? 而不是整个图片的透明度?
这个功能我倒是没做过,
如果你只调整alpha的话,单独写一个函数就行.
关于idiv
这个指令我没用过,查了一下,是有符号除法,你为什么不用div呢? 这个是无符号除,因为颜色分量都是无符号的.
还有:
你居然可以这么写: imul eax, edx
因为我用mul都是这样的: mulebx , 即被乘数是eax, 乘数是ebx,结果低32位放到eax上,高32位放到edx上,
你这个居然能用两个寄存器.
另外,你的代码我没看出有什么问题. 因为是这样,所以是这样哇。。。我是按照这个来的 http://www.cnblogs.com/del/archive/2010/04/15/1712950.html
用有符号的的指令,因为无符号的指令编译过不去,不知道什么毛病
其实alpha一通百通,色调也是一样,我都已经成功了,只是不知道idiv是什么毛病,也不知道我上面自己瞎想的对不对。。。OTZ 引用第7楼secondsen于2012-10-13 21:25发表的 :
因为是这样,所以是这样哇。。。我是按照这个来的 http://www.cnblogs.com/del/archive/2010/04/15/1712950.html
用有符号的的指令,因为无符号的指令编译过不去,不知道什么毛病
其实alpha一通百通,色调也是一样,我都已经成功了,只是不知道idiv是什么毛病,也不知道我上面自己瞎想的对不对。。。OTZ http://www.rpgchina.net/images/back.gif
div编译不了?
那就奇怪了,我是从16位汇编学过来的,我一直使用mul和div,而没用过imul和idiv, 也没出现什么编译不了的问题.
你的写法和我的是一样的.
另外,你不应该除以edx,因为你是在做32位除法,你的edx总是0,被除数都在eax上 不是edx:eax合起来是被除数么
页:
[1]
2