⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unit1.~pas

📁 使用Delphi实现了对一张图片的几何变换
💻 ~PAS
📖 第 1 页 / 共 2 页
字号:
unit unit1;

interface

uses
   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
   Dialogs, ExtDlgs, Menus, ExtCtrls, ComCtrls, math, ImgList, ToolWin;
type
   TForm1 = class(TForm)
      MainMenu1: TMainMenu;
      N1: TMenuItem;
      N19: TMenuItem;
      N20: TMenuItem;
      OpenPictureDialog1: TOpenPictureDialog;
      SavePictureDialog1: TSavePictureDialog;
      StatusBar1: TStatusBar;
    PopupMenu1: TPopupMenu;
    N90S1: TMenuItem;
    N90N1: TMenuItem;
    N5: TMenuItem;
    N6: TMenuItem;
    I1: TMenuItem;
    O1: TMenuItem;
    N10: TMenuItem;
    N11: TMenuItem;
    N12: TMenuItem;
    N13: TMenuItem;
    N15: TMenuItem;
    V1: TMenuItem;
    Y1: TMenuItem;
    C1: TMenuItem;
    N17: TMenuItem;
    R1: TMenuItem;
    N2: TMenuItem;
    Q1: TMenuItem;
    Image1: TImage;
    procedure N19Click(Sender: TObject);
    procedure N20Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure N90S1Click(Sender: TObject);
    procedure N90N1Click(Sender: TObject);
    procedure N5Click(Sender: TObject);
    procedure I1Click(Sender: TObject);
    procedure O1Click(Sender: TObject);
    procedure N11Click(Sender: TObject);
    procedure N12Click(Sender: TObject);
    procedure N15Click(Sender: TObject);
    procedure V1Click(Sender: TObject);
    procedure Y1Click(Sender: TObject);
    procedure C1Click(Sender: TObject);
    procedure R1Click(Sender: TObject);
    procedure Q1Click(Sender: TObject);
   private
      //定义开始时间和结束时间变量
      BeginTime, EndTime: longint;
      //定义用来保存原始图像的位图对象
      OldBmp: TBitmap;
      //实现远视图效果的函数
      procedure bmp_Tilt(const InBmp, OutBmp: TBitmap;
         const WidthTop, WidthBottom: integer);
      //实现任意角度旋转的功能函数
      procedure bmp_eddy(Oribmp, NewBmp: Tbitmap; angle: extended);
      //实现扭曲效果的函数
      procedure bmp_twist(var Oribmp, NewBmp: TBitmap; Count: integer);
      //实现波浪效果的函数
      procedure bmp_Wave(XDIV, YDIV, RatioVal: Integer);
      //实现缩放的函数
      procedure ZoomInOut(bitmap: TBitmap; m, n: extended);
      { Private declarations }
   public
      { Public declarations }
   end;

var
   Form1: TForm1;



implementation

{$R *.dfm}

//打开位图文件
procedure TForm1.N19Click(Sender: TObject);
begin
  if OpenPictureDialog1.Execute then
    //获取bmp位图文件
    image1.Picture.Bitmap.LoadFromFile(OpenPictureDialog1.FileName)
  else
    exit;
  //将选定的bmp文件指定给OldBmp,以实现还原操作
  OldBmp.Assign(image1.Picture.Bitmap);
end;

//保存位图文件
procedure TForm1.N20Click(Sender: TObject);
begin
   //定义保存图像文件时图像类型为bmp位图文件
   SavePictureDialog1.Filter := '*.bmp|*.bmp';
   if SavePictureDialog1.Execute then
   begin
      //保存文件
      Image1.Picture.Bitmap.SaveToFile(SavePictureDialog1.FileName + '.bmp');
   end;
end;


//窗体创建
procedure TForm1.FormCreate(Sender: TObject);
begin
  //设置Image1的属性
  Image1.AutoSize := True;
  Image1.Stretch := True;
  //创建OldBmp位图对象
  OldBmp := TBitmap.Create;
  //设置打开图像文件时的文件类型
  self.OpenPictureDialog1.Filter := '*.bmp|*.bmp';
end;
//顺时针转90度
procedure TForm1.N90S1Click(Sender: TObject);
var
   i, J: Integer;
   Bmp1, Bmp2: TBitmap;
