分享

delphi 图象旋转

 独孤求财 2012-03-12

delphi 图象旋转

时间:2011-5-31来源:yang 作者: peng点击: 24次

--- Delphi中的Image构件可以显示位图,进一步,我们还可以用它完成位图旋转。
---- 把一个点绕原点旋转α角度后,新的坐标位置与原坐标位置的关系是:
X=xcosα-ysinα
Y= xsinα+ycosα
例如要把位图顺时针旋转90度,坐标变换公式为:X=-y Y=x

问题:图形旋转问题? ( 积分:100, 回复:14, 阅读:275 )
分类:图形图象 ( 版主:垃圾清洁工, menxin )  
来自:liyipeng, 时间:2002-10-5 13:09:00, ID:1360379 [显示:小字体 | 大字体]  

如何编程实现,让picturebox中显示的图片可以旋转,比如旋转90度?  


来自:草央包包, 时间:2002-10-5 13:23:00, ID:1360396
用imgedit(activeX 控件)试一下。
 


来自:xyl999, 时间:2002-10-5 13:30:00, ID:1360398
BOOL StretchBlt(

   HDC hdcDest,  // handle of destination device context
   int nXOriginDest,  // x-coordinate of upper-left corner of dest. rect.
   int nYOriginDest,  // y-coordinate of upper-left corner of dest. rect.
   int nWidthDest,  // width of destination rectangle
   int nHeightDest,  // height of destination rectangle
   HDC hdcSrc,  // handle of source device context
   int nXOriginSrc,  // x-coordinate of upper-left corner of source rectangle
   int nYOriginSrc,  // y-coordinate of upper-left corner of source rectangle
   int nWidthSrc,  // width of source rectangle
   int nHeightSrc,  // height of source rectangle
   DWORD dwRop  // raster operation code
  );  
 


来自:诸葛白痴, 时间:2002-10-5 13:44:00, ID:1360411
好多方法,查查别人已经问过的问题  


来自:huazai, 时间:2002-10-5 14:19:00, ID:1360428
procedure ImageRotate90(aBitmap: TBitmap); //逆时针旋转90,速度很快
  nIdx, nOfs,
     x, y, i, nMultiplier: integer;
  nMemWidth, nMemHeight, nMemSize, nScanLineSize: LongInt;
  aScnLnBuffer: PChar;
  aScanLine: PByteArray;
begin
  nMultiplier := GetPixelSize(ABitmap);
  nMemWidth := aBitmap.Height;
  nMemHeight := aBitmap.Width;
  nMemSize := nMemWidth * nMemHeight * nMultiplier;
  GetMem(aScnLnBuffer, nMemSize);
  try
     nScanLineSize := aBitmap.Width * nMultiplier;
     GetMem(aScanLine, nScanLineSize);
     try
        for y := 0 to aBitmap.Height - 1 do
           begin
              Move(aBitmap.ScanLine[y]^, aScanLine^, nScanLineSize);
              for x := 0 to aBitmap.Width - 1 do
                 begin
                    nIdx := ((aBitmap.Width - 1) - x) * nMultiplier;
                    nOfs := (x * nMemWidth * nMultiplier) + (y * nMultiplier);
                    for i := 0 to nMultiplier - 1 do
                       Byte(aScnLnBuffer[nOfs + i]) := aScanLine[nIdx + i];
                 end;
           end;
        aBitmap.Height := nMemHeight; //¿íºÍ¸ß½»»»¿ªÊ¼ÄæʱÕëÐýת
        aBitmap.Width := nMemWidth;
        for y := 0 to nMemHeight - 1 do
           begin
              nOfs := y * nMemWidth * nMultiplier;
              Move((@(aScnLnBuffer[nOfs]))^, aBitmap.ScanLine[y]^, nMemWidth *
                 nMultiplier);
           end;
     finally
        FreeMem(aScanLine, nScanLineSize);
     end;
  finally
     FreeMem(aScnLnBuffer, nMemSize);
  end;
end;  


来自:liyipeng, 时间:2002-10-6 17:34:00, ID:1361557
huazai你好,我是个delphi的初学者,所以还有点问题问问你,就是你的旋转函数,
能不能告诉一下如何调用执行。比如在一个窗体上放置一个image控件后,如何设置属
性,如何使用你的函数等等,谢谢!  


