请问我怎么在我的bmp控件中旋转我的bmp图像。(旋转90度,180度等)

解决方案 »

  1.   

    调用方法:
       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.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.
      

  2.   

    调用方法:
       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 
      

  3.   

    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.