begin
   //创建Tbitmap对象Bmp1和Bmp2
   Bmp1 := TBitmap.Create;
   Bmp2 := TBitmap.Create;
   //将当前图像指定给Bmp1
   Bmp1.Assign(Image1.Picture.Graphic);
   Bmp2.Height := Image1.Picture.Width;
   Bmp2.Width := Image1.Picture.Height;
   //设定象素的显示颜色素
   Bmp1.PixelFormat := pf24bit;
   Bmp2.PixelFormat := pf24bit;
   //开始计时
   BeginTime := GetTickcount;
   for i := 0 to Image1.Height do
   begin
      for J := 0 to Image1.Width do
      begin
         //象素点颜色赋值
         Bmp2.Canvas.Pixels[(-i + Image1.Height), J] := Bmp1.Canvas.Pixels[J,I];
      end;
   end;
   //获得结束时间
   EndTime := GetTickcount;
   //计算出消耗时间
   self.StatusBar1.simpleText:= '执行时间为:' + inttostr(EndTime - BeginTime) + '毫秒';
   //显示变化后的图片
   Image1.Picture.Bitmap.Assign(Bmp2);
   //释放位图对象
   Bmp1.Free;
   Bmp2.Free;
end;

//逆时针转90度
procedure TForm1.N90N1Click(Sender: TObject);
var
   nIdx, nOfs,x, y, i, iMltplier: integer;
   iWidth, iHeight, iSize, iLineSize: LongInt;
   iBuffer: PChar;
   iLine: PByteArray;
begin
   //设定象素的显示颜色素
   image1.Picture.Bitmap.PixelFormat := pf24bit;
   iMltplier := 3;
   iWidth := image1.Picture.Bitmap.Height;
   iHeight := image1.Picture.Bitmap.Width;
   //设定实际需要内存大小
   iSize := iWidth * iHeight * iMltplier;
   //开始计时
   BeginTime := GetTickcount;
   //开辟内存
   GetMem(iBuffer, iSize);
   try
      //设定内存块iline的长度
      iLineSize := image1.Picture.Bitmap.Width * iMltplier;
      //为iLine分配内存
      GetMem(iLine, iLineSize);
      try
         for y := 0 to image1.Picture.Bitmap.Height - 1 do
         begin
            //进行数据块的移动
            Move(image1.Picture.Bitmap.ScanLine[y]^, iLine^, iLineSize);
            for x := 0 to image1.Picture.Bitmap.Width - 1 do
            begin
               nIdx := ((image1.Picture.Bitmap.Width - 1) - x) * iMltplier;
               nOfs := (x * iWidth * iMltplier) + (y * iMltplier);
               for i := 0 to iMltplier - 1 do
                  Byte(iBuffer[nOfs + i]) := iLine[nIdx + i];
            end;
         end;
         //宽和高交换开始,逆时针旋转
         image1.Picture.Bitmap.Height := iHeight;
         image1.Picture.Bitmap.Width := iWidth;
         for y := 0 to iHeight - 1 do
         begin
            //数据移动
            nOfs := y * iWidth * iMltplier;
            Move((@(iBuffer[nOfs]))^, image1.Picture.Bitmap.ScanLine[y]^, iWidth *
               iMltplier);
         end;
         //获得结束时间
         EndTime := GetTickcount;
         //计算出消耗时间
         self.StatusBar1.simpleText:= '执行时间为:' +
                        inttostr(EndTime - BeginTime) + '毫秒';
      finally
         //释放内存iLine
         FreeMem(iLine, iLineSize);
      end;
   finally
      //释放内存iBuffer
      FreeMem(iBuffer, iSize);
   end;
end;

//任意角度旋转
procedure TForm1.N5Click(Sender: TObject);
var
   bmp1,bmp2: TBitmap;
   angle: integer;
begin
   //创建Tbitmap对象bmp1和Bmp2
   bmp1 := TBitmap.Create;
   bmp2 := TBitmap.Create;
   //变换光标形状
   screen.Cursor := crhourglass;
   //开始计时
   BeginTime := GetTickcount;
   //将当前图像指定给Bmp1
   bmp1.Assign(image1.Picture.Bitmap);
   //弹出输入框,让用户输入需要旋转的角度数值
   angle := strtoint(inputbox('任意角度旋转位图', '请输入旋转的角度', '90'));
   //调用bmp_eddy过程实现旋转操作,旋转后的图像保存在bmp2中
   bmp_eddy(bmp1, bmp2, angle);
   //显示变化后的图片
   image1.picture.Bitmap.Assign(bmp2);
   //恢复屏幕光标形状
   screen.Cursor := crdefault;
   //获得结束时间
   EndTime := GetTickcount;
   //计算出消耗时间
   self.StatusBar1.simpleText:= '执行时间为:' + inttostr(EndTime - BeginTime) + '毫秒';
   //释放位图对象
   bmp1.Free;
   bmp2.Free;
end;

