且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在其中心旋转方形TBitmap

更新时间:2023-02-02 17:41:13

您正以另一种方式进行此操作,因此在生成的图像中可能存在孔洞,因为您正在循环源像素用1像素的步长....来纠正此循环,改为目标像素...


  1. 通过 bitmap2 像素(x2,y2)

  2. bitmap1
  3. 中的旋转后退(x1,y1)位置 复制像素值,如果( x1,y1 )在 bitmap1 之外,则
    >然后使用 clBlack 这样的背景色代替。

要提高速度,请使用 TBitmap-> ScanLine [y] 属性,如果使用的话,速度至少提高了 1000x 倍,请参见:






  • 左边是 bmp1 ,右边是 bmp2


    I am trying to find the simplest way to rotate and display a TBitmap on its center by any given angle needed. The TBitmap is square and any clipping that might occur is not important so long as the rotated bitmap's center point remains constant. The image is very small, only around 50 x 50 pixels so speed isn't an issue. Here is the code I have so far which rotates a TBitmap to 90 degrees, which is simple, the any angle thing less so.

    std::auto_ptr<Graphics::TBitmap> bitmap1(new Graphics::TBitmap);
    std::auto_ptr<Graphics::TBitmap> bitmap2(new Graphics::TBitmap);
    
    bitmap1->LoadFromFile("c:/myimage.bmp");
    bitmap1->Transparent = true;
    bitmap1->TransparentColor = bitmap1->Canvas->Pixels[50][50];
    bitmap2->Width=bitmap1->Height;
    bitmap2->Height=bitmap1->Width;
    double x1 = 0.0;
    double y1 = 0.0;
    
    for (int x = 0;x < bitmap1->Width; x++)
    {
        for(int y = 0;y < bitmap1->Height;y++)
        {
            x1 = std::cos(45.0) * x - std::sin(45.0) * y;
            y1 = sin(45.0) * x + cos(45.0) * y;
    
            bitmap2->Canvas->Pixels[x1][y1] =
            bitmap1->Canvas->Pixels[x][y];
        }
    }
    Form1->Canvas->Draw( 500, 200, bitmap2.get()); 
    

    See revised code... This allows for rotation but the copy creates a hazy image and the rotation point is at the top left.

    you are doing this the other way around so there may be present holes in the resulting image because you are looping the source pixels with 1 pixel step .... to remedy this loop the target pixels instead...

    1. loop through bitmap2 pixels (x2,y2)
    2. for each compute rotated-back (x1,y1) position in bitmap1
    3. copy pixel value if (x1,y1) is outside bitmap1 then use backgroun color like clBlack instead.

    To improve speed use TBitmap->ScanLine[y] property that will improve speed at least 1000x times if used right see:

    After I put all this together I got this:

    #include <math.h> // just for cos,sin
    
    // rotate src around x0,y0 [pixels] by angle [rad] and store result in dst
    void rotate(Graphics::TBitmap *dst,Graphics::TBitmap *src,double x0,double y0,double angle)
        {
        int x,y,xx,yy,xs,ys;
        double s,c,fx,fy;
        // resize dst to the same size as src
        xs=src->Width;
        ys=src->Height;
        dst->SetSize(xs,ys);
        // allow direct pixel access for src
        src->HandleType=bmDIB;
        src->PixelFormat=pf32bit;
        DWORD **psrc=new DWORD*[ys];
        for (y=0;y<ys;y++) psrc[y]=(DWORD*)src->ScanLine[y];
        // allow direct pixel access for dst
        dst->HandleType=bmDIB;
        dst->PixelFormat=pf32bit;
        DWORD **pdst=new DWORD*[ys];
        for (y=0;y<ys;y++) pdst[y]=(DWORD*)dst->ScanLine[y];
        // precompute variables
        c=cos(angle);
        s=sin(angle);
        // loop all dst pixels
        for (y=0;y<ys;y++)
         for (x=0;x<xs;x++)
            {
            // compute position in src
            fx=x;       // convert to double
            fy=y;
            fx-=x0;     // translate to center of rotation
            fy-=y0;
            xx=double(+(fx*c)+(fy*s)+x0);   // rotate and translate back
            yy=double(-(fx*s)+(fy*c)+y0);
            // copy pixels
            if ((xx>=0)&&(xx<xs)&&(yy>=0)&&(yy<ys)) pdst[y][x]=psrc[yy][xx];
             else pdst[y][x]=0; // black
            }
        // free memory
        delete[] psrc;
        delete[] pdst;
        }
    

    usage:

    // init
    Graphics::TBitmap *bmp1,*bmp2;
    bmp1=new Graphics::TBitmap;
    bmp1->LoadFromFile("image.bmp");
    bmp1->HandleType=bmDIB;
    bmp1->PixelFormat=pf32bit;
    bmp2=new Graphics::TBitmap;
    bmp2->HandleType=bmDIB;
    bmp2->PixelFormat=pf32bit;
    
    // rotate
    rotate(bmp2,bmp1,bmp1->Width/2,bmp1->Height/2,25.0*M_PI/180.0);
    // here render bmp2 or whatever
    
    // exit
    delete bmp1;
    delete bmp2;
    

    Here example output:

    On the left is bmp1 and on the right rotated bmp2