2017-05-27 81 views
0

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

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

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

+0

@Raw N阱的问题是存在的......你的意思是我的编辑发布以包括答案? – Jim

+0

您想要实施[旋转矩阵](https://www.siggraph.org/education/materials/HyperGraph/modeling/mod_tran/2drota.htm)。大多数图形软件包都有一个矩阵变换库。 – selbie

+1

https://stackoverflow.com/questions/10633400/rotate-bitmap-by-real-angle – selbie

回答

0

你正在此周围做的其他方式,从而可以存在孔在所得图像中,因为你与1个像素步骤循环源像素....补救这个循环中的目标像素,而不是...

  1. 遍历bitmap2像素(x2,y2)
  2. 为旋转回每个计算在bitmap1
  3. 拷贝(x1,y1)位置像素值 如果(x1,y1)位于bitmap1之外,则改为使用类似clBlack的背景色。

为了提高速度使用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