来自:huazai, 时间:2002-10-6 18:00:00, ID:1361572
childform.Image1.Picture.Bitmap.PixelFormat := pf24bit;
ImageRotate90(childform.Image1.Picture.Bitmap);
这样就可以了,给分吧  


来自:chuguozhen, 时间:2002-10-6 21:06:00, ID:1361734
procedure TForm1.BitBtn1Click(Sender: TObject);//90度
var
color:TColor;
i,j:integer;
begin
   Image2.Width:=Image1.Height;
   Image2.Height:=Image1.Width;
   for i:=0 to Image1.Width do
   for j:=0 to Image1.Height do
     begin
         Image2.Canvas.Pixels[j,i]:=Image1.Canvas.Pixels[i,j];
     end;
end;

procedure TForm1.BitBtn2Click(Sender: TObject);//180度
var
color:TColor;
i,j:integer;
begin
   Image2.Height:=Image1.Height;
   Image2.Width:=Image1.Width;
   for i:=0 to Image1.Width do
   for j:=0 to Image1.Height do
     begin
         Image2.Canvas.Pixels[i,Image2.Height-j]:=Image1.Canvas.Pixels[i,j];
     end;
end;
任意角度的旋转,需要做数据变换,数学基本知识,以上两个只是演示,速度很慢,较快的办法不用Image,而是使用TBitmap,也就是先建立临时Bitmap,  


来自:huazai, 时间:2002-10-6 22:10:00, ID:1361813
我有任意角旋转的代码,比较简单,我得email:huazai@zju.edu.cn  


来自:wangzheking, 时间:2003-4-11 15:33:00, ID:1759773
huazai,能不能給我一份任意角度旋轉的代碼,Donald_sh@etang.com,謝謝  


来自:hdfsun, 时间:2003-4-13 23:15:00, ID:1765386
我给你一份任意角度旋轉的代碼,别忘了加分哦!

//旋转90度
procedure Rotate90(const Bitmap:TBitmap);
var
 i,j:Integer;
 rowIn,rowOut:pRGBTriple;
 Bmp:TBitmap;
 Width,Height:Integer;
begin
 Bmp:=TBitmap.Create;
 Bmp.Width := Bitmap.Height;
 Bmp.Height := Bitmap.Width;
 Bmp.PixelFormat := pf24bit;
 Width:=Bitmap.Width-1;
 Height:=Bitmap.Height-1;
 for  j := 0 to Height do
 begin
   rowIn  := Bitmap.ScanLine[j];
   for i := 0 to Width do
   begin
     rowOut := Bmp.ScanLine[i];
     Inc(rowOut,Height - j);
     rowOut^ := rowIn^;
     Inc(rowIn);
   end;
 end;
 Bitmap.Assign(Bmp);
end;

//旋转180度
procedure Rotate180(const Bitmap:TBitmap);
var
 i,j:Integer;
 rowIn,rowOut:pRGBTriple;
 Bmp:TBitmap;
 Width,Height:Integer;
begin
 Bmp:=TBitmap.Create;
 Bmp.Width := Bitmap.Width;
 Bmp.Height := Bitmap.Height;
 Bmp.PixelFormat := pf24bit;
 Width:=Bitmap.Width-1;
 Height:=Bitmap.Height-1;
 for  j := 0 to Height do
 begin
   rowIn  := Bitmap.ScanLine[j];
   for i := 0 to Width do
   begin
     rowOut := Bmp.ScanLine[Height - j];
     Inc(rowOut,Width - i);
     rowOut^ := rowIn^;
     Inc(rowIn);
   end;
 end;
 Bitmap.Assign(Bmp);
end;

//旋转270度
procedure Rotate270(const Bitmap:TBitmap);
var
 i,j:Integer;
 rowIn,rowOut:pRGBTriple;
 Bmp:TBitmap;
 Width,Height:Integer;
begin
 Bmp:=TBitmap.Create;
 Bmp.Width := Bitmap.Height;
 Bmp.Height := Bitmap.Width;
 Bmp.PixelFormat := pf24bit;
 Width:=Bitmap.Width-1;
 Height:=Bitmap.Height-1;
 for  j := 0 to Height do
 begin
   rowIn  := Bitmap.ScanLine[j];
   for i := 0 to Width do
   begin
     rowOut := Bmp.ScanLine[Width - i];
     Inc(rowOut,j);
     rowOut^ := rowIn^;
     Inc(rowIn);
   end;
 end;
 Bitmap.Assign(Bmp);
