最近偶的工作任务是写一个类似DDraw中Blt的函数..同时还要实现关键色,alpha透明,左右镜像,上下镜像,缩放..偶的程序写好了,功能正常,但速度暴慢..同时渲染100张图(278*142大小),且把上述特效都打开,只能达到10帧..偶的程序主要是逐点处理,下面是处理循环的代码片断,请高手指点一下,给点改进意见,怎么才能加快速度.for(UINT y=0; y<rect_src.ui32H; y++)
{
//记录每行的开始位置
addr_dst_t = addr_dst;
addr_src_t = addr_src; if(b_lrmirror) //左右镜像
addr_src += pixel_per_line<<1 ; if(b_zoom) //缩放,index_x是缩放处理每行的标志
index_x = 0; for(UINT x=0; x<rect_src.ui32W; x++)
{
if(b_colorkey) //关键色
{
UCHAR red,blue,green;
src_data = *addr_src;
r= (src_data>>11) & 31;
g= (src_data>>5) & 63;
b= src_data & 31; if( r>=red_l && r<=red_h
&& b>=blue_l && b<=blue_h
&& g>=green_l && g<=green_h)
{
b_flip = true;
}
else
b_flip = false;
}
if(b_alpha) //alpha透明
{
src_data = *addr_src;
dst_data=*addr_dst;
if(!b_colorkey)
{
r = (UCHAR)( (((src_data>>11) & 31)*alpha + ((dst_data>>11) & 31)*_alpha) >> 5 );
g = (UCHAR)( (((src_data>>5) & 63)*alpha + ((dst_data>>5) & 63)*_alpha) >> 5 );
b = (UCHAR)( ((src_data & 31)*alpha + (dst_data & 31)*_alpha) >> 5 );
}
else
{
r = (UCHAR)((r*alpha + ((dst_data>>11) & 31)*_alpha)>>5);
g = (UCHAR)((g*alpha + ((dst_data>>5) & 63)*_alpha)>>5);
b = (UCHAR)((b*alpha + (dst_data & 31)*_alpha)>>5);
}
} //写数据,步进指针 if(b_zoom)
{
while( index_x < x_rate )
{
if(!b_flip)
{
if(b_alpha)
*addr_dst++ = _RGB16BIT565(r,g,b);
else
*addr_dst++ = *addr_src;
}
else
addr_dst++;
index_x += 1000;
}
index_x -= x_rate; //x_rate,y_rate为缩放比例*1000(避免用浮点数)
}
else
{
if(b_flip)
{
addr_dst++;
}
else
{
if(b_alpha)
*addr_dst++ = _RGB16BIT565(r,g,b);
else
*addr_dst++ = *addr_src;
}
}
addr_src ++;
if(b_lrmirror) //左右镜像时的校正
addr_src -= 2;
} //步进到下一行
addr_dst = addr_dst_t + lpitch_dst;
if(b_zoom)
{
index_y += 1000;
while( index_y < y_rate )
{
memcpy(addr_dst, addr_dst-lpitch_dst,rect_dst.ui32W<<1);
addr_dst = lpitch_dst + addr_dst;
index_y += 1000;
}
index_y -= y_rate;
}
addr_src = addr_src_t + lpitch_src;
}在线等!!
{
//记录每行的开始位置
addr_dst_t = addr_dst;
addr_src_t = addr_src; if(b_lrmirror) //左右镜像
addr_src += pixel_per_line<<1 ; if(b_zoom) //缩放,index_x是缩放处理每行的标志
index_x = 0; for(UINT x=0; x<rect_src.ui32W; x++)
{
if(b_colorkey) //关键色
{
UCHAR red,blue,green;
src_data = *addr_src;
r= (src_data>>11) & 31;
g= (src_data>>5) & 63;
b= src_data & 31; if( r>=red_l && r<=red_h
&& b>=blue_l && b<=blue_h
&& g>=green_l && g<=green_h)
{
b_flip = true;
}
else
b_flip = false;
}
if(b_alpha) //alpha透明
{
src_data = *addr_src;
dst_data=*addr_dst;
if(!b_colorkey)
{
r = (UCHAR)( (((src_data>>11) & 31)*alpha + ((dst_data>>11) & 31)*_alpha) >> 5 );
g = (UCHAR)( (((src_data>>5) & 63)*alpha + ((dst_data>>5) & 63)*_alpha) >> 5 );
b = (UCHAR)( ((src_data & 31)*alpha + (dst_data & 31)*_alpha) >> 5 );
}
else
{
r = (UCHAR)((r*alpha + ((dst_data>>11) & 31)*_alpha)>>5);
g = (UCHAR)((g*alpha + ((dst_data>>5) & 63)*_alpha)>>5);
b = (UCHAR)((b*alpha + (dst_data & 31)*_alpha)>>5);
}
} //写数据,步进指针 if(b_zoom)
{
while( index_x < x_rate )
{
if(!b_flip)
{
if(b_alpha)
*addr_dst++ = _RGB16BIT565(r,g,b);
else
*addr_dst++ = *addr_src;
}
else
addr_dst++;
index_x += 1000;
}
index_x -= x_rate; //x_rate,y_rate为缩放比例*1000(避免用浮点数)
}
else
{
if(b_flip)
{
addr_dst++;
}
else
{
if(b_alpha)
*addr_dst++ = _RGB16BIT565(r,g,b);
else
*addr_dst++ = *addr_src;
}
}
addr_src ++;
if(b_lrmirror) //左右镜像时的校正
addr_src -= 2;
} //步进到下一行
addr_dst = addr_dst_t + lpitch_dst;
if(b_zoom)
{
index_y += 1000;
while( index_y < y_rate )
{
memcpy(addr_dst, addr_dst-lpitch_dst,rect_dst.ui32W<<1);
addr_dst = lpitch_dst + addr_dst;
index_y += 1000;
}
index_y -= y_rate;
}
addr_src = addr_src_t + lpitch_src;
}在线等!!
可以把循环当中if条件提取到for的外部去第二种:语言优化,它是算法之后的优化
比如用汇编来实现另外,既然有ddraw为何不用它呢,那个可是硬件支持的直接访问显存的操作
而你自己是不能直接访问显存的,效率自然就会低下
偶这段程序的目的是,如果显卡不支持alpha,就要用软件来模拟它.
而要模拟alpha,我就必须逐点处理,所以要用一个双重循环.
而且,在支持alpha的同时还要支持colorkey,缩放,镜像等,所以我的循环中有那么多的if..(if影响效率极低吧).更要命的是还要支持颜色转换(565->32,32->565),这个以后再说吧,先把前边的搞定.听说MMX能很大的提高效率,哪位达人会用MMX呢.偶的汇编学得不好,如果哪位能把colorkey及alpha处理那一段改写成MMX汇编,小弟不胜感激,再开帖送分,送完为止.
for(N次)
if (flag)
A
else
B
显然if被判断了N次如果改成
if (f)
for () A;
else
for () B;
显然if只被判断了一次而已,这样是可以提高效率的在双层循环内部的每个操作都被循环放大了很多次数,最主要优化的就是内层循环的东西VC里面提供的profiling功能是可以用来分析函数当中各个部分的执行效率的
虽然你把if提出来了,但一个for变成了两个.我的循环中有N个if,我还要考虑它们的组合,如果全提出来,得写多少个for啊..
我试过,即使在循环中写10 个if,好像影响也不及一个++运算大..可能是CPU能针对if做很大程度的优化吧
有一篇文章:
可能是最快的算法alpha blend汇编源代码,Intel官方提供