首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > .NET >

:(附源码),256色旋转算法速度有关问题:角度越大,速度越慢.(原因是内存颠簸造成,)

2012-02-13 
高手请进:(附源码),256色旋转算法速度问题:角度越大,速度越慢.(原因是内存颠簸造成,)procedureRotate(Bmp:

高手请进:(附源码),256色旋转算法速度问题:角度越大,速度越慢.(原因是内存颠簸造成,)
procedure   Rotate(Bmp:Pointer;BMPWidth,BMPHeight,cx,cy:Integer;Dst:Pointer;DstWidth,DSTHeight:integer;Angle:Double);
var
x,y,
dx,dy,
sdx,sdy,
xDiff,yDiff,
isinTheta,
icosTheta:   Integer;
SrcTmp:PByteArray;
DstTmp:             PByte;
sinTheta,
cosTheta,
Theta:           Double;
x_1,y_1:Integer;
calcfirstx,calcfirsty:Double;
begin
    Theta:=-Angle*Pi/180;
    sinTheta:=Sin(Theta);
    cosTheta:=Cos(Theta);
    xDiff:=(DstWidth-BmpWidth)div   2;
    yDiff:=(DstHeight-BmpHeight)div   2;
    isinTheta:=Round(sinTheta*$10000);
    icosTheta:=Round(cosTheta*$10000);
        DstTmp:=PByte(DST);
        SrcTmp:=PByteArray(BMP);
        x_1:=DstWidth-1;
        y_1:=DstHeight-1;
        calcfirstx:=cx-cx*cosTheta+cy*sinTheta-xDiff;
        calcfirsty:=cy-cx*sinTheta-cy*cosTheta-yDiff;
        for   y:=y_1-100   downto   0   do
        begin
            sdx:=Round((calcfirstx-y*sinTheta)*$10000);
            sdy:=Round((calcfirsty+y*cosTheta)*$10000);
            for   x:=x_1   downto   0   do
            begin
                dx:=sdx   shr   16;
                dy:=sdy   shr   16;
                if(dy <BMPHeight)and(dx <BMPWidth)   then
                begin
                      DstTmp^:=SrcTMP[dx+dy*BMPWidth];// < <--------------此处角度大时内存颠簸严重(图像大小:2048*1536)
                end;
                inc(sdx,icosTheta);
                inc(sdy,isinTheta);
                Inc(DstTmp);
            end;
        end;
end;


[解决办法]
旋转确实有这个问题
这个不叫“内存颠簸”吧 ,“内存颠簸”应该是因为缓存的路数不够,造成类似“hash”碰撞,从而降低缓存利用率;
这个应该是内存预取失效之类的,就是CPU预取的数据大部分是无效的(CPU会一次连续读取64字节到缓存,但某些角度的旋转需要的数据经常只有一个颜色数据(一般1-4字节),大部分数据都白读了);

尝试一下自己手工预取试试 (在几百个CPU周期之前读一下那个内存数据;可以考虑专门的预取指令比如prefetchnta、prefetcht0等) ,然后让预读代码和实际处理代码交错起来

(ps: 我没有尝试过这个方案;
我的blog中也写了几篇关于图像任意角度旋转的文章,并且还有带插值的高质量旋转实现)
[解决办法]
用GDI+吧。俺已经完美实现了。

热点排行