end;

前面为判断部分,如果是90,180,270这类特殊角度,将调用上面的代码,这样效率更高!

//任意角度
function RotateBitmap(Bitmap:TBitmap;Angle:Integer;BackColor:TColor):TBitmap;
var
 i,j,iOriginal,jOriginal,CosPoint,SinPoint : integer;
 RowOriginal,RowRotated : pRGBTriple;
 SinTheta,CosTheta : Extended;
 AngleAdd : integer;
begin
 Result:=TBitmap.Create;
 Result.PixelFormat := pf24bit;
 Result.Canvas.Brush.Color:=BackColor;
 Angle:=Angle Mod 360;
 if Angle<0 then Angle:=360-Abs(Angle);
 if Angle=0 then
   Result.Assign(Bitmap)
 else if Angle=90 then
 begin
   Result.Assign(Bitmap);
   Rotate90(Result);//如果是旋转90度,直接调用上面的代码
 end
 else if (Angle>90) and (Angle<180) then
 begin
   AngleAdd:=90;
   Angle:=Angle-AngleAdd;
 end
 else if Angle=180 then
 begin
   Result.Assign(Bitmap);
   Rotate180(Result);//如果是旋转180度,直接调用上面的过程
 end
 else if (Angle>180) and (Angle<270) then
 begin
   AngleAdd:=180;
   Angle:=Angle-AngleAdd;
 end
 else if Angle=270 then
 begin
   Result.Assign(Bitmap);
   Rotate270(Result);//如果是旋转270度,直接调用上面的过程
 end
 else if (Angle>270) and (Angle<360) then
 begin
   AngleAdd:=270;
   Angle:=Angle-AngleAdd;
 end
 else
   AngleAdd:=0;
 if (Angle>0) and (Angle<90) then
 begin
 SinCos((Angle + AngleAdd) * Pi / 180, SinTheta, CosTheta);
 if (SinTheta * CosTheta) < 0 then
 begin
   Result.Width := Round(Abs(Bitmap.Width * CosTheta - Bitmap.Height * SinTheta));
   Result.Height := Round(Abs(Bitmap.Width * SinTheta - Bitmap.Height * CosTheta));
 end
 else
 begin
   Result.Width := Round(Abs(Bitmap.Width * CosTheta + Bitmap.Height * SinTheta));
   Result.Height := Round(Abs(Bitmap.Width * SinTheta + Bitmap.Height * CosTheta));
 end;
 CosTheta:=Abs(CosTheta);
 SinTheta:=Abs(SinTheta);
 if (AngleAdd=0) or (AngleAdd=180) then
 begin
   CosPoint:=Round(Bitmap.Height*CosTheta);
   SinPoint:=Round(Bitmap.Height*SinTheta);
 end
 else
 begin
   SinPoint:=Round(Bitmap.Width*CosTheta);
   CosPoint:=Round(Bitmap.Width*SinTheta);
 end;
 for j := 0 to Result.Height-1 do
 begin
   RowRotated := Result.Scanline[j];
   for i := 0 to Result.Width-1 do
   begin
     Case AngleAdd of
       0:
       begin
         jOriginal := Round((j+1)*CosTheta-(i+1-SinPoint)*SinTheta)-1;
         iOriginal := Round((i+1)*CosTheta-(CosPoint-j-1)*SinTheta)-1;
       end;
       90:
       begin
         iOriginal := Round((j+1)*SinTheta-(i+1-SinPoint)*CosTheta)-1;
         jOriginal := Bitmap.Height-Round((i+1)*SinTheta-(CosPoint-j-1)*CosTheta);
       end;
       180:
       begin
         jOriginal := Bitmap.Height-Round((j+1)*CosTheta-(i+1-SinPoint)*SinTheta);
         iOriginal := Bitmap.Width-Round((i+1)*CosTheta-(CosPoint-j-1)*SinTheta);
       end;
       270:
       begin
         iOriginal := Bitmap.Width-Round((j+1)*SinTheta-(i+1-SinPoint)*CosTheta);
         jOriginal := Round((i+1)*SinTheta-(CosPoint-j-1)*CosTheta)-1;
       end;
     end;
     if (iOriginal >= 0) and (iOriginal <= Bitmap.Width-1)and
        (jOriginal >= 0) and (jOriginal <= Bitmap.Height-1)
     then
     begin
       RowOriginal := Bitmap.Scanline[jOriginal];
       Inc(RowOriginal,iOriginal);
       RowRotated^ := RowOriginal^;
       Inc(RowRotated);
     end
     else
     begin
       Inc(RowRotated);
     end;
   end;
 end;
 end;
