在其中心旋转方形TBitmap

时间:2017-05-27 05:41:02

标签: c++builder tbitmap

我正在尝试找到最简单的方法来旋转并在其中心显示TBitmap所需的任何给定角度。 TBitmap是方形的,只要旋转的位图的中心点保持不变,任何可能发生的剪裁都不重要。图像非常小,只有大约50 x 50像素,因此速度不是问题。这是我到目前为止的代码,它将TBitmap旋转到90度,这很简单,任何角度都不那么重要。

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()); 

请参阅修改后的代码...这允许旋转,但副本会创建模糊图像,旋转点位于左上角。

1 个答案:

答案 0 :(得分:1)

你这样做是相反的,所以在生成的图像中可能存在漏洞,因为你用1像素步长循环源像素....来补救这个循环目标像素而不是......

  1. 循环显示bitmap2像素(x2,y2)
  2. (x1,y1)
  3. 中的每个计算后退bitmap1位置
  4. 复制像素值 if {x1,y1)在bitmap1之外,然后使用像clBlack这样的背景颜色。
  5. 要提高速度使用TBitmap->ScanLine[y]属性,如果使用正确,请至少1000x次提高速度:

    我把所有这些放在一起后得到了这个:

    #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;
        }
    

    用法:

    // 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;
    

    这里的示例输出:

    example

    左侧是bmp1,右侧是bmp2