调用方法: 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=xcosα-ysinα Y=xsinα+ycosα 例如要把位图顺时针旋转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.htmlTRotateImage 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.
调用方法: 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=xcosα-ysinα Y=xsinα+ycosα 例如要把位图顺时针旋转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
unit Unit1;interfaceuses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, ImgList, ComCtrls;type TDrawingTool = (dtLine, dtRectangle, dtEllipse, dtRoundRect); TNode = Record rectx1 : integer; rectx2 : integer; recty1 : integer; recty2 : integer; name : string; pic : tpicture; //rect : trect; end; TLine =record StartPt,EndPt :TPoint; end; TForm1 = class(TForm) ScrollBox1: TScrollBox; Image1: TImage; TreeView1: TTreeView; ImageList1: TImageList; procedure Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure FormCreate(Sender: TObject); procedure Image1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure TreeView1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure FormClose(Sender: TObject; var Action: TCloseAction); procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); private { Private declarations } pic : tpicture; name : string; drawing,moving,Lining : Boolean; picnode : array of TNode; ArrLine :array of TLine; nodecount,nodeselectNo : integer; LineCount,LineSelectNo :integer; origin, movept :TPoint; DrawingTool: TDrawingTool; procedure DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode); procedure RefreshImage; public { Public declarations } end;var Form1: TForm1;implementation{$R *.DFM}procedure TForm1.RefreshImage; var i :integer; beginend;procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var i : integer; tmprect : trect; begin if button = mbleft then begin if drawing then begin image1.Canvas.Draw(x,y,pic.Graphic); setlength(picNode,nodeCount+1); picnode[nodecount].rectx1 := x; picnode[nodecount].recty1 := y; picnode[nodecount].rectx2 := x + pic.Width; picnode[nodecount].recty2 := y + pic.Height; picnode[nodecount].name := name; picnode[nodecount].pic := tpicture.Create; picnode[nodecount].pic := pic; image1.Canvas.TextOut(picnode[nodecount].rectx1,picnode[nodecount].recty2,picnode[nodecount].name); nodecount := nodecount + 1; drawing := False; end else begin for i := 0 to nodecount do begin tmprect := rect(picnode[i].rectx1,picnode[i].recty1,picnode[i].rectx2,picnode[i].recty2); if ptinrect(tmprect,point(x,y)) then begin moving := true; nodeselectNo := i; break; end; end; end; end else if Button =mbRight then begin for i := 0 to nodecount do begin tmprect := rect(picnode[i].rectx1,picnode[i].recty1,picnode[i].rectx2,picnode[i].recty2); if ptinrect(tmprect,point(x,y)) then begin //moving := true; nodeselectNo := i; DrawingTool :=dtLine; lining :=true; Origin :=point(x,y); MovePt := Origin; break; end; end; end; end;procedure TForm1.FormCreate(Sender: TObject); begin nodecount := 0; LineCount :=0; setlength(picnode,30); drawing := false; moving := false; Lining :=false; end;procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var tmprect : trect; i :integer; CanLine :Boolean; begin CanLine :=False; if button = mbleft then begin if moving then begin tmprect := rect(picnode[nodeselectno].rectx1,picnode[nodeselectno].recty1,picnode[nodeselectno].rectx2,picnode[nodeselectno].recty2); image1.Canvas.FillRect(tmpRect); image1.Canvas.Brush.Color := clWhite; image1.Canvas.TextOut(picnode[nodeselectno].rectx1,picnode[nodeselectno].recty2,' '); image1.Canvas.Draw(x,y,picnode[nodeselectno].pic.Graphic); picnode[nodeselectno].rectx1 := x; picnode[nodeselectno].recty1 := y; picnode[nodeselectno].rectx2 := x + picnode[nodeselectno].pic.Width; picnode[nodeselectno].recty2 := y + picnode[nodeselectno].pic.Height; image1.Canvas.TextOut(picnode[nodeselectno].rectx1,picnode[nodeselectno].recty2,picnode[nodeselectno].name); for i :=0 to Length(ArrLine)-1 do begin if ptInRect(tmpRect,ArrLine[i].StartPt) then begin DrawShape(Point(x,y),ArrLine[i].EndPt,PmCopy); DrawShape(ArrLine[i].StartPt,ArrLine[i].EndPt,pmNotXor); ArrLine[i].StartPt :=Point(x,y); end else if ptInRect(tmpRect,ArrLine[i].EndPt) then begin DrawShape(ArrLine[i].StartPt,Point(x,y),PmCopy); DrawShape(ArrLine[i].StartPt,ArrLine[i].EndPt,pmNotXor); ArrLine[i].EndPt :=Point(x,y); end; end; image1.Refresh; moving := false; end; end else if button =mbRight then begin if lining then begin for i := 0 to nodecount do begin tmprect := rect(picnode[i].rectx1,picnode[i].recty1,picnode[i].rectx2,picnode[i].recty2); if ptinrect(tmprect,point(x,y)) then begin CanLine :=True; break; end; end; if CanLine then begin DrawShape(Origin, Point(X, Y), pmCopy); inc(LineCount); setlength(ArrLine,LineCount); ArrLine[LineCount-1].StartPt :=Origin; ArrLine[LineCount-1].EndPt :=Point(x,y); lining :=false; end else begin DrawShape(Origin,Point(x,y),pmNotXor); lining :=false; end; end; end; end;procedure TForm1.TreeView1MouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); var i : integer; bmp : tbitmap; begin for i := 0 to Treeview1.Items.Count - 1 do begin if Treeview1.Items[i].Selected then begin pic := TPicture.Create; bmp :=TBitmap.Create; ImageList1.GetBitmap(Treeview1.Items[i].ImageIndex,bmp); //SelectIndex := i; pic.Assign(bmp); Drawing :=True; name :=TreeView1.Items[i].Text; bmp.Free; end; end; end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction); var i : integer; begin pic.Free; for i := 0 to nodecount-1 do picnode[nodecount].pic.Free; end;procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); begin if lining then begin DrawShape(Origin, MovePt, pmNotXor); MovePt := Point(X, Y); DrawShape(Origin, MovePt, pmNotXor); end; end;procedure TForm1.DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode); begin with Image1.Canvas do begin Pen.Mode := AMode; case DrawingTool of dtLine: begin Image1.Canvas.MoveTo(TopLeft.X, TopLeft.Y); Image1.Canvas.LineTo(BottomRight.X, BottomRight.Y); end; dtRectangle: Image1.Canvas.Rectangle(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y); dtEllipse: Image1.Canvas.Ellipse(Topleft.X, TopLeft.Y, BottomRight.X, BottomRight.Y); dtRoundRect: Image1.Canvas.RoundRect(TopLeft.X, TopLeft.Y, BottomRight.X, BottomRight.Y, (TopLeft.X - BottomRight.X) div 2, (TopLeft.Y - BottomRight.Y) div 2); end; end; end;end.
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=xcosα-ysinα
Y=xsinα+ycosα
例如要把位图顺时针旋转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.htmlTRotateImage 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.
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=xcosα-ysinα
Y=xsinα+ycosα
例如要把位图顺时针旋转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
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, ImgList, ComCtrls;type
TDrawingTool = (dtLine, dtRectangle, dtEllipse, dtRoundRect);
TNode = Record
rectx1 : integer;
rectx2 : integer;
recty1 : integer;
recty2 : integer;
name : string;
pic : tpicture;
//rect : trect;
end; TLine =record
StartPt,EndPt :TPoint;
end; TForm1 = class(TForm)
ScrollBox1: TScrollBox;
Image1: TImage;
TreeView1: TTreeView;
ImageList1: TImageList;
procedure Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormCreate(Sender: TObject);
procedure Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
private
{ Private declarations }
pic : tpicture;
name : string;
drawing,moving,Lining : Boolean;
picnode : array of TNode;
ArrLine :array of TLine;
nodecount,nodeselectNo : integer;
LineCount,LineSelectNo :integer;
origin, movept :TPoint;
DrawingTool: TDrawingTool;
procedure DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode);
procedure RefreshImage;
public
{ Public declarations }
end;var
Form1: TForm1;implementation{$R *.DFM}procedure TForm1.RefreshImage;
var i :integer;
beginend;procedure TForm1.Image1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
i : integer;
tmprect : trect;
begin
if button = mbleft then
begin
if drawing then
begin
image1.Canvas.Draw(x,y,pic.Graphic);
setlength(picNode,nodeCount+1);
picnode[nodecount].rectx1 := x;
picnode[nodecount].recty1 := y;
picnode[nodecount].rectx2 := x + pic.Width;
picnode[nodecount].recty2 := y + pic.Height;
picnode[nodecount].name := name;
picnode[nodecount].pic := tpicture.Create;
picnode[nodecount].pic := pic;
image1.Canvas.TextOut(picnode[nodecount].rectx1,picnode[nodecount].recty2,picnode[nodecount].name);
nodecount := nodecount + 1;
drawing := False;
end
else
begin
for i := 0 to nodecount do
begin
tmprect := rect(picnode[i].rectx1,picnode[i].recty1,picnode[i].rectx2,picnode[i].recty2);
if ptinrect(tmprect,point(x,y)) then
begin
moving := true;
nodeselectNo := i;
break;
end;
end;
end;
end else if Button =mbRight then
begin
for i := 0 to nodecount do
begin
tmprect := rect(picnode[i].rectx1,picnode[i].recty1,picnode[i].rectx2,picnode[i].recty2);
if ptinrect(tmprect,point(x,y)) then
begin
//moving := true;
nodeselectNo := i;
DrawingTool :=dtLine;
lining :=true;
Origin :=point(x,y);
MovePt := Origin;
break;
end;
end;
end;
end;procedure TForm1.FormCreate(Sender: TObject);
begin
nodecount := 0;
LineCount :=0;
setlength(picnode,30);
drawing := false;
moving := false;
Lining :=false;
end;procedure TForm1.Image1MouseUp(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
tmprect : trect;
i :integer;
CanLine :Boolean;
begin
CanLine :=False;
if button = mbleft then
begin
if moving then
begin
tmprect := rect(picnode[nodeselectno].rectx1,picnode[nodeselectno].recty1,picnode[nodeselectno].rectx2,picnode[nodeselectno].recty2);
image1.Canvas.FillRect(tmpRect);
image1.Canvas.Brush.Color := clWhite;
image1.Canvas.TextOut(picnode[nodeselectno].rectx1,picnode[nodeselectno].recty2,' ');
image1.Canvas.Draw(x,y,picnode[nodeselectno].pic.Graphic);
picnode[nodeselectno].rectx1 := x;
picnode[nodeselectno].recty1 := y;
picnode[nodeselectno].rectx2 := x + picnode[nodeselectno].pic.Width;
picnode[nodeselectno].recty2 := y + picnode[nodeselectno].pic.Height;
image1.Canvas.TextOut(picnode[nodeselectno].rectx1,picnode[nodeselectno].recty2,picnode[nodeselectno].name);
for i :=0 to Length(ArrLine)-1 do
begin
if ptInRect(tmpRect,ArrLine[i].StartPt) then
begin
DrawShape(Point(x,y),ArrLine[i].EndPt,PmCopy);
DrawShape(ArrLine[i].StartPt,ArrLine[i].EndPt,pmNotXor);
ArrLine[i].StartPt :=Point(x,y);
end else if ptInRect(tmpRect,ArrLine[i].EndPt) then
begin
DrawShape(ArrLine[i].StartPt,Point(x,y),PmCopy);
DrawShape(ArrLine[i].StartPt,ArrLine[i].EndPt,pmNotXor);
ArrLine[i].EndPt :=Point(x,y);
end;
end;
image1.Refresh;
moving := false;
end;
end else if button =mbRight then
begin
if lining then
begin
for i := 0 to nodecount do
begin
tmprect := rect(picnode[i].rectx1,picnode[i].recty1,picnode[i].rectx2,picnode[i].recty2);
if ptinrect(tmprect,point(x,y)) then
begin
CanLine :=True;
break;
end;
end;
if CanLine then
begin
DrawShape(Origin, Point(X, Y), pmCopy);
inc(LineCount);
setlength(ArrLine,LineCount);
ArrLine[LineCount-1].StartPt :=Origin;
ArrLine[LineCount-1].EndPt :=Point(x,y);
lining :=false;
end else
begin
DrawShape(Origin,Point(x,y),pmNotXor);
lining :=false;
end;
end;
end;
end;procedure TForm1.TreeView1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
var
i : integer;
bmp : tbitmap;
begin
for i := 0 to Treeview1.Items.Count - 1 do
begin
if Treeview1.Items[i].Selected then
begin
pic := TPicture.Create;
bmp :=TBitmap.Create;
ImageList1.GetBitmap(Treeview1.Items[i].ImageIndex,bmp);
//SelectIndex := i;
pic.Assign(bmp);
Drawing :=True;
name :=TreeView1.Items[i].Text;
bmp.Free;
end;
end;
end;procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
var
i : integer;
begin
pic.Free;
for i := 0 to nodecount-1 do
picnode[nodecount].pic.Free;
end;procedure TForm1.Image1MouseMove(Sender: TObject; Shift: TShiftState; X,
Y: Integer);
begin
if lining then
begin
DrawShape(Origin, MovePt, pmNotXor);
MovePt := Point(X, Y);
DrawShape(Origin, MovePt, pmNotXor);
end;
end;procedure TForm1.DrawShape(TopLeft, BottomRight: TPoint; AMode: TPenMode);
begin
with Image1.Canvas do
begin
Pen.Mode := AMode;
case DrawingTool of
dtLine:
begin
Image1.Canvas.MoveTo(TopLeft.X, TopLeft.Y);
Image1.Canvas.LineTo(BottomRight.X, BottomRight.Y);
end;
dtRectangle: Image1.Canvas.Rectangle(TopLeft.X, TopLeft.Y, BottomRight.X,
BottomRight.Y);
dtEllipse: Image1.Canvas.Ellipse(Topleft.X, TopLeft.Y, BottomRight.X,
BottomRight.Y);
dtRoundRect: Image1.Canvas.RoundRect(TopLeft.X, TopLeft.Y, BottomRight.X,
BottomRight.Y, (TopLeft.X - BottomRight.X) div 2,
(TopLeft.Y - BottomRight.Y) div 2);
end;
end;
end;end.