//实现任意角度旋转的功能函数
procedure Tform1.bmp_eddy(OriBmp, NewBmp: 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
   //变换位图的格式
   if OriBmp.Width > OriBmp.Height then
   begin
      NewBmp.width := OriBmp.Width;
      NewBmp.height := OriBmp.Width;
   end
   else
      NewBmp.Width := OriBmp.Height;
   NewBmp.Height := OriBmp.Height;
   //将角度转换为PI值
   angle := (angle / 180) * pi;
   // 计算中心点,可以调整它来获得更好的效果
   c1x := OriBmp.width div 2;
   c1y := OriBmp.height div 2;
   c2x := NewBmp.width div 2;
   c2y := NewBmp.height div 2;
   // 获得需要的步骤数值,存入n
   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 := OriBmp.canvas.pixels[c1x + p1x, c1y + p1y];
         c1 := OriBmp.canvas.pixels[c1x - p1x, c1y - p1y];
         c2 := OriBmp.canvas.pixels[c1x + p1y, c1y - p1x];
         c3 := OriBmp.canvas.pixels[c1x - p1y, c1y + p1x]; 
         NewBmp.Canvas.pixels[c2x + p2x, c2y + p2y] := c0;
         NewBmp.canvas.pixels[c2x - p2x, c2y - p2y] := c1;
         NewBmp.canvas.pixels[c2x + p2y, c2y - p2x] := c2;
         NewBmp.canvas.pixels[c2x - p2y, c2y + p2x] := c3;
      end;
      //加入处理消息的函数,允许用户在运算期间进行其他操作
      application.processmessages;
   end;
end;

//缩小
procedure TForm1.I1Click(Sender: TObject);
begin
   //开始计时
   BeginTime := GetTickcount;
   //调用ZoomInOut实现缩小
   ZoomInOut(image1.Picture.Bitmap, 0.8, 0.8);
   //获得结束时间
   EndTime := GetTickcount;
   //计算出消耗时间
   self.StatusBar1.simpleText:= '执行时间为:' +
                  inttostr(EndTime - BeginTime) + '毫秒';
end;

//放大
procedure TForm1.O1Click(Sender: TObject);
begin
   //开始计时
   BeginTime := GetTickcount;
   //调用ZoomInOut实现放大
   ZoomInOut(image1.Picture.Bitmap, 1.2, 1.2);
   //获得结束时间
   EndTime := GetTickcount;
   //计算出消耗时间
   self.StatusBar1.simpleText:= '执行时间为:' +
                  inttostr(EndTime - BeginTime) + '毫秒';
end;

//实现缩放的函数
procedure TForm1.ZoomInOut(bitmap: TBitmap; m, n: extended);
var
   Mybmp: TBitmap;
begin
   self.DoubleBuffered := True;
   //创建Tbitmap对象mybmp
   Mybmp := TBitmap.Create;
   //取整数
   Mybmp.Width := Trunc(m * Self.Image1.Width);
   Mybmp.Height := Trunc(n * self.Image1.Height);
   image1.Width := Mybmp.Width;
   image1.Height := MyBmp.Height;
   //设置指定设备环境中的位图伸展模式
   SetStretchBltMode(Mybmp.Canvas.Handle, HalfTone);
   //从oldbmp中拷贝图像到mybmp中
   Stretchblt(Mybmp.Canvas.Handle, 0, 0, Mybmp.Width,
      Mybmp.Height, OldBmp.Canvas.Handle, 0, 0, OldBmp.Width,
      OldBmp.Height,SRCCOPY);
   //设定象素的显示颜色素
   Mybmp.PixelFormat := pf24bit;
   //显示变化后的图片
   image1.Picture.Bitmap.Assign(MyBmp);
   //释放位图对象
   MyBmp.Free;
end;

//扭曲效果
procedure TForm1.N11Click(Sender: TObject);
var
   bmp1,bmp2: TBitmap;
   i: integer;
begin
   //若当前无图片,则不做处理
   if self.Image1.Picture.Bitmap.Empty then
   begin
      ShowMessage('请加载图片');
      exit;
   end
   else
      //设定象素的显示颜色素
      self.Image1.Picture.Bitmap.PixelFormat := pf24bit;
   //开始计时
   BeginTime := GetTickCount;
   //设置状态栏显示内容
   statusbar1.simpleText := '';
   //创建Tbitmap对象bmp1
   bmp1 := TBitmap.Create;
   //将当前图像指定给Bmp1
   bmp1.Assign(self.Image1.Picture.Bitmap);
   //创建Tbitmap对象bmp1
   bmp2 := tbitmap.create;
   bmp2.width := bmp1.width;
   bmp2.height := bmp1.height;
   //设定象素的显示颜色素
   bmp2.pixelformat := pf24bit;
   //设定扭曲程度
   i := 100;
   //调用bmp_twist实现扭曲
   bmp_twist(bmp1, bmp2, i);
   //显示变化后的图片
   self.Image1.picture.bitmap.assign(bmp2);
   //释放位图对象
   bmp2.Free;
   bmp1.Free;
   //获得结束时间
   EndTime := GetTickCount;
   //显示消耗时间
   self.StatusBar1.simpleText :=
      '  完成时间: ' + inttostr(EndTime - BeginTime) + '毫秒';
end;

//转换参数值

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -