首页  编辑  

Image 任意角度的旋转

Tags: /超级猛料/Picture.图形图像编程/控件和绘图/   Date Created:

调用方法:

  bmp_rotate(Image1.Picture.Bitmap, Image2.Picture.Bitmap, RAngle);

procedure TfrmColor.bmp_rotate(src,dst:tbitmap;angle:extended);

var

 c1x,c1y,c2x,c2y:integer;

 p1x,p1y,p2x,p2y:integer;

 radius,n:integer;

 alpha:extended;

 c0,c1,c2,c3:tcolor;

begin

  //将角度转换为PI值

 angle := (angle / 180) * pi;

  // 计算中心点,你可以修改它

 c1x := src.width div 2;

 c1y := src.height div 2;

 c2x := dst.width div 2;

 c2y := dst.height div 2;  

  // 步骤数值number

 if c2x < c2y then

   n := c2y

 else

   n := c2x;

 dec (n,1);

  // 开始旋转

 for p2x := 0 to n do begin

   for p2y := 0 to n do begin

     if p2x = 0 then

       alpha:= pi/2

     else

       alpha := arctan2(p2y,p2x);

     radius := round(sqrt((p2x*p2x)+(p2y*p2y)));

     p1x := round(radius * cos(angle+alpha));

     p1y := round(radius * sin(angle+alpha));

           

     c0 := src.canvas.pixels[c1x+p1x,c1y+p1y];

     c1 := src.canvas.pixels[c1x-p1x,c1y-p1y];

     c2 := src.canvas.pixels[c1x+p1y,c1y-p1x];

     c3 := src.canvas.pixels[c1x-p1y,c1y+p1x];

     dst.canvas.pixels[c2x+p2x,c2y+p2y]:=c0;

     dst.canvas.pixels[c2x-p2x,c2y-p2y]:=c1;

     dst.canvas.pixels[c2x+p2y,c2y-p2x]:=c2;

     dst.canvas.pixels[c2x-p2y,c2y+p2x]:=c3;

   end;

   application.processmessages

 end;

end;

*************8

----把一个点绕原点旋转 α 角度后,新的坐标位置与原坐标位置的

关系是:

X=xcos α -ysin α

Y=x sin α +ycos α

例如要把位图顺时针旋转90度,坐标变换公式为:X=-yY=x

----把这一公式用到Image构件上,显示位图的主要问题是Image构

件显示的位图只有一个象限,并且x、y坐标也是互相颠倒的,为了

解决这个问题,必须在Image构件上建立一个新的坐标原点。下面就

举例说明。

----1.新建一工程project1,在form1上添加image1、image2、

image3、image4,其Autosize属性设为True,image1用来显示原

图,image2、image3、image4分别用来显示旋转90度、180度和270

度后的图像。双击image1,选定一幅bmp图。

----2.添加Button1、Button2、Button3和Button4按钮,其

caption属性分别为"原图"、"旋转90度"、"旋转180度"、

"旋转270度"。

----3.编写"旋转90度"按钮的OnClick事件。

procedureTForm1.Button2Click(Sender:TObject);

var

i,j:integer;

begin

//确定旋转后位图的大小

image2.Picture.Bitmap.Height:=image1.picture.width;

image2.Picture.Bitmap.Width:=image1.picture.height;

fori:=0toimage1.Heightdo

forj:=0toimage1.Widthdo

image2.canvas.Pixels[(-i+image1.Height),

j]:=image1.canvas.Pixels[j,i];

end;

----4.编写"旋转180度"按钮的OnClick事件。

procedureTForm1.Button3Click(Sender:TObject);

var

i,j:integer;

begin

//确定旋转后位图的大小

image3.Picture.Bitmap.Height:=image1.picture.Height;

image3.Picture.Bitmap.Width:=image1.picture.Width;

fori:=0toimage1.Heightdo

forj:=0toimage1.Widthdo

image3.canvas.Pixels[(image1.Width

-j),(image1.Height-i)]:=image1.canvas.Pixels[j,i];

end;

----5.编写"旋转270度"按钮的OnClick事件。代码和步骤3相

似,只需要用image4替换image2,然后用以下的语句替换步骤3for

循环中的原有的语句。

image4.canvas.Pixels[i,(image1.Width-j)]:=image1.canvas.Pixels[j,i];

procedure Rotate(Bmp,Dst:TFastRGB;cx,cy:Integer;Angle:Extended);

var

cAngle,

sAngle:  Double;

xDiff,

yDiff,

xpr,ypr,

ix,iy,

px,py,

x,y:      Integer;

Tmp:      PFColor;{what means?}

begin

 Angle:=-Angle*Pi/180;

 sAngle:=Sin(Angle);

 cAngle:=Cos(Angle);

 xDiff:=(Dst.Width-Bmp.Width)div 2;

 yDiff:=(Dst.Height-Bmp.Height)div 2;

 Tmp:=Dst.Bits;{what means?}

 for y:=0 to Dst.Height-1 do

 begin

   py:=2*(y-cy)+1;

   for x:=0 to Dst.Width-1 do

   begin

     px:=2*(x-cx)+1;

     xpr:=Round(px*cAngle-py*sAngle);

     ypr:=Round(px*sAngle+py*cAngle);

     ix:=((xpr-1)div 2+cx)-xDiff;

     iy:=((ypr-1)div 2+cy)-yDiff;

     if(ix>-1)and(ix<Bmp.Width)and(iy>-1)and(iy<Bmp.Height)then

     Tmp^:=Bmp.Pixels[iy,ix]; {what means?}

     Inc(Tmp);

   end;

   Tmp:=Pointer(Integer(Tmp)+Dst.Gap); {what means?}

 end;

end;

原理:

                   cos(Alpha), sin(Alpha), 0  

只需要用源矩阵乘以  -sin(Alpha),cos(Alpha), 0

                   0, 0, 1

如果你发现转过来的图形带有很整齐的花点,解决的办法是反向计算,即从目标求的源点的坐标和像素值。

以上的例子就是这样的。

如果真的按下面下矩阵计算每个点,目标区有一些点会是白点(因为有些源点通过计算和四舍五入在目标中凑到一起了),我以前解决的办法是从目标求的源点的坐标和像素值,不过首先要取到目标区的区域(往往是斜的)。

                   cos(Alpha), sin(Alpha), 0  

                   -sin(Alpha),cos(Alpha), 0

                   0, 0, 1

下载我说的控件吗,有现成的例子及DEMO!

http://www.crosswinds.net/~khojasteh/delphi-components.html

TRotateImage v1.21  

 This component is a visual component similar to TImage with ability to rotate the image in any arbitrary angle. TRotateImage can be used on Delphi 3, 4, and 5.