在其中心旋转方形TBitmap [英] Rotating a square TBitmap on its center

查看:90
本文介绍了在其中心旋转方形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->画布->像素[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->画布->像素[x1] [y1] =
bitmap1->画布->像素[x] [y];
}
}
Form1-> Canvas-> Draw(500,200,bitmap2.get());

查看修改后的代码...这样可以旋转,但是副本会产生模糊的图像和旋转点在左上方。

解决方案

您正以另一种方式进行此操作,因此在生成的图像中可能存在孔洞,因为您正在循环源像素用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

    这篇关于在其中心旋转方形TBitmap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