end;



 


来自:zbsfg, 时间:2003-9-22 11:14:00, ID:2191819
function RotateBitmap(Bitmap:TBitmap;Angle:Integer;BackColor:TColor):TBitmap;
好像有问题  


来自:billy_phd, 时间:2003-9-26 20:08:00, ID:2202631
这是一段可以旋转任意角度的代码:
///////////////////////////////// /
////// designed by billy_phd /////
//////////////////////////////////
unit urotate;

interface

uses
 Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
 Dialogs, ExtCtrls, StdCtrls, Spin;

type
 Trgbarray = array[0..32767]of trgbtriple;
 prgbarray=^Trgbarray;

 TForm1 = class(TForm)
   Button1: TButton;
   Image1: TImage;
   OpenDialog1: TOpenDialog;
   SpinEdit1: TSpinEdit;
   SpinEdit2: TSpinEdit;
   Image2: TImage;
   procedure Button1Click(Sender: TObject);
   procedure rotatebitmap;
   procedure SpinEdit1Change(Sender: TObject);
   procedure SpinEdit2Change(Sender: TObject);
 private
   { Private declarations }
   rotatedbitmap:tbitmap;
   sourcebitmap:tbitmap;
 public
   { Public declarations }
 end;

var
 Form1: TForm1;

implementation

{$R *.dfm}
procedure tform1.rotatebitmap;
var rowrotated,roworiginal:prgbarray;
   i,j,ioriginal,joriginal,jprime,iprime:integer;
   sinthed,costhed:double;
   thed:double;
begin
 rotatedbitmap:=tbitmap.Create;
 rotatedbitmap.Width:=sourcebitmap.Width;
 rotatedbitmap.Height:=sourcebitmap.Height;
 rotatedbitmap.PixelFormat:=pf24bit;

 thed:=-(spinedit1.Value+spinedit2.Value/100)*pi/180;
 sinthed:=sin(thed);
 costhed:=cos(thed);

 //through my test if i use :for j:=rotatedbitmap.height-1 downto 0 do ;has the
 //same result;
 for j:=0 to rotatedbitmap.Height-1  do
 begin
  rowrotated:=rotatedbitmap.ScanLine[j];
  jprime:=2*j+1;
  for i:=0 to rotatedbitmap.Width-1  do
  begin
   iprime:=2*i+1;

   //if ioriginal:=-(round(iprime*costhed-jprime*sinthed)-1) div 2 ;
   //joriginal:=(round(jprime*costhed+iprime*sinthed)-1) div 2 ;we
   //can get another graphics,so we can change the diaplay of rotation
   //by choosing the proper mathematical function
   
   ioriginal:=(round(iprime*costhed-jprime*sinthed)-1) div 2;
   joriginal:=(round(jprime*costhed+iprime*sinthed)-1) div 2 ;

   if (ioriginal>=0) and (ioriginal<=rotatedbitmap.Width-1) and(joriginal>=0) and(joriginal<=rotatedbitmap.Height-1)
   then begin
       roworiginal:=sourcebitmap.ScanLine[joriginal];
       rowrotated[i]:=roworiginal[ioriginal];
       end
   else
   begin
      rowrotated[i].rgbtBlue:=255;
      rowrotated[i].rgbtGreen:=0;
      rowrotated[i].rgbtRed:=0;
   end;
   end;
  end;
 image1.Picture.Graphic:=rotatedbitmap;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
sourcebitmap:=tbitmap.Create;
if opendialog1.Execute then
  sourcebitmap.LoadFromFile(opendialog1.FileName);
  image2.Picture.Graphic:=sourcebitmap;
  rotatebitmap;

end;

procedure TForm1.SpinEdit1Change(Sender: TObject);
begin
 rotatebitmap;
end;

procedure TForm1.SpinEdit2Change(Sender: TObject);
begin
  rotatebitmap;
end;

end.
 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多