关于16位色的Alpha,速度不理想,懂汇编的进来帮助优化一下

flyinwuhan 2006-06-16 10:11:14
要实现的功能:把一张16位565格式位图alphablend到另一张16位565格式位图上。
没有alpha通道,把源位图每一个点的亮度作为alpha值,即:
alphavalue := (r * 77 + g * 150 + B * 29) shr 8;// / 255

r3 := (r2 * alphavalue + r1 * (255-alphavalue)) shr 8;
g3 := (g2 * alphavalue + g1 * (255-alphavalue)) shr 8;
b3 := (b2 * alphavalue + b1 * (255-alphavalue)) shr 8;

下面是我写的汇编,效率很低,麻烦高人耐心看完~~~最好给点指导!先谢了!

const
BMP_FILE_SIGN = $4D42; //tagBITMAPFILEHEADER.bfType

MASK_R: int64 = $f800f800f800f800;
MASK_G: int64 = $07e007e007e007e0;
MASK_B: int64 = $001f001f001f001f;
MAX_A: int64 = $00ff00ff00ff00ff;
MUL_R: int64 = $004d004d004d004d;
MUL_G: int64 = $0096009600960096;
MUL_B: int64 = $001d001d001d001d;

for j := 1 to (nDstRight - nDstX) div 4 do
begin
asm
mov ECX, ptrSrc//这个ptr指针指向16位565格式源位图数据
mov EDX, ptrDst//这个ptr指针指向16位565格式目标位图数据
movq mm0, [ECX]
movq mm7, [EDX]

movq mm1, mm0 //把源图像565色彩分离成为888
movq mm2, mm0
pand mm0, MASK_R
psrlw mm0, 8
pand mm1, MASK_G
psrlw mm1, 3
pand mm2, MASK_B
psllw mm2, 3

movq mm3, mm0 //计算源图像的每个像素点的亮度
movq mm4, mm1
movq mm5, mm2
pmullw mm3, MUL_R //r2 * 77
pmullw mm4, MUL_G //g2 * 150
pmullw mm5, MUL_B //b2 * 29
paddusw mm3, mm4
paddusw mm3, mm5
psrlw mm3, 8 //(r2 * 77 + g2 * 150 + b2 * 29) shr 8

pmullw mm0, mm3 //r2 * av
pmullw mm1, mm3
pmullw mm2, mm3

movq mm4, mm7 //把目标图像565色彩分离成为888
movq mm5, mm7
movq mm6, mm7
pand mm4, MASK_R
psrlw mm4, 8
pand mm5, MASK_G
psrlw mm5, 3
pand mm6, MASK_B
psllw mm6, 3

movq mm7, MAX_A
psubusw mm7, mm3 //255 - av

pmullw mm4, mm7 //r1 * (255 - av)
pmullw mm5, mm7
pmullw mm6, mm7

paddusw mm4, mm0 //(r2 * av + r1 * (255-av)
paddusw mm5, mm1
paddusw mm6, mm2

psrlw mm4, 8 //(r2 * av + r1 * (255-av)) shr 8;
psrlw mm5, 8
psrlw mm6, 8

psrlw mm4, 3 //RGB各取5,6,5位
psrlw mm5, 2
psrlw mm6, 3

psllw mm4, 11 //组合成16位565格式
psllw mm5, 5
por mm4, mm5
por mm4, mm6

movq [EDX], mm4 //写回缓冲区
end;
Inc(ptrSrc, 4);
Inc(ptrDst, 4);
end;

关于上面alpha的计算思路如下:
for j:=1 to (nDstRight - nDstX) mod 4 do
begin
if ptrSrc^ <> 0 then
begin
r1 := (ptrDst^ and $F800) shr 8;
g1 := (ptrDst^ and $07E0) shr 3;
b1 := (ptrDst^ and $001F) shl 3;

r2 := (ptrSrc^ and $F800) shr 8;
g2 := (ptrSrc^ and $07E0) shr 3;
b2 := (ptrSrc^ and $001F) shl 3;

av := (r2 * 77 + g2 * 150 + B2 * 29) shr 8;

r3 := (r2 * av + r1 * (255-av)) shr 8;
g3 := (g2 * av + g1 * (255-av)) shr 8;
b3 := (b2 * av + b1 * (255-av)) shr 8;

r3 := r3 shr 3;
g3 := g3 shr 2;
b3 := b3 shr 3;

ptrDst^ := (r3 shl 11) or (g3 shl 5) or (b3);
end;
Inc(ptrDst);
Inc(ptrSrc);
end;
...全文
383 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
hswxf 2006-06-23
  • 打赏
  • 举报
回复
过奖了
你参考一下:http://www.freeworld.net.cn/Article/Catalog28/22947.html
我也不知道他写的如何
flyinwuhan 2006-06-23
  • 打赏
  • 举报
回复
就这样吧 谢谢大家了
shinesi 2006-06-23
  • 打赏
  • 举报
回复
图像处理中常用的办法是 查表+MMX
flyinwuhan 2006-06-22
  • 打赏
  • 举报
回复
楼上的很专业啊!
我的目的就是逐个点计算Alphablend,就是你说的图流啦。计算Alphablend的原理我知道,也MMX写出来了,只是我不了解汇编,不知道我的写法有没有优化的余地。
hswxf 2006-06-22
  • 打赏
  • 举报
回复
楼主是什么意思?是只想速度(快)还是想求一个更好的转移算法?还是只是进行数据级的图像转移?还是想在加工中显示出你的图?
如果是快的话,我想最好不用MMX指令,因为你用的方法只是更慢,还不如用串指令!
如果只是转移数据,建议使用DMA专用通道等
如果是贴图也不用MMX,最好专用显卡驱动(寄存器级操作)
如果是数据流的话(图流),那你用MMX可能就对了。
suncheng_hong 2006-06-21
  • 打赏
  • 举报
回复
5555555555555一点都不懂。。。
5
flyinwuhan 2006-06-21
  • 打赏
  • 举报
回复
再没有高手来就准备结贴了~~高手赶快啊
flyinwuhan 2006-06-18
  • 打赏
  • 举报
回复
找到rgbMask了,rgbMASK = $07e0f81f;

for j := nDstX to nDstRight - 1 do
begin
sour := ptrSrc^;
dest := ptrDst^;
if sour <> 0 then
asm
movzx eax, sour//零扩展成32位
mov cx, ax//把sour放到bx中
sal eax, 16//算术左移16位,低位填0
mov ax, cx//把sour放到ax中,现在的eax中放的是两个sour
and eax, rgbMask//与上rgbMask
mul alphav//乘上alpha值
mov edx, eax//保存到esi

movzx eax, dest//同样的方法
mov cx, ax
sal eax, 16
mov ax, cx
and eax, rgbMask
mul ialphav
add eax, edx//加上刚刚的值
shr eax, 5//逻辑右移5位,高位填0

and eax, rgbMask//与上rgbMask
mov edx, eax//放到esi中
shr eax, 16//逻辑右移动16位,高位填0
or eax, edx//或上esi
mov dest, ax//返回
end;
ptrDst^ := dest;
Inc(ptrSrc);
Inc(ptrDst);
end;

但是时间只是比用pascal快大概10%

并且,这种算法怎么用MMX写出来呢?如果用MMX写的话速度至少应该提高2倍,谁帮助写一下?我写的不理想啊~~~~~~~~~
merkey2002 2006-06-18
  • 打赏
  • 举报
回复
555555
一点都不懂。。。
蒋晟 2006-06-18
  • 打赏
  • 举报
回复
MMX未必快,如果CPU支持SSE的话
yyjzsl 2006-06-17
  • 打赏
  • 举报
回复
关注,顶下
cncharles 2006-06-17
  • 打赏
  • 举报
回复
怎么与我学得汇编一样?
PANBing 2006-06-17
  • 打赏
  • 举报
回复
关注,帮顶
fox1999 2006-06-17
  • 打赏
  • 举报
回复
都已经用了 MMX 了.

想再提高,得找高手了.
蒋晟 2006-06-17
  • 打赏
  • 举报
回复
http://jonlee.cnblogs.com/archive/2005/08/04/206884.html
flyinwuhan 2006-06-17
  • 打赏
  • 举报
回复
jiangsheng(蒋晟.Net[MVP]) 给的链接很有用,这个算法应该是更快:

rgbTemp = ((((sour<<16)|sour) & rgbMask ) * alpha +
(((dest<<16)|dest) & rgbMask ) * (32-alpha) ) >> 5;
rgbTemp = rgbTemp & rgbMask;
return (WORD)((rgbTemp>>16)|rgbTemp);

但是。。。里面有个常量rgbMask应该是如何定义的呢??琢磨半天也琢磨不出来啊~
postren 2006-06-16
  • 打赏
  • 举报
回复
不懂汇编
路过了

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