小弟现在在做32位bmp图像90度旋转,想求优化一点的算法,比如mmx,或sse写的旋转代码。我得编译环境是vc6.0,谢谢各位大侠了了。

解决方案 »

  1.   

    cximage有现成的函数可调用,看看cximage的demo吧
      

  2.   

    恩 我也知道,我现在是win7 32位系统,做32位bmp图像(4096*2400*4)的图像旋转耗时为125毫秒,老师要求是在100毫秒内完成。
      

  3.   

    你是按字节处理的?32位位图按dword搞很方便。
      

  4.   

    我是按像素处理的,一次处理一个像素(4字节),这样做还是不能保证在100ms内。程序代码
    for(int i=0;i < bmpHeight;i++)
    {
       for(int j=0;j<bmpWidth;j++)
      { 
          *( (UINT32*)rotateBuf + j*bmpHeight + i) = *((UINT32*)pBmpBuf + (bmpHeight-1-i)*bmpWidth + j);
      }
    大侠们看看能否帮我优化这段代码
      

  5.   


    for(int i=0;i < bmpHeight;i++)
    {
    int temp = (bmpHeight-1-i)*bmpWidth;
    for(int j=0;j<bmpWidth;j++)
    {  
    *( (UINT32*)rotateBuf + j*bmpHeight + i) = *((UINT32*)pBmpBuf + temp + j);
    }
    }这样可以减少一半的乘法运算量
      

  6.   

     (bmpHeight-1-i)*bmpWidth   这一部分在第二个循环里是不变的,用一个中间变量在第一个循环里保存以方便调用,。
    实际上 *((UINT32*)pBmpBuf + (bmpHeight-1-i)*bmpWidth + j)这个指针每次循环的时候都是递加了1,用++之类的效率会更高。
      

  7.   

    这句可以优化
    *((UINT32*)pBmpBuf + (bmpHeight-1-i)*bmpWidth + j);第一层循环指到每行开头DWORD* pData。
    第二层循环每次pData++;
      

  8.   


    int nData;
    for(int i=0;i < bmpHeight;i++)
    {
        for(int j=0;j<bmpWidth;j++)
        {
            nData=0;
        }
    }
    你测一下这段代码执行时间是多少
    然后不能在100毫米一下你可以不用再努力了
      

  9.   

    http://blog.csdn.net/morbi/article/details/5674687
      

  10.   

    只旋转90度,直接用for循环,如果是多核,可以用opencmp来提速
      

  11.   

    OK我写了一个程序,细节上没有检查;为了取时间我用Debug模式 70ms,如果Release应该更快#define width  4096     // width必须为8的倍数
    #define height 2400    U32 *src = (U32 *)malloc(width*height*sizeof(U32));
        U32 *dst = (U32 *)malloc(width*height*sizeof(U32));
        int y;    DWORD t1 = timeGetTime();#pragma omp parallel 
    #pragma omp parallel for private(y)
        for( y = 0; y < height; y++)
            {
            U32 *s = src + y * width;    // 注意因为考虑多核,这里有些低效
            U32 *d = dst + (height - 1 - y);
            for(int x = 0; x < width; x+=8)
                {
                d[0]          = s[0];    // 技巧在这里,仔细考虑
                d[height * 1] = s[1];
                d[height * 2] = s[2];
                d[height * 3] = s[3];            d[height * 4] = s[4];
                d[height * 1] = s[5];
                d[height * 2] = s[6];
                d[height * 3] = s[7];            d += (height << 3);
                s += 8;
                }
            }
        DWORD t2 = timeGetTime() - t1;
    机器配置很一般,好像是1.6G主频,笔记本(我不确定是否是在全速下);
      

  12.   

    哦,最后3行写错了:
      d[height * 5] = s[5];
      d[height * 6] = s[6];
      d[height * 7] = s[7];
    不过应该不影响结果 ---- 提供一个思路
      

  13.   

    #include"ENobject2D.h"
    //2D图rotate/move/scale
    //旋转以及对缩放有修正作用
    void ENobject2D::LHxxROTATE_2DIMAGE(char *Tname,float &angle,int mirrorX,int mirrorY)
    {
        int i=0;
    TList=ENobject2DListOb.GetNode(Tname);
    LHxx2DIMAGE *sc=TList->ObjectData;
    if(angle>=PI*2)
    {
    angle-=PI*2;
    }
    if(angle<=-PI*2)
    {
    angle+=PI*2;
    }
    sc->LHxxAngle=angle;
    float dx,dy,dw,dh;//临时变量
    float sw = sc->LHxxIw;//image width
    float sh = sc->LHxxIh;//image height 
    float sclx,scly,sclw,sclh;//复位并放缩的坐标(局部坐标系--image的坐标系)
    float hotx =sw/2+sc->LHxxRotateOffset.first;//旋转中心
    float hoty =sh/2+sc->LHxxRotateOffset.second;
    //复位  放缩 , 旋转  ,平移
        float xscale=sc->LHxxScaleX;
    float yscale=sc->LHxxScaleY;
    //放缩后的区域
    sclx = -hotx;
    scly = -hoty;
        //原始旋转中心
    sclw = (sw - hotx);
    sclh = (sh - hoty);
    float sint, cost;
    sint = sinf(sc->LHxxAngle);
    cost = cosf(sc->LHxxAngle);
    float                   TestAngleXDa[4];
    float                   TestAngleYDa[4];
    memcpy(TestAngleXDa,sc->LHxxAngleXDa,sizeof(sc->LHxxAngleXDa));
    memcpy(TestAngleYDa,sc->LHxxAngleYDa,sizeof(sc->LHxxAngleYDa));
    if(mirrorX==1)
    {
    LHxx2DSCREENVERTEX* ss;
    sc->LHxx2DMVertexBuffer->Lock( 0, 0, (void**)&ss, 0 );
    //求得4点旋转量                          (减去放大值)
    TestAngleXDa[0] = sclx*cost - scly*sint  -sclx;
    TestAngleYDa[0] = sclx*sint + scly*cost  -scly;
    TestAngleXDa[1] = sclw*cost - scly*sint  -sclw;
    TestAngleYDa[1] = sclw*sint + scly*cost  -scly;
    TestAngleXDa[2] = sclx*cost - sclh*sint  -sclx;
    TestAngleYDa[2] = sclx*sint + sclh*cost  -sclh;
    TestAngleXDa[3] = sclw*cost - sclh*sint  -sclw;
    TestAngleYDa[3] = sclw*sint + sclh*cost  -sclh;
    sc->LHxx2DMVertexBuffer->Unlock();
    }
    else if(mirrorX==2 )
    {
    LHxx2DSCREENVERTEX* ss;
    sc->LHxx2DMVertexBuffer->Lock( 0, 0, (void**)&ss, 0 );
    //求得4点旋转量                          (减去放大值)
    TestAngleXDa[1] = sclx*cost - scly*sint  -sclx;
    TestAngleYDa[1] = sclx*sint + scly*cost  -scly;
    TestAngleXDa[0] = sclw*cost - scly*sint  -sclw;
    TestAngleYDa[0] = sclw*sint + scly*cost  -scly;
    TestAngleXDa[3] = sclx*cost - sclh*sint  -sclx;
    TestAngleYDa[3] = sclx*sint + sclh*cost  -sclh;
    TestAngleXDa[2] = sclw*cost - sclh*sint  -sclw;
    TestAngleYDa[2] = sclw*sint + sclh*cost  -sclh;
    sc->LHxx2DMVertexBuffer->Unlock();
    }
    if(mirrorX==1 && mirrorY==2)
    {
    LHxx2DSCREENVERTEX* ss;
    sc->LHxx2DMVertexBuffer->Lock( 0, 0, (void**)&ss, 0 );
         //求得4点旋转量                          (减去放大值)
    TestAngleXDa[2] = sclx*cost - scly*sint  -sclx;
    TestAngleYDa[2] = sclx*sint + scly*cost  -scly;
    TestAngleXDa[3] = sclw*cost - scly*sint  -sclw;
    TestAngleYDa[3] = sclw*sint + scly*cost  -scly;
    TestAngleXDa[0] = sclx*cost - sclh*sint  -sclx;
    TestAngleYDa[0] = sclx*sint + sclh*cost  -sclh;
    TestAngleXDa[1] = sclw*cost - sclh*sint  -sclw;
    TestAngleYDa[1] = sclw*sint + sclh*cost  -sclh;
    sc->LHxx2DMVertexBuffer->Unlock();
    }
    else if(mirrorX==2 && mirrorY==2)
    {
    LHxx2DSCREENVERTEX* ss;
    sc->LHxx2DMVertexBuffer->Lock( 0, 0, (void**)&ss, 0 );
         //求得4点旋转量                          (减去放大值)
    TestAngleXDa[3] = sclx*cost - scly*sint  -sclx;
    TestAngleYDa[3] = sclx*sint + scly*cost  -scly;
    TestAngleXDa[2] = sclw*cost - scly*sint  -sclw;
    TestAngleYDa[2] = sclw*sint + scly*cost  -scly;
    TestAngleXDa[1] = sclx*cost - sclh*sint  -sclx;
    TestAngleYDa[1] = sclx*sint + sclh*cost  -sclh;
    TestAngleXDa[0] = sclw*cost - sclh*sint  -sclw;
    TestAngleYDa[0] = sclw*sint + sclh*cost  -sclh;
    sc->LHxx2DMVertexBuffer->Unlock();
    }
    memcpy(sc->LHxxAngleXDa,TestAngleXDa,sizeof(TestAngleXDa));
    memcpy(sc->LHxxAngleYDa,TestAngleYDa,sizeof(TestAngleYDa));
    }void ENobject2D::LHxxMOVE_2DIMAGE(char *Tname,float movex,float movey,int mirrorX,int mirrorY)
    {
    TList=ENobject2DListOb.GetNode(Tname);
    LHxx2DIMAGE *sc=TList->ObjectData;
    sc->LHxxIx=movex;
    sc->LHxxIy=movey;
    float h=sc->LHxxIh;//缩放后的大小
    float w=sc->LHxxIw;
    //以中心为图片的位置
    float x=sc->LHxxIx-sc->LHxxIw/2;
    float y=sc->LHxxIy-sc->LHxxIh/2;
    if(mirrorX==1)
    {
    LHxx2DSCREENVERTEX* ss;
    sc->LHxx2DMVertexBuffer->Lock( 0, 0, (void**)&ss, 0 );
    ss[0].LHxxSx=x   +sc->LHxxAngleXDa[0];
    // ss[0].LHxxSy=y   +LHxxAngleYDa[0];
    ss[1].LHxxSx=x+w +sc->LHxxAngleXDa[1];
    // ss[1].LHxxSy=y   +LHxxAngleYDa[1];
    ss[2].LHxxSx=x  +sc->LHxxAngleXDa[2];
    // ss[2].LHxxSy=y+h +LHxxAngleYDa[2];
    ss[3].LHxxSx=x+w+sc->LHxxAngleXDa[3];
    // ss[3].LHxxSy=y+h +LHxxAngleYDa[3];
    sc->LHxx2DMVertexBuffer->Unlock();
    }
    else if(mirrorX==2)
    {
    LHxx2DSCREENVERTEX* ss;
    sc->LHxx2DMVertexBuffer->Lock( 0, 0, (void**)&ss, 0 );
    ss[0].LHxxSx=x +w  +sc->LHxxAngleXDa[0];
    // ss[0].LHxxSy=y   +LHxxAngleYDa[0];
    ss[1].LHxxSx=x +sc->LHxxAngleXDa[1];
    // ss[1].LHxxSy=y   +LHxxAngleYDa[1];
    ss[2].LHxxSx=x +w  +sc->LHxxAngleXDa[2];
    // ss[2].LHxxSy=y+h +LHxxAngleYDa[2];
    ss[3].LHxxSx=x +sc->LHxxAngleXDa[3];
    // ss[3].LHxxSy=y+h +LHxxAngleYDa[3];
    sc->LHxx2DMVertexBuffer->Unlock();
    }
    if(mirrorY==1)
    {
    LHxx2DSCREENVERTEX* ss;
    sc->LHxx2DMVertexBuffer->Lock( 0, 0, (void**)&ss, 0 );
    // ss[0].LHxxSx=x   +LHxxAngleXDa[0];
    ss[0].LHxxSy=y   +sc->LHxxAngleYDa[0];
    // ss[1].LHxxSx=x+w +LHxxAngleXDa[1];
    ss[1].LHxxSy=y   +sc->LHxxAngleYDa[1];
    // ss[2].LHxxSx=x  +LHxxAngleXDa[2];
    ss[2].LHxxSy=y+h +sc->LHxxAngleYDa[2];
    // ss[3].LHxxSx=x+w+LHxxAngleXDa[3];
    ss[3].LHxxSy=y+h +sc->LHxxAngleYDa[3];
    sc->LHxx2DMVertexBuffer->Unlock();
    }
    else if(mirrorY==2)
    {
    LHxx2DSCREENVERTEX* ss;
    sc->LHxx2DMVertexBuffer->Lock( 0, 0, (void**)&ss, 0 );
    // ss[0].LHxxSx=x +w  +LHxxAngleXDa[0];
    ss[0].LHxxSy=y +h  +sc->LHxxAngleYDa[0];
    // ss[1].LHxxSx=x +LHxxAngleXDa[1];
    ss[1].LHxxSy=y +h +sc->LHxxAngleYDa[1];
    // ss[2].LHxxSx=x +w  +LHxxAngleXDa[2];
    ss[2].LHxxSy=y +sc->LHxxAngleYDa[2];
    // ss[3].LHxxSx=x +LHxxAngleXDa[3];
    ss[3].LHxxSy=y +sc->LHxxAngleYDa[3];
    sc->LHxx2DMVertexBuffer->Unlock();
    }
    }
    void ENobject2D::LHxxSCALE_2DIMAGE(char *Tname,float scalex,float scaley,int mirrorX,int mirrorY)
    {
    TList=ENobject2DListOb.GetNode(Tname);
    LHxx2DIMAGE *sc=TList->ObjectData;
    //缩小极限为-0.1
    if(scalex<=-0.1 || scaley<-0.1)
    {
    return;
    }
    //求出缩放差
    float sx=1-scalex;
    float sy=1-scaley;
    if(sx<0)//放大
    {
    sc->LHxxIw=sc->LHxxRw+abs(sc->LHxxRw*sx);
    sc->LHxxScaleOffsetX+=abs(sc->LHxxRw*sx);//计得缩放了多大
    }
    if(sx>0)//缩小
    {
    sc->LHxxIw=sc->LHxxRw-sc->LHxxRw*sx;
    sc->LHxxScaleOffsetX-=abs(sc->LHxxRw*sx);
    }
    if(sy<0)//放大
    {
    sc->LHxxIh=sc->LHxxRh+abs(sc->LHxxRh*sy);
    sc->LHxxScaleOffsetY+=abs(sc->LHxxRh*sy);
    }
    if(sy>0)//缩小
    {
    sc->LHxxIh=sc->LHxxRh-sc->LHxxRh*sy;
    sc->LHxxScaleOffsetY-=abs(sc->LHxxRh*sy);
    }
    //当前缩放倍数
        sc->LHxxScaleX=scalex;
    sc->LHxxScaleY=scaley;
    //将放大的数据过滤
    LHxxROTATE_2DIMAGE(Tname,sc->LHxxAngle,mirrorX,mirrorY);
    }
      

  14.   

    要想速度快,就用并行算法,可以考虑gpu